react-native-modal
Advanced tools
Comparing version 6.5.0 to 7.0.0
{ | ||
"name": "react-native-modal", | ||
"version": "6.5.0", | ||
"version": "7.0.0", | ||
"description": "An enhanced React-Native modal", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
@@ -6,4 +6,4 @@ # react-native-modal | ||
An enhanced, animated and customizable react-native modal. | ||
An enhanced, animated and customizable react-native modal. | ||
The aim of `react-native-modal` is expanding the original react-native `Modal` component by adding animations and styles customization options while still providing a plain-simple API. | ||
@@ -13,9 +13,9 @@ | ||
* Smooth enter/exit animations | ||
* Plain simple and flexible APIs | ||
* Customizable backdrop opacity, color and timing | ||
* Listeners for the modal animations ending | ||
* Resize itself correctly on device rotation | ||
* Swipeable | ||
* Scrollable | ||
- Smooth enter/exit animations | ||
- Plain simple and flexible APIs | ||
- Customizable backdrop opacity, color and timing | ||
- Listeners for the modal animations ending | ||
- Resize itself correctly on device rotation | ||
- Swipeable | ||
- Scrollable | ||
@@ -27,5 +27,9 @@ ## Demo | ||
<img src="https://raw.githubusercontent.com/mmazzarolo/react-native-modal-datetime-picker/master/extras/datetimepicker-ios.gif" height="300" /> | ||
<img src="https://raw.githubusercontent.com/pistonsky/react-native-modal/master/.github/example-modal.gif" height="300" /> | ||
<img src="https://raw.githubusercontent.com/mmazzarolo/react-native-modal/master/.github/example-modal.gif" height="300" /> | ||
</p> | ||
<p align="center"> | ||
New GIFs of your modal are warmly welcome! Feel free to submit a PR. 🎉 | ||
</p> | ||
## Setup | ||
@@ -39,3 +43,3 @@ | ||
1. Import react-native-modal: | ||
1. Import react-native-modal: | ||
@@ -46,3 +50,3 @@ ```javascript | ||
2. Create a modal and nest its content inside of it: | ||
2. Create a modal and nest its content inside of it: | ||
@@ -63,3 +67,3 @@ ```javascript | ||
3. Then simply show it by setting the `isVisible` prop to true: | ||
3. Then simply show it by setting the `isVisible` prop to true: | ||
@@ -138,2 +142,4 @@ ```javascript | ||
| children | node | **REQUIRED** | The modal content | | ||
| deviceHeight | number | null | Device height (useful on devices that can hide the navigation bar) | | ||
| deviceWidth | number | null | Device width (useful on devices that can hide the navigation bar) | | ||
| isVisible | bool | **REQUIRED** | Show the modal? | | ||
@@ -163,13 +169,26 @@ | onBackButtonPress | func | () => null | Called when the Android back button is pressed | | ||
Checkout the package [react-native-extra-dimensions-android](https://github.com/Sunhat/react-native-extra-dimensions-android) | ||
React-Native has a few issues detecting the correct device width/height of some devices. | ||
If you're experiencing this issue, you'll need to install [`react-native-extra-dimensions-android`](https://github.com/Sunhat/react-native-extra-dimensions-android). | ||
Then, provide the real window height (obtained from `react-native-extra-dimensions-android`) to the modal: | ||
To use, here's an example: | ||
```javascript | ||
render() { | ||
const deviceWidth = Dimensions.get("window").width; | ||
const deviceHeight = Platform.OS === "ios" | ||
? Dimensions.get("window").height | ||
: require("react-native-extra-dimensions-android").get("REAL_WINDOW_HEIGHT"); | ||
return ( | ||
<Modal | ||
isVisible={this.state.isVisible} | ||
deviceHeight={deviceWidth} | ||
deviceHeight={deviceHeight} | ||
> | ||
<View style={{ flex: 1 }}> | ||
<Text>I am the modal content!</Text> | ||
</View> | ||
</Modal> | ||
) | ||
} | ||
``` | ||
const IOS = Platform.OS === "ios"; | ||
const WIDTH = Dimensions.get("window").width; | ||
const HEIGHT = IOS | ||
? Dimensions.get("window").height | ||
: require("react-native-extra-dimensions-android").get("REAL_WINDOW_HEIGHT"); | ||
``` | ||
@@ -221,2 +240,15 @@ ### How can I hide the modal by pressing outside of its content? | ||
Also, if you're providing the `deviceHeight` and `deviceWidth` props you'll have to manually update them when the layout changes. | ||
### I can't show multiple modals one after another | ||
Unfortunately right now react-native doesn't allow multiple modals to be displayed at the same time. | ||
This means that, in `react-native-modal`, if you want to immediately show a new modal after closing one you must first make sure that the modal that your closing has completed its hiding animation by using the `onModalHide` prop. | ||
### I can't show multiple modals at the same time | ||
See the question above. | ||
Showing multiple modals (or even alerts/dialogs) at the same time is not doable because of a react-native bug. | ||
That said, I would strongly advice against using multiple modals at the same time because, most often than not, this leads to a bad UX, especially on mobile (just my opinion). | ||
## Available animations | ||
@@ -226,3 +258,3 @@ | ||
## Acknowledgements | ||
## Acknowledgements | ||
@@ -229,0 +261,0 @@ Thanks [@oblador](https://github.com/oblador) for react-native-animatable, [@brentvatne](https://github.com/brentvatne) for the npm namespace and to anyone who contributed to this library! |
@@ -6,3 +6,8 @@ declare module "react-native-modal" { | ||
type AnimationConfig = string | { from: Object; to: Object }; | ||
type Orientation = "portrait" | "portrait-upside-down" | "landscape" | "landscape-left" | "landscape-right"; | ||
type Orientation = | ||
| "portrait" | ||
| "portrait-upside-down" | ||
| "landscape" | ||
| "landscape-left" | ||
| "landscape-right"; | ||
@@ -21,2 +26,4 @@ export interface ModalProps { | ||
children: ReactNode; | ||
deviceHeight?: number; | ||
deviceWidth?: number; | ||
hideModalContentWhileAnimating?: boolean; | ||
@@ -36,2 +43,7 @@ isVisible: boolean; | ||
supportedOrientations?: Orientation[]; | ||
onDismiss?: () => void; | ||
onShow?: () => void; | ||
hardwareAccelerated?: boolean; | ||
onOrientationChange?: (orientation: "portrait" | "landscape") => void; | ||
presentationStyle?: "fullScreen" | "pageSheet" | "formSheet" | "overFullScreen"; | ||
} | ||
@@ -38,0 +50,0 @@ |
@@ -47,2 +47,4 @@ import React, { Component } from "react"; | ||
children: PropTypes.node.isRequired, | ||
deviceHeight: PropTypes.number, | ||
deviceWidth: PropTypes.number, | ||
isVisible: PropTypes.bool.isRequired, | ||
@@ -84,2 +86,4 @@ hideModalContentWhileAnimating: PropTypes.bool, | ||
onModalShow: () => null, | ||
deviceHeight: null, | ||
deviceWidth: null, | ||
onModalHide: () => null, | ||
@@ -131,3 +135,3 @@ isVisible: false, | ||
componentWillReceiveProps(nextProps) { | ||
UNSAFE_componentWillReceiveProps(nextProps) { | ||
if (!this.state.isVisible && nextProps.isVisible) { | ||
@@ -163,3 +167,3 @@ this.setState({ isVisible: true, showContent: true }); | ||
componentWillUnmount() { | ||
UNSAFE_componentWillUnmount() { | ||
DeviceEventEmitter.removeListener( | ||
@@ -177,3 +181,3 @@ "didUpdateDimensions", | ||
// On modal close request, we slide the view down and fade out the backdrop | ||
this._close(); | ||
this.close(); | ||
} | ||
@@ -195,2 +199,9 @@ } | ||
this.panResponder = PanResponder.create({ | ||
onMoveShouldSetPanResponder: (evt, gestureState) => { | ||
// The number "4" is just a good tradeoff to make the panResponder | ||
// work correctly even when the modal has touchable buttons. | ||
// For reference: | ||
// https://github.com/react-native-community/react-native-modal/pull/197 | ||
return Math.abs(gestureState.dx) >= 4 || Math.abs(gestureState.dy) >= 4; | ||
}, | ||
onStartShouldSetPanResponder: () => { | ||
@@ -206,4 +217,5 @@ if (this.props.scrollTo) { | ||
// Dim the background while swiping the modal | ||
const deviceWidth = this.props.deviceWidth || this.state.deviceWidth; | ||
const accDistance = this.getAccDistancePerDirection(gestureState); | ||
const newOpacityFactor = 1 - accDistance / this.state.deviceWidth; | ||
const newOpacityFactor = 1 - accDistance / deviceWidth; | ||
if (this.isSwipeDirectionAllowed(gestureState)) { | ||
@@ -311,10 +323,13 @@ this.backdropRef && | ||
handleDimensionsUpdate = dimensionsUpdate => { | ||
// Here we update the device dimensions in the state if the layout changed (triggering a render) | ||
const deviceWidth = Dimensions.get("window").width; | ||
const deviceHeight = Dimensions.get("window").height; | ||
if ( | ||
deviceWidth !== this.state.deviceWidth || | ||
deviceHeight !== this.state.deviceHeight | ||
) { | ||
this.setState({ deviceWidth, deviceHeight }); | ||
if (!this.props.deviceHeight && !this.props.deviceWidth) { | ||
// Here we update the device dimensions in the state if the layout changed | ||
// (triggering a render) | ||
const deviceWidth = Dimensions.get("window").width; | ||
const deviceHeight = Dimensions.get("window").height; | ||
if ( | ||
deviceWidth !== this.state.deviceWidth || | ||
deviceHeight !== this.state.deviceHeight | ||
) { | ||
this.setState({ deviceWidth, deviceHeight }); | ||
} | ||
} | ||
@@ -345,3 +360,3 @@ }; | ||
if (!this.props.isVisible) { | ||
this._close(); | ||
this.close(); | ||
} else { | ||
@@ -355,3 +370,3 @@ this.props.onModalShow(); | ||
_close = () => { | ||
close = () => { | ||
if (this.transitionLock) return; | ||
@@ -415,2 +430,4 @@ this.transitionLock = true; | ||
children, | ||
deviceHeight: deviceHeightProp, | ||
deviceWidth: deviceWidthProp, | ||
isVisible, | ||
@@ -424,3 +441,4 @@ onModalShow, | ||
} = this.props; | ||
const { deviceWidth, deviceHeight } = this.state; | ||
const deviceWidth = deviceHeightProp || this.state.deviceWidth; | ||
const deviceHeight = deviceHeightProp || this.state.deviceHeight; | ||
@@ -427,0 +445,0 @@ const computedStyle = [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
34685
557
254