Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modernized Packages, multiple fixes #488

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .rgignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
src/assets/data/countries-emoji.json
data/countries*.json
281 changes: 136 additions & 145 deletions App.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,28 @@
import React, { useState } from 'react'
import {
Text,
StyleSheet,
PixelRatio,
Switch,
Button,
ScrollView,
} from 'react-native'
import CountryPicker, { CountryModalProvider } from './src/'
import { Text, StyleSheet, PixelRatio, Switch, Button, Pressable, ScrollView, TextInput, View } from 'react-native'
import CountryPicker, { CountryModalProvider, TranslationLanguageCodeList } from './src/'
import { CountryCode, Country } from './src/types'
import { Row } from './src/Row'
import { DARK_THEME } from './src/CountryTheme'

const styles = StyleSheet.create({
container: {
paddingVertical: 10,
justifyContent: 'center',
alignItems: 'center',
},
welcome: {
fontSize: 17,
textAlign: 'center',
margin: 5,
},
instructions: {
fontSize: 10,
textAlign: 'center',
color: '#888',
marginBottom: 0,
},
data: {
maxWidth: 250,
padding: 10,
marginTop: 7,
backgroundColor: '#ddd',
borderColor: '#888',
borderWidth: 1 / PixelRatio.get(),
color: '#777',
},
mainBox: { maxHeight: 2000, paddingVertical: 10, justifyContent: 'space-between', alignItems: 'center', flex: 1, },
container: { paddingVertical: 10, justifyContent: 'space-between', alignItems: 'center', },
button: { paddingVertical: 5, paddingHorizontal: 10, marginHorizontal: 4, backgroundColor: '#cfd4e7' },
countryPickerBox: { maxHeight: '30%', paddingVertical: 5, paddingHorizontal: 10, backgroundColor: '#eee' },
optionsBox: { maxHeight: '30%', marginVertical: 10, borderColor: '#abc', borderWidth: 1 / PixelRatio.get() },
dataBox: { maxHeight: '25%', flex: 1, width: '90%', marginHorizontal: 5, borderWidth: 1 / PixelRatio.get() },
textEntryBox: { flex: 1, padding: 5, marginLeft: 20, flexDirection: 'row', justifyContent: 'flex-start' },
buttonsBox: { flexDirection: 'row', marginTop: 2 },
//
welcome: { fontSize: 17, textAlign: 'center', marginHorizontal: 5, marginVertical: 10, },
heading: { fontSize: 17, textAlign: 'center', marginHorizontal: 5, marginVertical: 10, },
instructions: { fontSize: 10, textAlign: 'center', color: '#888', marginBottom: 5, paddingHorizontal: 15, },
data: { padding: 10, marginTop: 7, backgroundColor: '#ddd', borderColor: '#888', borderWidth: 1 / PixelRatio.get(), color: '#777' },
//
textEntryLabel: { flex: 2, width: '25%' },
textEntryInput: { flex: 3, marginLeft: 2 },
//
})

