react-native-country-select 0.3.0 → 0.3.2
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 +71 -47
- package/lib/components/AlphabeticFilter/index.tsx +21 -14
- package/lib/components/BottomSheetModal/index.tsx +2 -4
- package/lib/components/CloseButton/index.tsx +11 -7
- package/lib/components/CountryItem/index.tsx +17 -9
- package/lib/components/CountrySelect/index.tsx +37 -23
- package/lib/components/SearchInput/index.tsx +7 -5
- package/lib/interface/alfabeticFilterProps.ts +5 -4
- package/lib/interface/closeButtonProps.ts +4 -3
- package/lib/interface/countryItemProps.ts +5 -4
- package/lib/interface/countrySelectProps.ts +8 -7
- package/lib/interface/searchInputProps.ts +4 -3
- package/package.json +1 -1
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 Country Picker and Select Lib preview">
|
|
4
|
+
<img src="https://astroonauta.github.io/react-native-country-select/lib/assets/images/preview.png" alt="React Native Country Picker and Select Lib preview">
|
|
5
5
|
</div>
|
|
6
6
|
|
|
7
7
|
<br>
|
|
@@ -123,8 +123,8 @@ npx react-native-asset
|
|
|
123
123
|
- Class Component
|
|
124
124
|
|
|
125
125
|
```jsx
|
|
126
|
-
import React, {Component} from 'react';
|
|
127
|
-
import {Text, TouchableOpacity, View} from 'react-native';
|
|
126
|
+
import React, { Component } from 'react';
|
|
127
|
+
import { Text, TouchableOpacity, View } from 'react-native';
|
|
128
128
|
import CountrySelect from 'react-native-country-select';
|
|
129
129
|
|
|
130
130
|
export default class App extends Component {
|
|
@@ -138,14 +138,16 @@ export default class App extends Component {
|
|
|
138
138
|
};
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
handleCountrySelect = country => {
|
|
142
|
-
this.setState({country});
|
|
141
|
+
handleCountrySelect = (country) => {
|
|
142
|
+
this.setState({ country });
|
|
143
143
|
};
|
|
144
144
|
|
|
145
145
|
render() {
|
|
146
146
|
return (
|
|
147
|
-
<View style={{flex: 1}}>
|
|
148
|
-
<TouchableOpacity
|
|
147
|
+
<View style={{ flex: 1 }}>
|
|
148
|
+
<TouchableOpacity
|
|
149
|
+
onPress={() => this.setState({ showPicker: true })}
|
|
150
|
+
>
|
|
149
151
|
<Text>Select Country</Text>
|
|
150
152
|
</TouchableOpacity>
|
|
151
153
|
<Text>
|
|
@@ -155,7 +157,7 @@ export default class App extends Component {
|
|
|
155
157
|
|
|
156
158
|
<CountrySelect
|
|
157
159
|
visible={this.state.showPicker}
|
|
158
|
-
onClose={() => this.setState({showPicker: false})}
|
|
160
|
+
onClose={() => this.setState({ showPicker: false })}
|
|
159
161
|
onSelect={this.handleCountrySelect}
|
|
160
162
|
/>
|
|
161
163
|
</View>
|
|
@@ -169,8 +171,8 @@ export default class App extends Component {
|
|
|
169
171
|
- Function Component
|
|
170
172
|
|
|
171
173
|
```jsx
|
|
172
|
-
import React, {useState} from 'react';
|
|
173
|
-
import {Text, TouchableOpacity, View} from 'react-native';
|
|
174
|
+
import React, { useState } from 'react';
|
|
175
|
+
import { Text, TouchableOpacity, View } from 'react-native';
|
|
174
176
|
|
|
175
177
|
import CountrySelect from 'react-native-country-select';
|
|
176
178
|
|
|
@@ -178,7 +180,7 @@ export default function App() {
|
|
|
178
180
|
const [showPicker, setShowPicker] = useState(false);
|
|
179
181
|
const [selectedCountry, setSelectedCountry] = useState(null);
|
|
180
182
|
|
|
181
|
-
const handleCountrySelect = country => {
|
|
183
|
+
const handleCountrySelect = (country) => {
|
|
182
184
|
setSelectedCountry(country);
|
|
183
185
|
};
|
|
184
186
|
|
|
@@ -186,12 +188,14 @@ export default function App() {
|
|
|
186
188
|
<View
|
|
187
189
|
style={{
|
|
188
190
|
flex: 1,
|
|
189
|
-
}}
|
|
191
|
+
}}
|
|
192
|
+
>
|
|
190
193
|
<TouchableOpacity onPress={() => setShowPicker(true)}>
|
|
191
194
|
<Text>Select Country</Text>
|
|
192
195
|
</TouchableOpacity>
|
|
193
196
|
<Text>
|
|
194
|
-
Country:
|
|
197
|
+
Country:{' '}
|
|
198
|
+
{`${selectedCountry?.name?.common} (${selectedCountry?.cca2})`}
|
|
195
199
|
</Text>
|
|
196
200
|
|
|
197
201
|
<CountrySelect
|
|
@@ -209,14 +213,15 @@ export default function App() {
|
|
|
209
213
|
- Typescript
|
|
210
214
|
|
|
211
215
|
```tsx
|
|
212
|
-
import React, {useState} from 'react';
|
|
213
|
-
import {Text, TouchableOpacity, View} from 'react-native';
|
|
216
|
+
import React, { useState } from 'react';
|
|
217
|
+
import { Text, TouchableOpacity, View } from 'react-native';
|
|
214
218
|
|
|
215
|
-
import CountrySelect, {ICountry} from 'react-native-country-select';
|
|
219
|
+
import CountrySelect, { ICountry } from 'react-native-country-select';
|
|
216
220
|
|
|
217
221
|
export default function App() {
|
|
218
222
|
const [showPicker, setShowPicker] = useState<boolean>(false);
|
|
219
|
-
const [selectedCountry, setSelectedCountry] =
|
|
223
|
+
const [selectedCountry, setSelectedCountry] =
|
|
224
|
+
useState<ICountry | null>(null);
|
|
220
225
|
|
|
221
226
|
const handleCountrySelect = (country: ICountry) => {
|
|
222
227
|
setSelectedCountry(country);
|
|
@@ -226,12 +231,14 @@ export default function App() {
|
|
|
226
231
|
<View
|
|
227
232
|
style={{
|
|
228
233
|
flex: 1,
|
|
229
|
-
}}
|
|
234
|
+
}}
|
|
235
|
+
>
|
|
230
236
|
<TouchableOpacity onPress={() => setShowPicker(true)}>
|
|
231
237
|
<Text>Select Country</Text>
|
|
232
238
|
</TouchableOpacity>
|
|
233
239
|
<Text>
|
|
234
|
-
Country:
|
|
240
|
+
Country:{' '}
|
|
241
|
+
{`${selectedCountry?.name?.common} (${selectedCountry?.cca2})`}
|
|
235
242
|
</Text>
|
|
236
243
|
|
|
237
244
|
<CountrySelect
|
|
@@ -249,14 +256,16 @@ export default function App() {
|
|
|
249
256
|
- Multi Select Country
|
|
250
257
|
|
|
251
258
|
```tsx
|
|
252
|
-
import React, {useState} from 'react';
|
|
253
|
-
import {Text, TouchableOpacity, View} from 'react-native';
|
|
259
|
+
import React, { useState } from 'react';
|
|
260
|
+
import { Text, TouchableOpacity, View } from 'react-native';
|
|
254
261
|
|
|
255
|
-
import CountrySelect, {ICountry} from 'react-native-country-select';
|
|
262
|
+
import CountrySelect, { ICountry } from 'react-native-country-select';
|
|
256
263
|
|
|
257
264
|
export default function App() {
|
|
258
265
|
const [showPicker, setShowPicker] = useState<boolean>(false);
|
|
259
|
-
const [selectedCountries, setSelectedCountries] = useState<
|
|
266
|
+
const [selectedCountries, setSelectedCountries] = useState<
|
|
267
|
+
ICountry[]
|
|
268
|
+
>([]);
|
|
260
269
|
|
|
261
270
|
const handleCountrySelect = (countries: ICountry[]) => {
|
|
262
271
|
setSelectedCountries(countries);
|
|
@@ -266,7 +275,8 @@ export default function App() {
|
|
|
266
275
|
<View
|
|
267
276
|
style={{
|
|
268
277
|
flex: 1,
|
|
269
|
-
}}
|
|
278
|
+
}}
|
|
279
|
+
>
|
|
270
280
|
<TouchableOpacity onPress={() => setShowPicker(true)}>
|
|
271
281
|
<Text>Select Countries</Text>
|
|
272
282
|
</TouchableOpacity>
|
|
@@ -288,26 +298,33 @@ export default function App() {
|
|
|
288
298
|
|
|
289
299
|
### Modal Styles ([modalStyles](https://github.com/AstrOOnauta/react-native-country-select/blob/main/lib/interface/countrySelectStyles.ts))
|
|
290
300
|
|
|
291
|
-
| Property
|
|
292
|
-
|
|
|
293
|
-
| `backdrop`
|
|
294
|
-
| `container`
|
|
295
|
-
| `content`
|
|
296
|
-
| `dragHandleContainer`
|
|
297
|
-
| `dragHandleIndicator`
|
|
298
|
-
| `searchContainer`
|
|
299
|
-
| `searchInput`
|
|
300
|
-
| `list`
|
|
301
|
-
| `countryItem`
|
|
302
|
-
| `flag`
|
|
303
|
-
| `countryInfo`
|
|
304
|
-
| `callingCode`
|
|
305
|
-
| `countryName`
|
|
306
|
-
| `sectionTitle`
|
|
307
|
-
| `closeButton`
|
|
308
|
-
| `closeButtonText`
|
|
309
|
-
| `countryNotFoundContainer`
|
|
310
|
-
| `countryNotFoundMessage`
|
|
301
|
+
| Property | Type | Description |
|
|
302
|
+
| ---------------------------- | --------- | ------------------------- |
|
|
303
|
+
| `backdrop` | ViewStyle | Modal background overlay |
|
|
304
|
+
| `container` | ViewStyle | Modal main container |
|
|
305
|
+
| `content` | ViewStyle | Modal content area |
|
|
306
|
+
| `dragHandleContainer` | ViewStyle | Drag Handle area |
|
|
307
|
+
| `dragHandleIndicator` | ViewStyle | Drag Handle Indicator |
|
|
308
|
+
| `searchContainer` | ViewStyle | Search input wrapper |
|
|
309
|
+
| `searchInput` | TextStyle | Search input field |
|
|
310
|
+
| `list` | ViewStyle | Countries list container |
|
|
311
|
+
| `countryItem` | ViewStyle | Individual country row |
|
|
312
|
+
| `flag` | TextStyle | Country flag in list |
|
|
313
|
+
| `countryInfo` | ViewStyle | Country details container |
|
|
314
|
+
| `callingCode` | TextStyle | Calling code in list |
|
|
315
|
+
| `countryName` | TextStyle | Country name in list |
|
|
316
|
+
| `sectionTitle` | TextStyle | Section headers |
|
|
317
|
+
| `closeButton` | ViewStyle | Close button container |
|
|
318
|
+
| `closeButtonText` | TextStyle | Close button text |
|
|
319
|
+
| `countryNotFoundContainer` | ViewStyle | No results container |
|
|
320
|
+
| `countryNotFoundMessage` | TextStyle | No results message |
|
|
321
|
+
| `alphabetContainer` | ViewStyle | Alphabet filter container |
|
|
322
|
+
| `alphabetLetter` | ViewStyle | Alphabet letter item |
|
|
323
|
+
| `alphabetLetterText` | TextStyle | Alphabet letter text |
|
|
324
|
+
| `alphabetLetterActive` | ViewStyle | Active letter state |
|
|
325
|
+
| `alphabetLetterDisabled` | ViewStyle | Disabled letter state |
|
|
326
|
+
| `alphabetLetterTextActive` | TextStyle | Active letter text |
|
|
327
|
+
| `alphabetLetterTextDisabled` | TextStyle | Disabled letter text |
|
|
311
328
|
|
|
312
329
|
<br>
|
|
313
330
|
|
|
@@ -348,6 +365,7 @@ export default function App() {
|
|
|
348
365
|
| allCountriesTitle | string | No | 'All Countries' | All Countries section title |
|
|
349
366
|
| showsVerticalScrollIndicator | boolean | No | false | Displays a horizontal scroll indicator |
|
|
350
367
|
| countryNotFoundMessage | string | No | "No countries found" | Country not found in search |
|
|
368
|
+
| allowFontScaling | boolean | No | true | Whether to allow font scaling for text elements |
|
|
351
369
|
|
|
352
370
|
<br>
|
|
353
371
|
|
|
@@ -398,13 +416,19 @@ The `language` prop supports the following values:
|
|
|
398
416
|
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.
|
|
399
417
|
|
|
400
418
|
```js
|
|
401
|
-
const countrySelectModalContainer = getByTestId(
|
|
419
|
+
const countrySelectModalContainer = getByTestId(
|
|
420
|
+
'countrySelectContainer'
|
|
421
|
+
);
|
|
402
422
|
const countrySelectModalContent = getByTestId('countrySelectContent');
|
|
403
423
|
const countrySelectBackdrop = getByTestId('countrySelectBackdrop');
|
|
404
424
|
const countrySelectList = getByTestId('countrySelectList');
|
|
405
|
-
const countrySelectSearchInput = getByTestId(
|
|
425
|
+
const countrySelectSearchInput = getByTestId(
|
|
426
|
+
'countrySelectSearchInput'
|
|
427
|
+
);
|
|
406
428
|
const countrySelectItem = getByTestId('countrySelectItem');
|
|
407
|
-
const countrySelectCloseButton = getByTestId(
|
|
429
|
+
const countrySelectCloseButton = getByTestId(
|
|
430
|
+
'countrySelectCloseButton'
|
|
431
|
+
);
|
|
408
432
|
```
|
|
409
433
|
|
|
410
434
|
<br>
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/* eslint-disable no-undef-init */
|
|
2
2
|
/* eslint-disable react-hooks/exhaustive-deps */
|
|
3
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';
|
|
4
|
+
import React, { useEffect, useMemo, useRef } from 'react';
|
|
5
|
+
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
|
6
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';
|
|
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
12
|
|
|
13
13
|
const ALPHABET_VIEWPORT_HEIGHT = 0;
|
|
14
14
|
const ALPHABET_ITEM_SIZE = 28;
|
|
@@ -26,6 +26,7 @@ export const AlphabeticFilter: React.FC<AlphabeticFilterProps> = ({
|
|
|
26
26
|
accessibilityHintAlphabetFilter,
|
|
27
27
|
accessibilityLabelAlphabetLetter,
|
|
28
28
|
accessibilityHintAlphabetLetter,
|
|
29
|
+
allowFontScaling = true,
|
|
29
30
|
}) => {
|
|
30
31
|
const styles = createStyles(theme);
|
|
31
32
|
const alphabetScrollRef = useRef<ScrollView>(null);
|
|
@@ -63,7 +64,7 @@ export const AlphabeticFilter: React.FC<AlphabeticFilterProps> = ({
|
|
|
63
64
|
centerOffset +
|
|
64
65
|
ALPHABET_VERTICAL_PADDING,
|
|
65
66
|
);
|
|
66
|
-
alphabetScrollRef.current?.scrollTo({y, animated: true});
|
|
67
|
+
alphabetScrollRef.current?.scrollTo({ y, animated: true });
|
|
67
68
|
}
|
|
68
69
|
};
|
|
69
70
|
|
|
@@ -88,8 +89,9 @@ export const AlphabeticFilter: React.FC<AlphabeticFilterProps> = ({
|
|
|
88
89
|
}
|
|
89
90
|
ref={alphabetScrollRef}
|
|
90
91
|
style={[styles.alphabetContainer, countrySelectStyle?.alphabetContainer]}
|
|
91
|
-
contentContainerStyle={{alignItems: 'center', paddingVertical: 12}}
|
|
92
|
-
showsVerticalScrollIndicator={false}
|
|
92
|
+
contentContainerStyle={{ alignItems: 'center', paddingVertical: 12 }}
|
|
93
|
+
showsVerticalScrollIndicator={false}
|
|
94
|
+
>
|
|
93
95
|
{alphabet.map(letter => {
|
|
94
96
|
const enabled = letterIndexMap[letter] !== undefined;
|
|
95
97
|
const isActive = activeLetter === letter;
|
|
@@ -142,13 +144,16 @@ export const AlphabeticFilter: React.FC<AlphabeticFilterProps> = ({
|
|
|
142
144
|
accessibilityLabelAlphabetLetter ||
|
|
143
145
|
translations.accessibilityLabelAlphabetLetter[language] +
|
|
144
146
|
` ${letter}`
|
|
145
|
-
}
|
|
147
|
+
}
|
|
148
|
+
>
|
|
146
149
|
<Text
|
|
147
150
|
style={[
|
|
148
151
|
styles.alphabetLetterText,
|
|
149
152
|
isActive && styles.alphabetLetterTextActive,
|
|
150
153
|
countrySelectStyle?.alphabetLetterText,
|
|
151
|
-
]}
|
|
154
|
+
]}
|
|
155
|
+
allowFontScaling={allowFontScaling}
|
|
156
|
+
>
|
|
152
157
|
{letter}
|
|
153
158
|
</Text>
|
|
154
159
|
</TouchableOpacity>
|
|
@@ -161,13 +166,15 @@ export const AlphabeticFilter: React.FC<AlphabeticFilterProps> = ({
|
|
|
161
166
|
styles.alphabetLetter,
|
|
162
167
|
styles.alphabetLetterDisabled,
|
|
163
168
|
countrySelectStyle?.alphabetLetter,
|
|
164
|
-
]}
|
|
169
|
+
]}
|
|
170
|
+
>
|
|
165
171
|
<Text
|
|
166
172
|
style={[
|
|
167
173
|
styles.alphabetLetterText,
|
|
168
174
|
styles.alphabetLetterTextDisabled,
|
|
169
175
|
countrySelectStyle?.alphabetLetterText,
|
|
170
|
-
]}
|
|
176
|
+
]}
|
|
177
|
+
>
|
|
171
178
|
{letter}
|
|
172
179
|
</Text>
|
|
173
180
|
</View>
|
|
@@ -134,7 +134,7 @@ export const BottomSheetModal: React.FC<BottomSheetModalProps> = ({
|
|
|
134
134
|
toValue: 0,
|
|
135
135
|
duration: 200,
|
|
136
136
|
useNativeDriver: false,
|
|
137
|
-
}).start();
|
|
137
|
+
}).start(() => onRequestClose({} as NativeSyntheticEvent<any>));
|
|
138
138
|
return;
|
|
139
139
|
}
|
|
140
140
|
const finalHeight = Math.min(
|
|
@@ -159,7 +159,7 @@ export const BottomSheetModal: React.FC<BottomSheetModalProps> = ({
|
|
|
159
159
|
}).start();
|
|
160
160
|
},
|
|
161
161
|
}),
|
|
162
|
-
[bottomSheetSize
|
|
162
|
+
[bottomSheetSize, sheetHeight, onRequestClose],
|
|
163
163
|
);
|
|
164
164
|
return (
|
|
165
165
|
<Modal
|
|
@@ -193,8 +193,6 @@ export const BottomSheetModal: React.FC<BottomSheetModalProps> = ({
|
|
|
193
193
|
countrySelectStyle?.content,
|
|
194
194
|
{
|
|
195
195
|
height: sheetHeight,
|
|
196
|
-
minHeight: bottomSheetSize.minHeight,
|
|
197
|
-
maxHeight: bottomSheetSize.maxHeight,
|
|
198
196
|
},
|
|
199
197
|
]}>
|
|
200
198
|
<View
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {Text, TouchableOpacity} from 'react-native';
|
|
2
|
+
import { Text, TouchableOpacity } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import {createStyles} from '../styles';
|
|
5
|
-
import {ICloseButtonProps} from '../../interface';
|
|
6
|
-
import {translations} from '../../utils/getTranslation';
|
|
4
|
+
import { createStyles } from '../styles';
|
|
5
|
+
import { ICloseButtonProps } from '../../interface';
|
|
6
|
+
import { translations } from '../../utils/getTranslation';
|
|
7
7
|
|
|
8
8
|
export const CloseButton: React.FC<ICloseButtonProps> = ({
|
|
9
|
-
theme,
|
|
9
|
+
theme = 'light',
|
|
10
10
|
language,
|
|
11
11
|
onClose,
|
|
12
12
|
countrySelectStyle,
|
|
13
13
|
accessibilityLabelCloseButton,
|
|
14
14
|
accessibilityHintCloseButton,
|
|
15
|
+
allowFontScaling = true,
|
|
15
16
|
}) => {
|
|
16
17
|
const styles = createStyles(theme);
|
|
17
18
|
return (
|
|
@@ -28,9 +29,12 @@ export const CloseButton: React.FC<ICloseButtonProps> = ({
|
|
|
28
29
|
}
|
|
29
30
|
style={[styles.closeButton, countrySelectStyle?.closeButton]}
|
|
30
31
|
activeOpacity={0.6}
|
|
31
|
-
onPress={onClose}
|
|
32
|
+
onPress={onClose}
|
|
33
|
+
>
|
|
32
34
|
<Text
|
|
33
|
-
style={[styles.closeButtonText, countrySelectStyle?.closeButtonText]}
|
|
35
|
+
style={[styles.closeButtonText, countrySelectStyle?.closeButtonText]}
|
|
36
|
+
allowFontScaling={allowFontScaling}
|
|
37
|
+
>
|
|
34
38
|
{'\u00D7'}
|
|
35
39
|
</Text>
|
|
36
40
|
</TouchableOpacity>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React, {memo} from 'react';
|
|
2
|
-
import {View, Text, TouchableOpacity} from 'react-native';
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
|
+
import { View, Text, TouchableOpacity } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import {createStyles} from '../styles';
|
|
5
|
-
import {translations} from '../../utils/getTranslation';
|
|
6
|
-
import {ICountryItemProps} from '../../interface';
|
|
4
|
+
import { createStyles } from '../styles';
|
|
5
|
+
import { translations } from '../../utils/getTranslation';
|
|
6
|
+
import { ICountryItemProps } from '../../interface';
|
|
7
7
|
|
|
8
8
|
export const CountryItem = memo<ICountryItemProps>(
|
|
9
9
|
({
|
|
@@ -15,6 +15,7 @@ export const CountryItem = memo<ICountryItemProps>(
|
|
|
15
15
|
countrySelectStyle,
|
|
16
16
|
accessibilityLabel,
|
|
17
17
|
accessibilityHint,
|
|
18
|
+
allowFontScaling = true,
|
|
18
19
|
}) => {
|
|
19
20
|
const styles = createStyles(theme);
|
|
20
21
|
|
|
@@ -37,10 +38,13 @@ export const CountryItem = memo<ICountryItemProps>(
|
|
|
37
38
|
countrySelectStyle?.countryItem,
|
|
38
39
|
isSelected && styles.countryItemSelected,
|
|
39
40
|
]}
|
|
40
|
-
onPress={() => onSelect(country)}
|
|
41
|
+
onPress={() => onSelect(country)}
|
|
42
|
+
>
|
|
41
43
|
<Text
|
|
42
44
|
testID="countrySelectItemFlag"
|
|
43
|
-
style={[styles.flag, countrySelectStyle?.flag]}
|
|
45
|
+
style={[styles.flag, countrySelectStyle?.flag]}
|
|
46
|
+
allowFontScaling={allowFontScaling}
|
|
47
|
+
>
|
|
44
48
|
{country.flag || country.cca2}
|
|
45
49
|
</Text>
|
|
46
50
|
<View style={[styles.countryInfo, countrySelectStyle?.countryInfo]}>
|
|
@@ -50,7 +54,9 @@ export const CountryItem = memo<ICountryItemProps>(
|
|
|
50
54
|
styles.callingCode,
|
|
51
55
|
countrySelectStyle?.callingCode,
|
|
52
56
|
isSelected && styles.callingCodeSelected,
|
|
53
|
-
]}
|
|
57
|
+
]}
|
|
58
|
+
allowFontScaling={allowFontScaling}
|
|
59
|
+
>
|
|
54
60
|
{country.idd.root}
|
|
55
61
|
</Text>
|
|
56
62
|
<Text
|
|
@@ -59,7 +65,9 @@ export const CountryItem = memo<ICountryItemProps>(
|
|
|
59
65
|
styles.countryName,
|
|
60
66
|
countrySelectStyle?.countryName,
|
|
61
67
|
isSelected && styles.countryNameSelected,
|
|
62
|
-
]}
|
|
68
|
+
]}
|
|
69
|
+
allowFontScaling={allowFontScaling}
|
|
70
|
+
>
|
|
63
71
|
{country?.translations[language]?.common}
|
|
64
72
|
</Text>
|
|
65
73
|
</View>
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/* eslint-disable react-native/no-inline-styles */
|
|
2
2
|
/* eslint-disable react-hooks/exhaustive-deps */
|
|
3
|
-
import React, {useCallback, useMemo, useState, useRef} from 'react';
|
|
4
|
-
import {View, FlatList, ListRenderItem, Text} from 'react-native';
|
|
3
|
+
import React, { useCallback, useMemo, useState, useRef } from 'react';
|
|
4
|
+
import { View, FlatList, ListRenderItem, Text } from 'react-native';
|
|
5
5
|
|
|
6
|
-
import {PopupModal} from '../PopupModal';
|
|
7
|
-
import {CountryItem} from '../CountryItem';
|
|
8
|
-
import {CloseButton} from '../CloseButton';
|
|
9
|
-
import {SearchInput} from '../SearchInput';
|
|
10
|
-
import {FullscreenModal} from '../FullscreenModal';
|
|
11
|
-
import {BottomSheetModal} from '../BottomSheetModal';
|
|
12
|
-
import {AlphabeticFilter} from '../AlphabeticFilter';
|
|
6
|
+
import { PopupModal } from '../PopupModal';
|
|
7
|
+
import { CountryItem } from '../CountryItem';
|
|
8
|
+
import { CloseButton } from '../CloseButton';
|
|
9
|
+
import { SearchInput } from '../SearchInput';
|
|
10
|
+
import { FullscreenModal } from '../FullscreenModal';
|
|
11
|
+
import { BottomSheetModal } from '../BottomSheetModal';
|
|
12
|
+
import { AlphabeticFilter } from '../AlphabeticFilter';
|
|
13
13
|
|
|
14
|
-
import {createStyles} from '../styles';
|
|
15
|
-
import {translations} from '../../utils/getTranslation';
|
|
16
|
-
import {getCountriesList} from '../../utils/getCountriesList';
|
|
14
|
+
import { createStyles } from '../styles';
|
|
15
|
+
import { translations } from '../../utils/getTranslation';
|
|
16
|
+
import { getCountriesList } from '../../utils/getCountriesList';
|
|
17
17
|
import {
|
|
18
18
|
ICountry,
|
|
19
19
|
ICountrySelectProps,
|
|
@@ -69,6 +69,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
69
69
|
accessibilityHintAlphabetFilter,
|
|
70
70
|
accessibilityLabelAlphabetLetter,
|
|
71
71
|
accessibilityHintAlphabetLetter,
|
|
72
|
+
allowFontScaling = true,
|
|
72
73
|
...props
|
|
73
74
|
}) => {
|
|
74
75
|
const [searchQuery, setSearchQuery] = useState('');
|
|
@@ -208,6 +209,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
208
209
|
countrySelectStyle={countrySelectStyle}
|
|
209
210
|
accessibilityLabelCloseButton={accessibilityLabelCloseButton}
|
|
210
211
|
accessibilityHintCloseButton={accessibilityHintCloseButton}
|
|
212
|
+
allowFontScaling={allowFontScaling}
|
|
211
213
|
/>
|
|
212
214
|
);
|
|
213
215
|
};
|
|
@@ -224,6 +226,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
224
226
|
searchSelectionColor={searchSelectionColor}
|
|
225
227
|
accessibilityLabelSearchInput={accessibilityLabelSearchInput}
|
|
226
228
|
accessibilityHintSearchInput={accessibilityHintSearchInput}
|
|
229
|
+
allowFontScaling={allowFontScaling}
|
|
227
230
|
/>
|
|
228
231
|
);
|
|
229
232
|
|
|
@@ -231,7 +234,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
231
234
|
({
|
|
232
235
|
viewableItems,
|
|
233
236
|
}: {
|
|
234
|
-
viewableItems: Array<{item: IListItem; index: number | null}>;
|
|
237
|
+
viewableItems: Array<{ item: IListItem; index: number | null }>;
|
|
235
238
|
}) => {
|
|
236
239
|
if (isProgrammaticScroll.current) {
|
|
237
240
|
// Ignore transient updates while we are animating to a specific index
|
|
@@ -260,12 +263,15 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
260
263
|
style={[
|
|
261
264
|
styles.countryNotFoundContainer,
|
|
262
265
|
countrySelectStyle?.countryNotFoundContainer,
|
|
263
|
-
]}
|
|
266
|
+
]}
|
|
267
|
+
>
|
|
264
268
|
<Text
|
|
265
269
|
style={[
|
|
266
270
|
styles.countryNotFoundMessage,
|
|
267
271
|
countrySelectStyle?.countryNotFoundMessage,
|
|
268
|
-
]}
|
|
272
|
+
]}
|
|
273
|
+
allowFontScaling={allowFontScaling}
|
|
274
|
+
>
|
|
269
275
|
{countryNotFoundMessage ||
|
|
270
276
|
translations.searchNotFoundMessage[
|
|
271
277
|
language as ICountrySelectLanguages
|
|
@@ -301,7 +307,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
301
307
|
// Fallback if momentum does not trigger
|
|
302
308
|
isProgrammaticScroll.current = false;
|
|
303
309
|
}}
|
|
304
|
-
onScrollToIndexFailed={({index, averageItemLength}) => {
|
|
310
|
+
onScrollToIndexFailed={({ index, averageItemLength }) => {
|
|
305
311
|
// Simple recovery: estimate offset, then retry scrollToIndex after measurement
|
|
306
312
|
const estimatedOffset = Math.max(0, (averageItemLength || 0) * index);
|
|
307
313
|
flatListRef.current?.scrollToOffset({
|
|
@@ -321,7 +327,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
321
327
|
};
|
|
322
328
|
|
|
323
329
|
const renderItem: ListRenderItem<IListItem> = useCallback(
|
|
324
|
-
({item, index}) => {
|
|
330
|
+
({ item, index }) => {
|
|
325
331
|
if ('isSection' in item) {
|
|
326
332
|
if (sectionTitleComponent) {
|
|
327
333
|
return sectionTitleComponent(item);
|
|
@@ -330,7 +336,9 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
330
336
|
<Text
|
|
331
337
|
testID="countrySelectSectionTitle"
|
|
332
338
|
accessibilityRole="header"
|
|
333
|
-
style={[styles.sectionTitle, countrySelectStyle?.sectionTitle]}
|
|
339
|
+
style={[styles.sectionTitle, countrySelectStyle?.sectionTitle]}
|
|
340
|
+
allowFontScaling={allowFontScaling}
|
|
341
|
+
>
|
|
334
342
|
{popularCountriesTitle && index === 0
|
|
335
343
|
? popularCountriesTitle
|
|
336
344
|
: allCountriesTitle && index > 0
|
|
@@ -356,6 +364,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
356
364
|
countrySelectStyle={countrySelectStyle}
|
|
357
365
|
accessibilityLabel={accessibilityLabelCountryItem}
|
|
358
366
|
accessibilityHint={accessibilityHintCountryItem}
|
|
367
|
+
allowFontScaling={allowFontScaling}
|
|
359
368
|
/>
|
|
360
369
|
);
|
|
361
370
|
},
|
|
@@ -383,6 +392,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
383
392
|
accessibilityHintAlphabetFilter={accessibilityHintAlphabetFilter}
|
|
384
393
|
accessibilityLabelAlphabetLetter={accessibilityLabelAlphabetLetter}
|
|
385
394
|
accessibilityHintAlphabetLetter={accessibilityHintAlphabetLetter}
|
|
395
|
+
allowFontScaling={allowFontScaling}
|
|
386
396
|
/>
|
|
387
397
|
);
|
|
388
398
|
};
|
|
@@ -390,7 +400,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
390
400
|
const HeaderModal =
|
|
391
401
|
showSearchInput || showCloseButton ? (
|
|
392
402
|
<View
|
|
393
|
-
style={[styles.searchContainer, countrySelectStyle?.searchContainer]}
|
|
403
|
+
style={[styles.searchContainer, countrySelectStyle?.searchContainer]}
|
|
404
|
+
>
|
|
394
405
|
{(showCloseButton || isFullScreen) && renderCloseButton()}
|
|
395
406
|
{showSearchInput && renderSearchInput()}
|
|
396
407
|
</View>
|
|
@@ -398,7 +409,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
398
409
|
|
|
399
410
|
const ContentModal = (
|
|
400
411
|
<>
|
|
401
|
-
<View style={{flex: 1}}>{renderFlatList()}</View>
|
|
412
|
+
<View style={{ flex: 1 }}>{renderFlatList()}</View>
|
|
402
413
|
{showAlphabetFilter && <View>{renderAlphabetFilter()}</View>}
|
|
403
414
|
</>
|
|
404
415
|
);
|
|
@@ -424,7 +435,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
424
435
|
styles={styles}
|
|
425
436
|
countrySelectStyle={countrySelectStyle}
|
|
426
437
|
header={HeaderModal}
|
|
427
|
-
{...props}
|
|
438
|
+
{...props}
|
|
439
|
+
>
|
|
428
440
|
{ContentModal}
|
|
429
441
|
</FullscreenModal>
|
|
430
442
|
);
|
|
@@ -449,7 +461,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
449
461
|
styles={styles}
|
|
450
462
|
countrySelectStyle={countrySelectStyle}
|
|
451
463
|
header={HeaderModal}
|
|
452
|
-
{...props}
|
|
464
|
+
{...props}
|
|
465
|
+
>
|
|
453
466
|
{ContentModal}
|
|
454
467
|
</PopupModal>
|
|
455
468
|
);
|
|
@@ -478,7 +491,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
478
491
|
initialBottomsheetHeight={initialBottomsheetHeight}
|
|
479
492
|
dragHandleIndicatorComponent={dragHandleIndicatorComponent}
|
|
480
493
|
header={HeaderModal}
|
|
481
|
-
{...props}
|
|
494
|
+
{...props}
|
|
495
|
+
>
|
|
482
496
|
{ContentModal}
|
|
483
497
|
</BottomSheetModal>
|
|
484
498
|
);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {TextInput} from 'react-native';
|
|
2
|
+
import { TextInput } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import {createStyles} from '../styles';
|
|
5
|
-
import {translations} from '../../utils/getTranslation';
|
|
6
|
-
import {ISearchInputProps, ICountrySelectLanguages} from '../../interface';
|
|
4
|
+
import { createStyles } from '../styles';
|
|
5
|
+
import { translations } from '../../utils/getTranslation';
|
|
6
|
+
import { ISearchInputProps, ICountrySelectLanguages } from '../../interface';
|
|
7
7
|
|
|
8
8
|
export const SearchInput: React.FC<ISearchInputProps> = ({
|
|
9
|
-
theme,
|
|
9
|
+
theme = 'light',
|
|
10
10
|
language,
|
|
11
11
|
value,
|
|
12
12
|
onChangeText,
|
|
@@ -16,6 +16,7 @@ export const SearchInput: React.FC<ISearchInputProps> = ({
|
|
|
16
16
|
searchSelectionColor,
|
|
17
17
|
accessibilityLabelSearchInput,
|
|
18
18
|
accessibilityHintSearchInput,
|
|
19
|
+
allowFontScaling = true,
|
|
19
20
|
}) => {
|
|
20
21
|
const styles = createStyles(theme);
|
|
21
22
|
return (
|
|
@@ -42,6 +43,7 @@ export const SearchInput: React.FC<ISearchInputProps> = ({
|
|
|
42
43
|
selectionColor={searchSelectionColor}
|
|
43
44
|
value={value}
|
|
44
45
|
onChangeText={onChangeText}
|
|
46
|
+
allowFontScaling={allowFontScaling}
|
|
45
47
|
/>
|
|
46
48
|
);
|
|
47
49
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {IThemeProps} from './theme';
|
|
2
|
-
import {ICountrySelectStyle} from './countrySelectStyles';
|
|
3
|
-
import {ICountrySelectLanguages} from './countrySelectLanguages';
|
|
4
|
-
import {IListItem} from './itemList';
|
|
1
|
+
import { IThemeProps } from './theme';
|
|
2
|
+
import { ICountrySelectStyle } from './countrySelectStyles';
|
|
3
|
+
import { ICountrySelectLanguages } from './countrySelectLanguages';
|
|
4
|
+
import { IListItem } from './itemList';
|
|
5
5
|
|
|
6
6
|
export interface AlphabeticFilterProps {
|
|
7
7
|
theme?: IThemeProps;
|
|
@@ -15,4 +15,5 @@ export interface AlphabeticFilterProps {
|
|
|
15
15
|
accessibilityHintAlphabetFilter?: string;
|
|
16
16
|
accessibilityLabelAlphabetLetter?: string;
|
|
17
17
|
accessibilityHintAlphabetLetter?: string;
|
|
18
|
+
allowFontScaling?: boolean;
|
|
18
19
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {ICountrySelectLanguages} from './countrySelectLanguages';
|
|
2
|
-
import {ICountrySelectStyle} from './countrySelectStyles';
|
|
3
|
-
import {IThemeProps} from './theme';
|
|
1
|
+
import { ICountrySelectLanguages } from './countrySelectLanguages';
|
|
2
|
+
import { ICountrySelectStyle } from './countrySelectStyles';
|
|
3
|
+
import { IThemeProps } from './theme';
|
|
4
4
|
|
|
5
5
|
export interface ICloseButtonProps {
|
|
6
6
|
theme?: IThemeProps;
|
|
@@ -9,4 +9,5 @@ export interface ICloseButtonProps {
|
|
|
9
9
|
countrySelectStyle?: ICountrySelectStyle;
|
|
10
10
|
accessibilityLabelCloseButton?: string;
|
|
11
11
|
accessibilityHintCloseButton?: string;
|
|
12
|
+
allowFontScaling?: boolean;
|
|
12
13
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {ICountry} from './country';
|
|
2
|
-
import {IThemeProps} from './theme';
|
|
3
|
-
import {ICountrySelectStyle} from './countrySelectStyles';
|
|
4
|
-
import {ICountrySelectLanguages} from './countrySelectLanguages';
|
|
1
|
+
import { ICountry } from './country';
|
|
2
|
+
import { IThemeProps } from './theme';
|
|
3
|
+
import { ICountrySelectStyle } from './countrySelectStyles';
|
|
4
|
+
import { ICountrySelectLanguages } from './countrySelectLanguages';
|
|
5
5
|
|
|
6
6
|
export interface ICountryItemProps {
|
|
7
7
|
country: ICountry;
|
|
@@ -12,4 +12,5 @@ export interface ICountryItemProps {
|
|
|
12
12
|
countrySelectStyle?: ICountrySelectStyle;
|
|
13
13
|
accessibilityLabel?: string;
|
|
14
14
|
accessibilityHint?: string;
|
|
15
|
+
allowFontScaling?: boolean;
|
|
15
16
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {ModalProps} from 'react-native';
|
|
2
|
+
import { ModalProps } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import {ICountry} from './country';
|
|
5
|
-
import {IThemeProps} from './theme';
|
|
6
|
-
import {ICountryCca2} from './countryCca2';
|
|
7
|
-
import {ISectionTitle} from './sectionTitle';
|
|
8
|
-
import {ICountrySelectStyle} from './countrySelectStyles';
|
|
9
|
-
import {ICountrySelectLanguages} from './countrySelectLanguages';
|
|
4
|
+
import { ICountry } from './country';
|
|
5
|
+
import { IThemeProps } from './theme';
|
|
6
|
+
import { ICountryCca2 } from './countryCca2';
|
|
7
|
+
import { ISectionTitle } from './sectionTitle';
|
|
8
|
+
import { ICountrySelectStyle } from './countrySelectStyles';
|
|
9
|
+
import { ICountrySelectLanguages } from './countrySelectLanguages';
|
|
10
10
|
|
|
11
11
|
interface ICountrySelectBaseProps extends ModalProps, IThemeProps {
|
|
12
12
|
visible: boolean;
|
|
@@ -52,6 +52,7 @@ interface ICountrySelectBaseProps extends ModalProps, IThemeProps {
|
|
|
52
52
|
accessibilityHintAlphabetFilter?: string;
|
|
53
53
|
accessibilityLabelAlphabetLetter?: string;
|
|
54
54
|
accessibilityHintAlphabetLetter?: string;
|
|
55
|
+
allowFontScaling?: boolean;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
interface ICountrySelectSingleProps extends ICountrySelectBaseProps {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {ICountrySelectLanguages} from './countrySelectLanguages';
|
|
2
|
-
import {ICountrySelectStyle} from './countrySelectStyles';
|
|
3
|
-
import {IThemeProps} from './theme';
|
|
1
|
+
import { ICountrySelectLanguages } from './countrySelectLanguages';
|
|
2
|
+
import { ICountrySelectStyle } from './countrySelectStyles';
|
|
3
|
+
import { IThemeProps } from './theme';
|
|
4
4
|
|
|
5
5
|
export interface ISearchInputProps {
|
|
6
6
|
theme?: IThemeProps;
|
|
@@ -13,4 +13,5 @@ export interface ISearchInputProps {
|
|
|
13
13
|
searchSelectionColor?: string;
|
|
14
14
|
accessibilityLabelSearchInput?: string;
|
|
15
15
|
accessibilityHintSearchInput?: string;
|
|
16
|
+
allowFontScaling?: boolean;
|
|
16
17
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-country-select",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "🌍 React Native country picker with flags, search, TypeScript, i18n, and offline support. Lightweight, customizable, and designed with a modern UI.",
|
|
5
5
|
"main": "lib/index.tsx",
|
|
6
6
|
"types": "lib/index.d.ts",
|