Skip to content

Commit

Permalink
fix not native modal
Browse files Browse the repository at this point in the history
  • Loading branch information
xcarpentier committed Feb 4, 2020
1 parent f31c5a9 commit c872c39
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 148 deletions.
190 changes: 101 additions & 89 deletions App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
Button,
ScrollView,
} from 'react-native'
import CountryPicker from './src/'
import CountryPicker, { CountryModalProvider } from './src/'
import { CountryCode, Country } from './src/types'
import { Row } from './src/Row'
import { DARK_THEME } from './src/CountryTheme'
Expand Down Expand Up @@ -63,7 +63,6 @@ export default function App() {
const [withCallingCodeButton, setWithCallingCodeButton] = useState<boolean>(
false,
)

const [withFlag, setWithFlag] = useState<boolean>(true)
const [withEmoji, setWithEmoji] = useState<boolean>(true)
const [withFilter, setWithFilter] = useState<boolean>(true)
Expand All @@ -73,98 +72,111 @@ export default function App() {
const [withModal, setWithModal] = useState<boolean>(true)
const [visible, setVisible] = useState<boolean>(false)
const [dark, setDark] = useState<boolean>(false)
const [disableNativeModal, setDisableNativeModal] = useState<boolean>(false)
const onSelect = (country: Country) => {
setCountryCode(country.cca2)
setCountry(country)
}
const switchVisible = () => setVisible(!visible)
return (
<ScrollView contentContainerStyle={styles.container}>
<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 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='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 : {}}
{...{
countryCode,
withFilter,
excludeCountries: ['FR'],
withFlag,
withCurrencyButton,
withCallingCodeButton,
withCountryNameButton,
withAlphaFilter,
withCallingCode,
withCurrency,
withEmoji,
withModal,
withFlagButton,
onSelect,
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>
<CountryModalProvider>
<ScrollView contentContainerStyle={styles.container}>
<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 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 : {}}
{...{
countryCode,
withFilter,
excludeCountries: ['FR'],
withFlag,
withCurrencyButton,
withCallingCodeButton,
withCountryNameButton,
withAlphaFilter,
withCallingCode,
withCurrency,
withEmoji,
withModal,
withFlagButton,
onSelect,
disableNativeModal,
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>
</CountryModalProvider>
)
}
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default function App() {
const [countryCode, setCountryCode] = useState<CountryCode>('FR')
const [country, setCountry] = useState<Country>(null)
const [withCountryNameButton, setWithCountryNameButton] = useState<boolean>(
false
false,
)
const [withFlag, setWithFlag] = useState<boolean>(true)
const [withEmoji, setWithEmoji] = useState<boolean>(true)
Expand All @@ -57,28 +57,28 @@ export default function App() {
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to Country Picker !</Text>
<Option
title="With country name on button"
title='With country name on button'
value={withCountryNameButton}
onValueChange={setWithCountryNameButton}
/>
<Option title="With flag" value={withFlag} onValueChange={setWithFlag} />
<Option title='With flag' value={withFlag} onValueChange={setWithFlag} />
<Option
title="With emoji"
title='With emoji'
value={withEmoji}
onValueChange={setWithEmoji}
/>
<Option
title="With filter"
title='With filter'
value={withFilter}
onValueChange={setWithFilter}
/>
<Option
title="With calling code"
title='With calling code'
value={withCallingCode}
onValueChange={setWithCallingCode}
/>
<Option
title="With alpha filter code"
title='With alpha filter code'
value={withAlphaFilter}
onValueChange={setWithAlphaFilter}
/>
Expand All @@ -91,7 +91,7 @@ export default function App() {
withAlphaFilter,
withCallingCode,
withEmoji,
onSelect
onSelect,
}}
visible
/>
Expand Down Expand Up @@ -137,6 +137,7 @@ export default function App() {
- `closeButtonImage?`: [ImageSourcePropType](https://facebook.github.io/react-native/docs/image#props)
- `closeButtonStyle?`: StyleProp<ViewStyle>
- `closeButtonImageStyle?`: StyleProp<ImageStyle>
- `disableNativeModal?`: boolean (you have to wrap your all app with CountryModalProvider)

## Dark theme example

Expand Down
88 changes: 42 additions & 46 deletions src/AnimatedModal.tsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,52 @@
import React from 'react'
import { Animated, Dimensions } from 'react-native'
import * as React from 'react'
import { Animated, Dimensions, StyleSheet } from 'react-native'

const { width: WINDOW_WIDTH, height: WINDOW_HEIGHT } = Dimensions.get('screen')
const { height } = Dimensions.get('window')

const duration = 300
const useNativeDriver = true

interface Props {
visible?: boolean
children: React.ReactNode
}

const styles = {
wrapper: {
position: 'absolute',
width: WINDOW_WIDTH,
height: WINDOW_HEIGHT,
left: 0,
top: 0,
zIndex: 100,
},
export const AnimatedModal = ({ children, visible }: Props) => {
const translateY = new Animated.Value(height)

const showModal = Animated.timing(translateY, {
toValue: 0,
duration,
useNativeDriver,
}).start

const hideModal = Animated.timing(translateY, {
toValue: height,
duration,
useNativeDriver,
}).start

React.useEffect(() => {
if (visible) {
showModal()
} else {
hideModal()
}
}, [visible])

return (
<Animated.View
style={{
...StyleSheet.absoluteFillObject,
transform: [{ translateY }],
zIndex: 99,
}}
>
{children}
</Animated.View>
)
}

export class AnimatedModal extends React.Component<Props> {
aniVal = new Animated.Value(WINDOW_HEIGHT)

componentDidUpdate(prevProps: Props) {
const { visible } = this.props
if (visible && !prevProps.visible) {
this.showModal()
}
if (!visible && prevProps.visible) {
this.hideModal()
}
}

hideModal(): void {
Animated.timing(this.aniVal, {
toValue: WINDOW_HEIGHT,
duration: 300,
}).start()
}

showModal(): void {
Animated.timing(this.aniVal, {
toValue: 0,
duration: 300,
}).start()
}

render() {
return (
<Animated.View style={[styles.wrapper, { top: this.aniVal }]}>
{this.props.children}
</Animated.View>
)
}
AnimatedModal.defaultProps = {
visible: false,
}
Loading

0 comments on commit c872c39

Please sign in to comment.