interface OptionProps {
Expand All @@ -55,137 +40,143 @@ const Option = ({ value, onValueChange, title }: OptionProps) => (
export default function App() {
const [countryCode, setCountryCode] = useState<CountryCode | undefined>()
const [country, setCountry] = useState<Country>(null)
const [withCountryNameButton, setWithCountryNameButton] = useState<boolean>(
false,
)
//
const [withCountryNameButton, setWithCountryNameButton] = useState<boolean>(false)
const [withCurrencyButton, setWithCurrencyButton] = useState<boolean>(false)
const [withFlagButton, setWithFlagButton] = useState<boolean>(true)
const [withCallingCodeButton, setWithCallingCodeButton] = useState<boolean>(
false,
)
const [withCallingCodeButton, setWithCallingCodeButton] = useState<boolean>(false)
const [withFlag, setWithFlag] = useState<boolean>(true)
const [withEmoji, setWithEmoji] = useState<boolean>(true)
const [withFilter, setWithFilter] = useState<boolean>(true)
const [withAlphaFilter, setWithAlphaFilter] = useState<boolean>(false)
const [withLetterScroller, setWithLetterScroller] = useState<boolean>(true)
const [withCallingCode, setWithCallingCode] = useState<boolean>(false)
const [withCurrency, setWithCurrency] = useState<boolean>(false)
const [withModal, setWithModal] = useState<boolean>(true)
const [withModal, setWithModal] = useState<boolean>(false)
const [visible, setVisible] = useState<boolean>(false)
const [withDependents, setWithDependents] = useState<boolean>(false)
const [dark, setDark] = useState<boolean>(false)
const [fontScaling, setFontScaling] = useState<boolean>(true)
const [disableNativeModal, setDisableNativeModal] = useState<boolean>(false)

const [preferredCountriesStr, setPreferredCountriesStr] = useState<string>('UA')
const [excludeCountriesStr, setExcludeCountriesStr] = useState<string>('RU')
const [translation, setTranslation] = useState<string>(null)

const resetCountry = () => {
setCountry(null)
setCountryCode(null)
}
const onSelect = (country: Country) => {
setCountryCode(country.cca2)
setCountry(country)
}
const switchVisible = () => setVisible(!visible)

const excludeCountries = excludeCountriesStr.toUpperCase().trim().split(/\W+/)
const preferredCountries = preferredCountriesStr.toUpperCase().trim().split(/\W+/)

return (
<CountryModalProvider>
<ScrollView contentContainerStyle={styles.container}>
<View style={styles.mainBox}>
<Text style={styles.welcome}>Welcome to Country Picker !</Text>
<Option
title='With country name on button'
value={withCountryNameButton}
onValueChange={setWithCountryNameButton}
/>
<Option
title='With currency on button'
value={withCurrencyButton}
onValueChange={setWithCurrencyButton}
/>
<Option
title='With calling code on button'
value={withCallingCodeButton}
onValueChange={setWithCallingCodeButton}
/>
<Option
title='With flag'
value={withFlag}
onValueChange={setWithFlag}
/>
<Option
title='With font scaling'
value={fontScaling}
onValueChange={setFontScaling}
/>
<Option
title='With emoji'
value={withEmoji}
onValueChange={setWithEmoji}
/>
<Option
title='With filter'
value={withFilter}
onValueChange={setWithFilter}
/>
<Option
title='With calling code'
value={withCallingCode}
onValueChange={setWithCallingCode}
/>
<Option
title='With currency'
value={withCurrency}
onValueChange={setWithCurrency}
/>
<Option
title='With alpha filter code'
value={withAlphaFilter}
onValueChange={setWithAlphaFilter}
/>
<Option
title='Without native modal'
value={disableNativeModal}
onValueChange={setDisableNativeModal}
/>
<Option
title='With modal'
value={withModal}
onValueChange={setWithModal}
/>
<Option title='With dark theme' value={dark} onValueChange={setDark} />
<Option
title='With flag button'
value={withFlagButton}
onValueChange={setWithFlagButton}
/>
<CountryPicker
theme={dark ? DARK_THEME : {}}
{...{
allowFontScaling: fontScaling,
countryCode,
withFilter,
excludeCountries: ['FR'],
withFlag,
withCurrencyButton,
withCallingCodeButton,
withCountryNameButton,
withAlphaFilter,
withCallingCode,
withCurrency,
withEmoji,
withModal,
withFlagButton,
onSelect,
disableNativeModal,
preferredCountries: ['US', 'GB'],
modalProps: {
visible,
},
onClose: () => setVisible(false),
onOpen: () => setVisible(true),
}}
/>
<Text style={styles.instructions}>Press on the flag to open modal</Text>
<Button
title={'Open modal from outside using visible props'}
onPress={switchVisible}
/>
{country !== null && (
<Text style={styles.data}>{JSON.stringify(country, null, 0)}</Text>
)}
</ScrollView>
<Text style={styles.instructions}>Press on the flag/placeholder to open modal:</Text>

<View style={styles.countryPickerBox}>
<CountryPicker
theme={dark ? DARK_THEME : {}}
{...{
allowFontScaling: fontScaling,
countryCode,
withFilter,
excludeCountries,
withFlag,
withCurrencyButton,
withCallingCodeButton,
withCountryNameButton,
withLetterScroller,
withCallingCode,
withCurrency,
withEmoji,
withModal,
withFlagButton,
withDependents,
onSelect,
disableNativeModal,
preferredCountries,
translation,
modalProps: {
visible,
},
onClose: () => setVisible(false),
onOpen: () => setVisible(true),
placeholder: '(-country-)',
}}
/>
</View>

<View style={styles.optionsBox}>
<ScrollView>
<Text style={styles.heading}>Options:</Text>
<View style={styles.textEntryBox}>
<Text style={styles.textEntryLabel}>Preferred Countries: </Text>
<TextInput
style={styles.textEntryInput}
value={preferredCountriesStr}
onChangeText={setPreferredCountriesStr}
autoCapitalize='characters'
/>
</View>
<View style={styles.textEntryBox}>
<Text style={styles.textEntryLabel}>Exclude Countries: </Text>
<TextInput
style={styles.textEntryInput}
value={excludeCountriesStr}
onChangeText={setExcludeCountriesStr}
autoCapitalize='characters'
/>
</View>
<View style={styles.textEntryBox}>
<Text style={styles.textEntryLabel}>Translation:</Text>
<TextInput style={styles.textEntryInput} autoCorrect={false} value={translation} onChangeText={setTranslation} autoCapitalize='none' />
</View>
<Text style={styles.instructions}>{TranslationLanguageCodeList.join(' / ')}</Text>
<Text style={styles.instructions}>
ex: {excludeCountries.join('|')} pr: {preferredCountries.join('|')}
</Text>
<Option title='Show country name on button' value={withCountryNameButton} onValueChange={setWithCountryNameButton} />
<Option title='Show currency on button' value={withCurrencyButton} onValueChange={setWithCurrencyButton} />
<Option title='Show calling code on button' value={withCallingCodeButton} onValueChange={setWithCallingCodeButton} />
<Option title='Show flag on button' value={withFlagButton} onValueChange={setWithFlagButton} />
<Option title='With font scaling' value={fontScaling} onValueChange={setFontScaling} />
<Option title='Use emoji (not image) flags' value={withEmoji} onValueChange={setWithEmoji} />
<Option title='Provide type-to-filter entry' value={withFilter} onValueChange={setWithFilter} />
<Option title='Show flag in picker' value={withFlag} onValueChange={setWithFlag} />
<Option title='Show calling code in picker' value={withCallingCode} onValueChange={setWithCallingCode} />
<Option title='Show currency in picker' value={withCurrency} onValueChange={setWithCurrency} />
<Option title='Show letter scroller on right' value={withLetterScroller} onValueChange={setWithLetterScroller} />
<Option title='Include non-independent states' value={withDependents} onValueChange={setWithDependents} />
<Option title='Without native modal' value={disableNativeModal} onValueChange={setDisableNativeModal} />
<Option title='With modal' value={withModal} onValueChange={setWithModal} />
<Option title='With dark theme' value={dark} onValueChange={setDark} />
</ScrollView>
</View>

<View style={styles.dataBox}>
<ScrollView>
<Text style={styles.heading}>Result:</Text>
<Text style={styles.data}>{JSON.stringify(country, null, 2)}</Text>
</ScrollView>
</View>

<View style={styles.buttonsBox}>
<Pressable onPress={resetCountry} style={styles.button}>
<Text>Reset Country</Text>
</Pressable>
<Pressable onPress={switchVisible} style={styles.button}>
<Text>Open Modal Picker</Text>
</Pressable>
</View>
</View>
</CountryModalProvider>
)
}
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,19 @@ export default function App() {
- `disableNativeModal?`: boolean (you have to wrap your all app with CountryModalProvider)
- `preferredCountries`: [CountryCode](https://github.com/xcarpentier/react-native-country-picker-modal/blob/master/src/types.ts#L254) preferred countries they appear first (`withAlphaFilter` must be false)

### Caveats

Dynamically changing the translation, excludeCountries, and some other
props that affect the country list may give inconsistent results. In
particular, the search index is only calculated on first use and so
the changes to new language or different excluded countries will be
inconsistent.

## Dark theme example

<p align="center">
<img alt="react-native-country-picker-modal-dark" src="https://user-images.githubusercontent.com/2692166/40585272-094f817a-61b0-11e8-9668-abff0aeddb0e.png" width=150>
</p>
<p align="center"> <img alt="react-native-country-picker-modal-dark"
src="https://user-images.githubusercontent.com/2692166/40585272-094f817a-61b0-11e8-9668-abff0aeddb0e.png"
width=150> </p>

A simple example to display a `CountryPicker` component with a dark theme.

Expand Down Expand Up @@ -181,6 +189,8 @@ YES : It used the world-countries package and image is stored into json and base
## Contribution

- [@xcapentier](mailto:[email protected]) The main author.
- [@kanimetov](https://github.com/kanimetov) -- Arabic and Hebrew translations.
- [@mrflip](https://github.com/mrflip) -- updated to Expo 46 and minor fixes.

## Questions

Expand Down
Loading