react-native-country-select 0.3.1 → 0.3.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 +80 -62
- package/lib/components/AlphabeticFilter/index.tsx +21 -14
- package/lib/components/CloseButton/index.tsx +11 -7
- package/lib/components/CountryItem/index.tsx +35 -15
- package/lib/components/CountrySelect/index.tsx +93 -43
- package/lib/components/SearchInput/index.tsx +7 -5
- package/lib/index.d.ts +11 -5
- package/lib/index.tsx +3 -1
- package/lib/interface/alfabeticFilterProps.ts +5 -4
- package/lib/interface/closeButtonProps.ts +4 -3
- package/lib/interface/country.ts +2 -1
- package/lib/interface/countryItemProps.ts +9 -4
- package/lib/interface/countrySelectProps.ts +11 -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>
|
|
@@ -320,41 +330,43 @@ export default function App() {
|
|
|
320
330
|
|
|
321
331
|
## CountrySelect Props ([countrySelectProps](https://github.com/AstrOOnauta/react-native-country-select/blob/main/lib/interface/countrySelectProps.ts))
|
|
322
332
|
|
|
323
|
-
| Prop | Type | Required | Default | Description
|
|
324
|
-
| ---------------------------- | ----------------------------------------------------------------------- | -------- | -------------------- |
|
|
325
|
-
| visible | boolean | Yes | false | Controls the visibility of the country picker modal
|
|
326
|
-
| onClose | () => void | Yes | - | Callback function called when the modal is closed
|
|
327
|
-
| onSelect | (country: [ICountry](lib/interfaces/country.ts)) => void | Yes | - | Callback function called when a country is selected
|
|
328
|
-
| modalType | 'bottomSheet' \| 'popup' | No | 'bottomSheet' | Type of modal to display
|
|
329
|
-
| countrySelectStyle | [ICountrySelectStyle](lib/interfaces/countrySelectStyles.ts) | No | - | Custom styles for the country picker
|
|
330
|
-
| isMultiSelect | boolean | No | false | Whether the user can select multiple options
|
|
331
|
-
| selectedCountries | [ICountry[]](lib/interfaces/country.ts) | No | - | Array of countries to show in multi select mode
|
|
332
|
-
| isFullScreen | boolean | No | false | Whether the modal should be full screen
|
|
333
|
-
| popularCountries | string[] | No | [] | Array of country codes to show in popular section
|
|
334
|
-
| visibleCountries | [ICountryCca2[]](lib/interfaces/countryCca2.ts) | No | [] | Array of country codes to show (whitelist)
|
|
335
|
-
| hiddenCountries | [ICountryCca2[]](lib/interfaces/countryCca2.ts) | No | [] | Array of country codes to hide (blacklist)
|
|
336
|
-
| theme | 'light' \| 'dark' | No | 'light' | Theme for the country picker
|
|
337
|
-
| language | [ICountrySelectLanguages](lib/interfaces/countrySelectLanguages.ts) | No | 'eng' | Language for country names (see supported languages below)
|
|
338
|
-
| showSearchInput | boolean | No | true | Whether to show the search input field
|
|
339
|
-
| showAlphabetFilter | boolean | No | false | Whether to show the alphabetic filter on modal
|
|
340
|
-
| searchPlaceholder | string | No | 'Search country...' | Placeholder text for search input
|
|
341
|
-
| searchPlaceholderTextColor | string | No | '#00000080' | Placeholder text color for search input
|
|
342
|
-
| searchSelectionColor | string | No | default | Highlight, selection handle and cursor color of the search input
|
|
343
|
-
| minBottomsheetHeight | number \| string | No | 30% | Minimum height for bottom sheet modal
|
|
344
|
-
| maxBottomsheetHeight | number \| string | No | 80% | Maximum height for bottom sheet modal
|
|
345
|
-
| initialBottomsheetHeight | number \| string | No | 50% | Initial height for bottom sheet modal
|
|
346
|
-
| disabledBackdropPress | boolean | No | false | Whether to disable backdrop press to close
|
|
347
|
-
| removedBackdrop | boolean | No | false | Whether to remove the backdrop completely
|
|
348
|
-
| onBackdropPress | () => void | No | - | Custom callback for backdrop press
|
|
349
|
-
| dragHandleIndicatorComponent | () => ReactElement | - | - | Custom component for drag handle indicator on bottom sheet
|
|
350
|
-
| countryItemComponent | (item: [ICountry](lib/interfaces/country.ts)) => ReactElement | No | - | Custom component for country items
|
|
351
|
-
| sectionTitleComponent | (item: [ISectionTitle](lib/interfaces/sectionTitle.ts)) => ReactElement | No | - | Custom component for section titles
|
|
352
|
-
| closeButtonComponent | () => ReactElement | No | - | Custom component for closeButton
|
|
353
|
-
|
|
|
354
|
-
|
|
|
355
|
-
|
|
|
356
|
-
|
|
|
357
|
-
|
|
|
333
|
+
| Prop | Type | Required | Default | Description |
|
|
334
|
+
| ---------------------------- | ----------------------------------------------------------------------- | -------- | -------------------- | -------------------------------------------------------------------------------------- |
|
|
335
|
+
| visible | boolean | Yes | false | Controls the visibility of the country picker modal |
|
|
336
|
+
| onClose | () => void | Yes | - | Callback function called when the modal is closed |
|
|
337
|
+
| onSelect | (country: [ICountry](lib/interfaces/country.ts)) => void | Yes | - | Callback function called when a country is selected |
|
|
338
|
+
| modalType | 'bottomSheet' \| 'popup' | No | 'bottomSheet' | Type of modal to display |
|
|
339
|
+
| countrySelectStyle | [ICountrySelectStyle](lib/interfaces/countrySelectStyles.ts) | No | - | Custom styles for the country picker |
|
|
340
|
+
| isMultiSelect | boolean | No | false | Whether the user can select multiple options |
|
|
341
|
+
| selectedCountries | [ICountry[]](lib/interfaces/country.ts) | No | - | Array of countries to show in multi select mode |
|
|
342
|
+
| isFullScreen | boolean | No | false | Whether the modal should be full screen |
|
|
343
|
+
| popularCountries | string[] | No | [] | Array of country codes to show in popular section |
|
|
344
|
+
| visibleCountries | [ICountryCca2[]](lib/interfaces/countryCca2.ts) | No | [] | Array of country codes to show (whitelist) |
|
|
345
|
+
| hiddenCountries | [ICountryCca2[]](lib/interfaces/countryCca2.ts) | No | [] | Array of country codes to hide (blacklist) |
|
|
346
|
+
| theme | 'light' \| 'dark' | No | 'light' | Theme for the country picker |
|
|
347
|
+
| language | [ICountrySelectLanguages](lib/interfaces/countrySelectLanguages.ts) | No | 'eng' | Language for country names (see supported languages below) |
|
|
348
|
+
| showSearchInput | boolean | No | true | Whether to show the search input field |
|
|
349
|
+
| showAlphabetFilter | boolean | No | false | Whether to show the alphabetic filter on modal |
|
|
350
|
+
| searchPlaceholder | string | No | 'Search country...' | Placeholder text for search input |
|
|
351
|
+
| searchPlaceholderTextColor | string | No | '#00000080' | Placeholder text color for search input |
|
|
352
|
+
| searchSelectionColor | string | No | default | Highlight, selection handle and cursor color of the search input |
|
|
353
|
+
| minBottomsheetHeight | number \| string | No | 30% | Minimum height for bottom sheet modal |
|
|
354
|
+
| maxBottomsheetHeight | number \| string | No | 80% | Maximum height for bottom sheet modal |
|
|
355
|
+
| initialBottomsheetHeight | number \| string | No | 50% | Initial height for bottom sheet modal |
|
|
356
|
+
| disabledBackdropPress | boolean | No | false | Whether to disable backdrop press to close |
|
|
357
|
+
| removedBackdrop | boolean | No | false | Whether to remove the backdrop completely |
|
|
358
|
+
| onBackdropPress | () => void | No | - | Custom callback for backdrop press |
|
|
359
|
+
| dragHandleIndicatorComponent | () => ReactElement | - | - | Custom component for drag handle indicator on bottom sheet |
|
|
360
|
+
| countryItemComponent | (item: [ICountry](lib/interfaces/country.ts)) => ReactElement | No | - | Custom component for country items |
|
|
361
|
+
| sectionTitleComponent | (item: [ISectionTitle](lib/interfaces/sectionTitle.ts)) => ReactElement | No | - | Custom component for section titles |
|
|
362
|
+
| closeButtonComponent | () => ReactElement | No | - | Custom component for closeButton |
|
|
363
|
+
| customFlag | (country: [ICountry](lib/interfaces/country.ts)) => ReactElement | No | - | Custom render function for country flags. Returns rendered element in selected country |
|
|
364
|
+
| showCloseButton | boolean | No | false | Whether to show the close button |
|
|
365
|
+
| popularCountriesTitle | string | No | 'Popular Countries' | Popular Countries section title |
|
|
366
|
+
| allCountriesTitle | string | No | 'All Countries' | All Countries section title |
|
|
367
|
+
| showsVerticalScrollIndicator | boolean | No | false | Displays a horizontal scroll indicator |
|
|
368
|
+
| countryNotFoundMessage | string | No | "No countries found" | Country not found in search |
|
|
369
|
+
| allowFontScaling | boolean | No | true | Whether to allow font scaling for text elements |
|
|
358
370
|
|
|
359
371
|
<br>
|
|
360
372
|
|
|
@@ -405,13 +417,19 @@ The `language` prop supports the following values:
|
|
|
405
417
|
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.
|
|
406
418
|
|
|
407
419
|
```js
|
|
408
|
-
const countrySelectModalContainer = getByTestId(
|
|
420
|
+
const countrySelectModalContainer = getByTestId(
|
|
421
|
+
'countrySelectContainer'
|
|
422
|
+
);
|
|
409
423
|
const countrySelectModalContent = getByTestId('countrySelectContent');
|
|
410
424
|
const countrySelectBackdrop = getByTestId('countrySelectBackdrop');
|
|
411
425
|
const countrySelectList = getByTestId('countrySelectList');
|
|
412
|
-
const countrySelectSearchInput = getByTestId(
|
|
426
|
+
const countrySelectSearchInput = getByTestId(
|
|
427
|
+
'countrySelectSearchInput'
|
|
428
|
+
);
|
|
413
429
|
const countrySelectItem = getByTestId('countrySelectItem');
|
|
414
|
-
const countrySelectCloseButton = getByTestId(
|
|
430
|
+
const countrySelectCloseButton = getByTestId(
|
|
431
|
+
'countrySelectCloseButton'
|
|
432
|
+
);
|
|
415
433
|
```
|
|
416
434
|
|
|
417
435
|
<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>
|
|
@@ -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
|
({
|
|
@@ -13,8 +13,10 @@ export const CountryItem = memo<ICountryItemProps>(
|
|
|
13
13
|
theme = 'light',
|
|
14
14
|
language = 'eng',
|
|
15
15
|
countrySelectStyle,
|
|
16
|
+
customFlag,
|
|
16
17
|
accessibilityLabel,
|
|
17
18
|
accessibilityHint,
|
|
19
|
+
allowFontScaling = true,
|
|
18
20
|
}) => {
|
|
19
21
|
const styles = createStyles(theme);
|
|
20
22
|
|
|
@@ -37,20 +39,36 @@ export const CountryItem = memo<ICountryItemProps>(
|
|
|
37
39
|
countrySelectStyle?.countryItem,
|
|
38
40
|
isSelected && styles.countryItemSelected,
|
|
39
41
|
]}
|
|
40
|
-
onPress={() => onSelect(country)}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
onPress={() => onSelect(country)}
|
|
43
|
+
>
|
|
44
|
+
{customFlag &&
|
|
45
|
+
customFlag(country) !== undefined &&
|
|
46
|
+
customFlag(country) !== null ? (
|
|
47
|
+
customFlag(country)
|
|
48
|
+
) : (
|
|
49
|
+
<Text
|
|
50
|
+
testID="countrySelectItemFlag"
|
|
51
|
+
style={[styles.flag, countrySelectStyle?.flag]}
|
|
52
|
+
allowFontScaling={allowFontScaling}
|
|
53
|
+
>
|
|
54
|
+
{country.flag || country.cca2}
|
|
55
|
+
</Text>
|
|
56
|
+
)}
|
|
57
|
+
<View
|
|
58
|
+
style={[
|
|
59
|
+
styles.countryInfo,
|
|
60
|
+
countrySelectStyle?.countryInfo,
|
|
61
|
+
]}
|
|
62
|
+
>
|
|
47
63
|
<Text
|
|
48
64
|
testID="countrySelectItemCallingCode"
|
|
49
65
|
style={[
|
|
50
66
|
styles.callingCode,
|
|
51
67
|
countrySelectStyle?.callingCode,
|
|
52
68
|
isSelected && styles.callingCodeSelected,
|
|
53
|
-
]}
|
|
69
|
+
]}
|
|
70
|
+
allowFontScaling={allowFontScaling}
|
|
71
|
+
>
|
|
54
72
|
{country.idd.root}
|
|
55
73
|
</Text>
|
|
56
74
|
<Text
|
|
@@ -59,11 +77,13 @@ export const CountryItem = memo<ICountryItemProps>(
|
|
|
59
77
|
styles.countryName,
|
|
60
78
|
countrySelectStyle?.countryName,
|
|
61
79
|
isSelected && styles.countryNameSelected,
|
|
62
|
-
]}
|
|
80
|
+
]}
|
|
81
|
+
allowFontScaling={allowFontScaling}
|
|
82
|
+
>
|
|
63
83
|
{country?.translations[language]?.common}
|
|
64
84
|
</Text>
|
|
65
85
|
</View>
|
|
66
86
|
</TouchableOpacity>
|
|
67
87
|
);
|
|
68
|
-
}
|
|
88
|
+
}
|
|
69
89
|
);
|
|
@@ -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,
|
|
@@ -51,6 +51,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
51
51
|
sectionTitleComponent,
|
|
52
52
|
countryItemComponent,
|
|
53
53
|
closeButtonComponent,
|
|
54
|
+
customFlag,
|
|
54
55
|
popularCountriesTitle,
|
|
55
56
|
allCountriesTitle,
|
|
56
57
|
showsVerticalScrollIndicator = false,
|
|
@@ -69,10 +70,13 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
69
70
|
accessibilityHintAlphabetFilter,
|
|
70
71
|
accessibilityLabelAlphabetLetter,
|
|
71
72
|
accessibilityHintAlphabetLetter,
|
|
73
|
+
allowFontScaling = true,
|
|
72
74
|
...props
|
|
73
75
|
}) => {
|
|
74
76
|
const [searchQuery, setSearchQuery] = useState('');
|
|
75
|
-
const [activeLetter, setActiveLetter] = useState<string | null>(
|
|
77
|
+
const [activeLetter, setActiveLetter] = useState<string | null>(
|
|
78
|
+
null
|
|
79
|
+
);
|
|
76
80
|
|
|
77
81
|
const flatListRef = useRef<FlatList<IListItem>>(null);
|
|
78
82
|
const isProgrammaticScroll = useRef(false);
|
|
@@ -117,8 +121,9 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
117
121
|
}, [countriesList]);
|
|
118
122
|
|
|
119
123
|
const keyExtractor = useCallback(
|
|
120
|
-
(item: IListItem) =>
|
|
121
|
-
|
|
124
|
+
(item: IListItem) =>
|
|
125
|
+
'isSection' in item ? item.title : item.cca2,
|
|
126
|
+
[]
|
|
122
127
|
);
|
|
123
128
|
|
|
124
129
|
const handlePressLetter = useCallback(
|
|
@@ -131,7 +136,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
131
136
|
for (let i = index; i < countriesList.length; i++) {
|
|
132
137
|
const item = countriesList[i];
|
|
133
138
|
if (!('isSection' in item)) {
|
|
134
|
-
const name =
|
|
139
|
+
const name =
|
|
140
|
+
(item as ICountry)?.translations[language]?.common || '';
|
|
135
141
|
if (name) {
|
|
136
142
|
computedLetter = name[0].toUpperCase();
|
|
137
143
|
}
|
|
@@ -148,7 +154,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
148
154
|
viewPosition: 0,
|
|
149
155
|
});
|
|
150
156
|
},
|
|
151
|
-
[countriesList, language]
|
|
157
|
+
[countriesList, language]
|
|
152
158
|
);
|
|
153
159
|
|
|
154
160
|
const handleCloseModal = () => {
|
|
@@ -171,29 +177,38 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
171
177
|
|
|
172
178
|
const isCountrySelected = useCallback(
|
|
173
179
|
(cca2: string) => selectedCountryCodes.has(cca2),
|
|
174
|
-
[selectedCountryCodes]
|
|
180
|
+
[selectedCountryCodes]
|
|
175
181
|
);
|
|
176
182
|
|
|
177
183
|
const handleSelectCountry = useCallback(
|
|
178
184
|
(country: ICountry) => {
|
|
185
|
+
const countryWithCustomFlag = customFlag
|
|
186
|
+
? {
|
|
187
|
+
...country,
|
|
188
|
+
customFlag: customFlag(country),
|
|
189
|
+
}
|
|
190
|
+
: country;
|
|
191
|
+
|
|
179
192
|
if (isMultiSelect) {
|
|
180
193
|
if (isCountrySelected(country.cca2)) {
|
|
181
194
|
(onSelect as (countries: ICountry[]) => void)(
|
|
182
|
-
selectedCountries.filter(c => c.cca2 !== country.cca2)
|
|
195
|
+
selectedCountries.filter((c) => c.cca2 !== country.cca2)
|
|
183
196
|
);
|
|
184
197
|
return;
|
|
185
198
|
}
|
|
186
199
|
(onSelect as (countries: ICountry[]) => void)([
|
|
187
200
|
...selectedCountries,
|
|
188
|
-
|
|
201
|
+
countryWithCustomFlag,
|
|
189
202
|
]);
|
|
190
203
|
return;
|
|
191
204
|
}
|
|
192
205
|
|
|
193
|
-
(onSelect as (country: ICountry) => void)(
|
|
206
|
+
(onSelect as (country: ICountry) => void)(
|
|
207
|
+
countryWithCustomFlag
|
|
208
|
+
);
|
|
194
209
|
onClose();
|
|
195
210
|
},
|
|
196
|
-
[isMultiSelect, isCountrySelected, selectedCountries]
|
|
211
|
+
[isMultiSelect, isCountrySelected, selectedCountries, customFlag]
|
|
197
212
|
);
|
|
198
213
|
|
|
199
214
|
const renderCloseButton = () => {
|
|
@@ -208,6 +223,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
208
223
|
countrySelectStyle={countrySelectStyle}
|
|
209
224
|
accessibilityLabelCloseButton={accessibilityLabelCloseButton}
|
|
210
225
|
accessibilityHintCloseButton={accessibilityHintCloseButton}
|
|
226
|
+
allowFontScaling={allowFontScaling}
|
|
211
227
|
/>
|
|
212
228
|
);
|
|
213
229
|
};
|
|
@@ -224,6 +240,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
224
240
|
searchSelectionColor={searchSelectionColor}
|
|
225
241
|
accessibilityLabelSearchInput={accessibilityLabelSearchInput}
|
|
226
242
|
accessibilityHintSearchInput={accessibilityHintSearchInput}
|
|
243
|
+
allowFontScaling={allowFontScaling}
|
|
227
244
|
/>
|
|
228
245
|
);
|
|
229
246
|
|
|
@@ -231,7 +248,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
231
248
|
({
|
|
232
249
|
viewableItems,
|
|
233
250
|
}: {
|
|
234
|
-
viewableItems: Array<{item: IListItem; index: number | null}>;
|
|
251
|
+
viewableItems: Array<{ item: IListItem; index: number | null }>;
|
|
235
252
|
}) => {
|
|
236
253
|
if (isProgrammaticScroll.current) {
|
|
237
254
|
// Ignore transient updates while we are animating to a specific index
|
|
@@ -242,7 +259,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
242
259
|
const it = v.item;
|
|
243
260
|
const idx = v.index ?? -1;
|
|
244
261
|
if (!('isSection' in it) && idx >= allCountriesStartIndex) {
|
|
245
|
-
const name =
|
|
262
|
+
const name =
|
|
263
|
+
(it as ICountry)?.translations[language]?.common || '';
|
|
246
264
|
if (name) {
|
|
247
265
|
updated = name[0].toUpperCase();
|
|
248
266
|
}
|
|
@@ -250,7 +268,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
250
268
|
}
|
|
251
269
|
}
|
|
252
270
|
setActiveLetter(updated);
|
|
253
|
-
}
|
|
271
|
+
}
|
|
254
272
|
).current;
|
|
255
273
|
|
|
256
274
|
const renderFlatList = () => {
|
|
@@ -260,12 +278,15 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
260
278
|
style={[
|
|
261
279
|
styles.countryNotFoundContainer,
|
|
262
280
|
countrySelectStyle?.countryNotFoundContainer,
|
|
263
|
-
]}
|
|
281
|
+
]}
|
|
282
|
+
>
|
|
264
283
|
<Text
|
|
265
284
|
style={[
|
|
266
285
|
styles.countryNotFoundMessage,
|
|
267
286
|
countrySelectStyle?.countryNotFoundMessage,
|
|
268
|
-
]}
|
|
287
|
+
]}
|
|
288
|
+
allowFontScaling={allowFontScaling}
|
|
289
|
+
>
|
|
269
290
|
{countryNotFoundMessage ||
|
|
270
291
|
translations.searchNotFoundMessage[
|
|
271
292
|
language as ICountrySelectLanguages
|
|
@@ -291,7 +312,9 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
291
312
|
keyExtractor={keyExtractor}
|
|
292
313
|
renderItem={renderItem}
|
|
293
314
|
keyboardShouldPersistTaps="handled"
|
|
294
|
-
showsVerticalScrollIndicator={
|
|
315
|
+
showsVerticalScrollIndicator={
|
|
316
|
+
showsVerticalScrollIndicator || false
|
|
317
|
+
}
|
|
295
318
|
style={[styles.list, countrySelectStyle?.list]}
|
|
296
319
|
onViewableItemsChanged={onViewableItemsChanged}
|
|
297
320
|
onMomentumScrollEnd={() => {
|
|
@@ -301,9 +324,12 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
301
324
|
// Fallback if momentum does not trigger
|
|
302
325
|
isProgrammaticScroll.current = false;
|
|
303
326
|
}}
|
|
304
|
-
onScrollToIndexFailed={({index, averageItemLength}) => {
|
|
327
|
+
onScrollToIndexFailed={({ index, averageItemLength }) => {
|
|
305
328
|
// Simple recovery: estimate offset, then retry scrollToIndex after measurement
|
|
306
|
-
const estimatedOffset = Math.max(
|
|
329
|
+
const estimatedOffset = Math.max(
|
|
330
|
+
0,
|
|
331
|
+
(averageItemLength || 0) * index
|
|
332
|
+
);
|
|
307
333
|
flatListRef.current?.scrollToOffset({
|
|
308
334
|
offset: estimatedOffset,
|
|
309
335
|
animated: false,
|
|
@@ -321,7 +347,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
321
347
|
};
|
|
322
348
|
|
|
323
349
|
const renderItem: ListRenderItem<IListItem> = useCallback(
|
|
324
|
-
({item, index}) => {
|
|
350
|
+
({ item, index }) => {
|
|
325
351
|
if ('isSection' in item) {
|
|
326
352
|
if (sectionTitleComponent) {
|
|
327
353
|
return sectionTitleComponent(item);
|
|
@@ -330,7 +356,12 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
330
356
|
<Text
|
|
331
357
|
testID="countrySelectSectionTitle"
|
|
332
358
|
accessibilityRole="header"
|
|
333
|
-
style={[
|
|
359
|
+
style={[
|
|
360
|
+
styles.sectionTitle,
|
|
361
|
+
countrySelectStyle?.sectionTitle,
|
|
362
|
+
]}
|
|
363
|
+
allowFontScaling={allowFontScaling}
|
|
364
|
+
>
|
|
334
365
|
{popularCountriesTitle && index === 0
|
|
335
366
|
? popularCountriesTitle
|
|
336
367
|
: allCountriesTitle && index > 0
|
|
@@ -345,7 +376,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
345
376
|
}
|
|
346
377
|
|
|
347
378
|
const countryItem = item as ICountry;
|
|
348
|
-
const selected =
|
|
379
|
+
const selected =
|
|
380
|
+
isMultiSelect && isCountrySelected(countryItem.cca2);
|
|
349
381
|
return (
|
|
350
382
|
<CountryItem
|
|
351
383
|
country={countryItem}
|
|
@@ -354,8 +386,10 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
354
386
|
theme={theme as IThemeProps}
|
|
355
387
|
language={language}
|
|
356
388
|
countrySelectStyle={countrySelectStyle}
|
|
389
|
+
customFlag={customFlag}
|
|
357
390
|
accessibilityLabel={accessibilityLabelCountryItem}
|
|
358
391
|
accessibilityHint={accessibilityHintCountryItem}
|
|
392
|
+
allowFontScaling={allowFontScaling}
|
|
359
393
|
/>
|
|
360
394
|
);
|
|
361
395
|
},
|
|
@@ -366,7 +400,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
366
400
|
sectionTitleComponent,
|
|
367
401
|
isMultiSelect,
|
|
368
402
|
isCountrySelected,
|
|
369
|
-
]
|
|
403
|
+
]
|
|
370
404
|
);
|
|
371
405
|
|
|
372
406
|
const renderAlphabetFilter = () => {
|
|
@@ -379,10 +413,19 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
379
413
|
countries={countriesList}
|
|
380
414
|
allCountriesStartIndex={allCountriesStartIndex}
|
|
381
415
|
countrySelectStyle={countrySelectStyle}
|
|
382
|
-
accessibilityLabelAlphabetFilter={
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
416
|
+
accessibilityLabelAlphabetFilter={
|
|
417
|
+
accessibilityLabelAlphabetFilter
|
|
418
|
+
}
|
|
419
|
+
accessibilityHintAlphabetFilter={
|
|
420
|
+
accessibilityHintAlphabetFilter
|
|
421
|
+
}
|
|
422
|
+
accessibilityLabelAlphabetLetter={
|
|
423
|
+
accessibilityLabelAlphabetLetter
|
|
424
|
+
}
|
|
425
|
+
accessibilityHintAlphabetLetter={
|
|
426
|
+
accessibilityHintAlphabetLetter
|
|
427
|
+
}
|
|
428
|
+
allowFontScaling={allowFontScaling}
|
|
386
429
|
/>
|
|
387
430
|
);
|
|
388
431
|
};
|
|
@@ -390,7 +433,11 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
390
433
|
const HeaderModal =
|
|
391
434
|
showSearchInput || showCloseButton ? (
|
|
392
435
|
<View
|
|
393
|
-
style={[
|
|
436
|
+
style={[
|
|
437
|
+
styles.searchContainer,
|
|
438
|
+
countrySelectStyle?.searchContainer,
|
|
439
|
+
]}
|
|
440
|
+
>
|
|
394
441
|
{(showCloseButton || isFullScreen) && renderCloseButton()}
|
|
395
442
|
{showSearchInput && renderSearchInput()}
|
|
396
443
|
</View>
|
|
@@ -398,7 +445,7 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
398
445
|
|
|
399
446
|
const ContentModal = (
|
|
400
447
|
<>
|
|
401
|
-
<View style={{flex: 1}}>{renderFlatList()}</View>
|
|
448
|
+
<View style={{ flex: 1 }}>{renderFlatList()}</View>
|
|
402
449
|
{showAlphabetFilter && <View>{renderAlphabetFilter()}</View>}
|
|
403
450
|
</>
|
|
404
451
|
);
|
|
@@ -424,7 +471,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
424
471
|
styles={styles}
|
|
425
472
|
countrySelectStyle={countrySelectStyle}
|
|
426
473
|
header={HeaderModal}
|
|
427
|
-
{...props}
|
|
474
|
+
{...props}
|
|
475
|
+
>
|
|
428
476
|
{ContentModal}
|
|
429
477
|
</FullscreenModal>
|
|
430
478
|
);
|
|
@@ -449,7 +497,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
449
497
|
styles={styles}
|
|
450
498
|
countrySelectStyle={countrySelectStyle}
|
|
451
499
|
header={HeaderModal}
|
|
452
|
-
{...props}
|
|
500
|
+
{...props}
|
|
501
|
+
>
|
|
453
502
|
{ContentModal}
|
|
454
503
|
</PopupModal>
|
|
455
504
|
);
|
|
@@ -478,7 +527,8 @@ export const CountrySelect: React.FC<ICountrySelectProps> = ({
|
|
|
478
527
|
initialBottomsheetHeight={initialBottomsheetHeight}
|
|
479
528
|
dragHandleIndicatorComponent={dragHandleIndicatorComponent}
|
|
480
529
|
header={HeaderModal}
|
|
481
|
-
{...props}
|
|
530
|
+
{...props}
|
|
531
|
+
>
|
|
482
532
|
{ContentModal}
|
|
483
533
|
</BottomSheetModal>
|
|
484
534
|
);
|
|
@@ -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
|
};
|
package/lib/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
ICountrySelectProps,
|
|
8
8
|
ICountrySelectStyle,
|
|
9
9
|
ICountrySelectLanguages,
|
|
10
|
+
ISectionTitle,
|
|
10
11
|
} from './interface';
|
|
11
12
|
|
|
12
13
|
declare function getAllCountries(): ICountry[];
|
|
@@ -16,21 +17,25 @@ declare function getCountryByCca2(cca2: string): ICountry | undefined;
|
|
|
16
17
|
declare function getCountryByCca3(cca3: string): ICountry | undefined;
|
|
17
18
|
|
|
18
19
|
declare function getCountriesByCallingCode(
|
|
19
|
-
callingCode: string
|
|
20
|
+
callingCode: string
|
|
20
21
|
): ICountry[] | undefined;
|
|
21
22
|
|
|
22
23
|
declare function getCountriesByName(
|
|
23
24
|
name: string,
|
|
24
|
-
language: ICountrySelectLanguages
|
|
25
|
+
language: ICountrySelectLanguages
|
|
25
26
|
): ICountry[] | undefined;
|
|
26
27
|
|
|
27
|
-
declare function getCountriesByRegion(
|
|
28
|
+
declare function getCountriesByRegion(
|
|
29
|
+
region: string
|
|
30
|
+
): ICountry[] | undefined;
|
|
28
31
|
|
|
29
32
|
declare function getCountriesBySubregion(
|
|
30
|
-
subregion: string
|
|
33
|
+
subregion: string
|
|
31
34
|
): ICountry[] | undefined;
|
|
32
35
|
|
|
33
|
-
declare function getContriesDependents(
|
|
36
|
+
declare function getContriesDependents(
|
|
37
|
+
cca2: string
|
|
38
|
+
): ICountry[] | undefined;
|
|
34
39
|
|
|
35
40
|
declare function getCountriesIndependents(): ICountry[] | undefined;
|
|
36
41
|
|
|
@@ -45,6 +50,7 @@ export {
|
|
|
45
50
|
ICountrySelectProps,
|
|
46
51
|
ICountrySelectStyle,
|
|
47
52
|
ICountrySelectLanguages,
|
|
53
|
+
ISectionTitle,
|
|
48
54
|
getAllCountries,
|
|
49
55
|
getCountryByCca2,
|
|
50
56
|
getCountryByCca3,
|
package/lib/index.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {CountrySelect} from './components';
|
|
1
|
+
import { CountrySelect } from './components';
|
|
2
2
|
import {
|
|
3
3
|
ICountry,
|
|
4
4
|
ICountryCca2,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
ICountrySelectProps,
|
|
7
7
|
ICountrySelectStyle,
|
|
8
8
|
ICountrySelectLanguages,
|
|
9
|
+
ISectionTitle,
|
|
9
10
|
} from './interface';
|
|
10
11
|
import {
|
|
11
12
|
getAllCountries,
|
|
@@ -40,4 +41,5 @@ export type {
|
|
|
40
41
|
ICountrySelectProps,
|
|
41
42
|
ICountrySelectStyle,
|
|
42
43
|
ICountrySelectLanguages,
|
|
44
|
+
ISectionTitle,
|
|
43
45
|
};
|
|
@@ -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
|
}
|
package/lib/interface/country.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {ICountryCca2} from './countryCca2';
|
|
1
|
+
import { ICountryCca2 } from './countryCca2';
|
|
2
2
|
|
|
3
3
|
// Currency interface
|
|
4
4
|
export interface ICountryCurrency {
|
|
@@ -107,5 +107,6 @@ export interface ICountry {
|
|
|
107
107
|
borders: string[];
|
|
108
108
|
area: number;
|
|
109
109
|
flag: string;
|
|
110
|
+
customFlag?: React.ReactElement | null | undefined;
|
|
110
111
|
demonyms: ICountryDemonyms;
|
|
111
112
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ICountry } from './country';
|
|
3
|
+
import { IThemeProps } from './theme';
|
|
4
|
+
import { ICountrySelectStyle } from './countrySelectStyles';
|
|
5
|
+
import { ICountrySelectLanguages } from './countrySelectLanguages';
|
|
5
6
|
|
|
6
7
|
export interface ICountryItemProps {
|
|
7
8
|
country: ICountry;
|
|
@@ -10,6 +11,10 @@ export interface ICountryItemProps {
|
|
|
10
11
|
onSelect: (country: ICountry) => void;
|
|
11
12
|
language: ICountrySelectLanguages;
|
|
12
13
|
countrySelectStyle?: ICountrySelectStyle;
|
|
14
|
+
customFlag?: (
|
|
15
|
+
country: ICountry
|
|
16
|
+
) => React.ReactElement | null | undefined;
|
|
13
17
|
accessibilityLabel?: string;
|
|
14
18
|
accessibilityHint?: string;
|
|
19
|
+
allowFontScaling?: boolean;
|
|
15
20
|
}
|
|
@@ -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;
|
|
@@ -34,6 +34,9 @@ interface ICountrySelectBaseProps extends ModalProps, IThemeProps {
|
|
|
34
34
|
countryItemComponent?: (item: ICountry) => React.ReactElement;
|
|
35
35
|
sectionTitleComponent?: (item: ISectionTitle) => React.ReactElement;
|
|
36
36
|
closeButtonComponent?: () => React.ReactElement;
|
|
37
|
+
customFlag?: (
|
|
38
|
+
country: ICountry
|
|
39
|
+
) => React.ReactElement | null | undefined;
|
|
37
40
|
popularCountriesTitle?: string;
|
|
38
41
|
allCountriesTitle?: string;
|
|
39
42
|
showsVerticalScrollIndicator?: boolean;
|
|
@@ -52,6 +55,7 @@ interface ICountrySelectBaseProps extends ModalProps, IThemeProps {
|
|
|
52
55
|
accessibilityHintAlphabetFilter?: string;
|
|
53
56
|
accessibilityLabelAlphabetLetter?: string;
|
|
54
57
|
accessibilityHintAlphabetLetter?: string;
|
|
58
|
+
allowFontScaling?: boolean;
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
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.3",
|
|
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",
|