react-native-popover-view
Advanced tools
Comparing version 1.0.5 to 1.0.6
{ | ||
"name": "react-native-popover-view", | ||
"version": "1.0.5", | ||
"version": "1.0.6", | ||
"description": "A <Popover /> component for react-native", | ||
@@ -19,4 +19,3 @@ "main": "src/index.js", | ||
"start": "node_modules/react-native/packager/packager.sh", | ||
"test": "jest", | ||
"postinstall": "node ./check-rn.js" | ||
"test": "jest" | ||
}, | ||
@@ -51,8 +50,3 @@ "jest": { | ||
}, | ||
"peerDependencies": { | ||
"react-navigation": ">=2.0.0" | ||
}, | ||
"dependencies": { | ||
"fs": "^0.0.1-security" | ||
} | ||
"dependencies": {} | ||
} |
@@ -16,2 +16,4 @@ 'use strict'; | ||
const DEBUG = true; | ||
const PLACEMENT_OPTIONS = Object.freeze({ | ||
@@ -47,4 +49,3 @@ TOP: 'top', | ||
translateArrow: new Animated.ValueXY() | ||
}, | ||
viewport: null | ||
} | ||
}; | ||
@@ -57,9 +58,23 @@ | ||
setDefaultDisplayArea(evt) { | ||
if (this.safeAreaViewReady || !isIOS()) { | ||
let newDisplayArea = new Rect(evt.nativeEvent.layout.x + 10, evt.nativeEvent.layout.y + 10, evt.nativeEvent.layout.width - 20, evt.nativeEvent.layout.height - 20); | ||
if (!this.state.defaultDisplayArea || rectChanged(this.state.defaultDisplayArea, newDisplayArea)) { | ||
this.setState({defaultDisplayArea: newDisplayArea});//, () => this.handleGeomChange({displayArea: newDisplayArea})); | ||
let newDisplayArea = new Rect(evt.nativeEvent.layout.x + 10, evt.nativeEvent.layout.y + 10, evt.nativeEvent.layout.width - 20, evt.nativeEvent.layout.height - 20); | ||
if (!this.state.defaultDisplayArea || rectChanged(this.state.defaultDisplayArea, newDisplayArea)) { | ||
if (DEBUG) console.log("setDefaultDisplayArea - newDisplayArea: " + JSON.stringify(newDisplayArea)); | ||
if (this.safeAreaViewReady || !isIOS()) { | ||
this.setState({defaultDisplayArea: newDisplayArea}, () => { | ||
this.calculateRect(this.props, fromRect => { | ||
if (rectChanged(fromRect, this.state.fromRect) | ||
|| rectChanged(this.getDisplayArea(), this.displayAreaStore)) { | ||
this.displayAreaStore = this.getDisplayArea(); | ||
if (DEBUG) console.log("setDefaultDisplayArea (inside calculateRect callback) - fromRect: " + JSON.stringify(fromRect)); | ||
if (DEBUG) console.log("setDefaultDisplayArea (inside calculateRect callback) - getDisplayArea(): " + JSON.stringify(this.displayAreaStore)); | ||
this.setState({fromRect}, () => { | ||
this.handleGeomChange(); | ||
this.waitForResizeToFinish = false; | ||
}); | ||
} | ||
}) | ||
}); | ||
} | ||
this.safeAreaViewReady = true; | ||
} | ||
this.safeAreaViewReady = true; | ||
} | ||
@@ -72,3 +87,3 @@ | ||
keyboardDidHide() { | ||
this.setState({shiftedDisplayArea: null}, () => this.handleGeomChange({displayArea: this.getDisplayArea()})); | ||
this.setState({shiftedDisplayArea: null}, () => this.handleGeomChange()); | ||
} | ||
@@ -87,3 +102,3 @@ | ||
height: combinedY - displayArea.y | ||
}}, () => this.handleGeomChange({displayArea: this.state.shiftedDisplayArea})); | ||
}}, () => this.handleGeomChange()); | ||
} | ||
@@ -97,2 +112,8 @@ | ||
// This is used so that when the device is rotating or the viewport is expanding for any other reason, | ||
// we can suspend updates due to content changes until we are finished calculating the new display | ||
// area and rect for the new viewport size | ||
// This makes the recalc on rotation much faster | ||
this.waitForResizeToFinish = false; | ||
// Show popover if isVisible is initially true | ||
@@ -112,6 +133,12 @@ if (this.props.isVisible) | ||
handleResizeEvent = (event) => this.setState({viewport: event.window}); | ||
// First thing called when device rotates | ||
handleResizeEvent = (event) => { | ||
if (this.props.isVisible) { | ||
this.safeAreaViewReady = false; | ||
this.waitForResizeToFinish = true; | ||
} | ||
} | ||
measureContent(requestedContentSize) { | ||
if (requestedContentSize.width && requestedContentSize.height) { | ||
if (requestedContentSize.width && requestedContentSize.height && !this.waitForResizeToFinish) { | ||
if (this.state.isAwaitingShow) { | ||
@@ -125,3 +152,4 @@ if ((this.props.fromView && !this.state.fromRect) || !this.getDisplayArea() || !this.safeAreaViewReady) { | ||
} else if (requestedContentSize.width !== this.state.requestedContentSize.width || requestedContentSize.height !== this.state.requestedContentSize.height) { | ||
this.handleGeomChange({requestedContentSize}); | ||
if (DEBUG) console.log("measureContent - requestedContentSize: " + JSON.stringify(requestedContentSize)); | ||
this.handleGeomChange(requestedContentSize); | ||
} | ||
@@ -136,2 +164,7 @@ } | ||
if (DEBUG) { | ||
console.log("computeGeometry - displayArea: " + JSON.stringify(displayArea)); | ||
console.log("computeGeometry - fromRect: " + JSON.stringify(fromRect)); | ||
} | ||
if (fromRect && isRect(fromRect)) { | ||
@@ -438,11 +471,11 @@ //check to see if fromRect is outside of displayArea, and adjust if it is | ||
getTranslateOrigin() { | ||
const {forcedContentSize, requestedContentSize, popoverOrigin, anchorPoint} = this.state; | ||
const {forcedContentSize, requestedContentSize, popoverOrigin, anchorPoint} = this.state; | ||
const viewWidth = forcedContentSize.width || requestedContentSize.width || 0; | ||
const viewHeight = forcedContentSize.height || requestedContentSize.height || 0; | ||
const popoverCenter = new Point(popoverOrigin.x + (viewWidth / 2), | ||
popoverOrigin.y + (viewHeight / 2)); | ||
const shiftHorizantal = anchorPoint.x - popoverCenter.x; | ||
const shiftVertical = anchorPoint.y - popoverCenter.y; | ||
return new Point(popoverOrigin.x + shiftHorizantal, popoverOrigin.y + shiftVertical); | ||
const viewWidth = forcedContentSize.width || requestedContentSize.width || 0; | ||
const viewHeight = forcedContentSize.height || requestedContentSize.height || 0; | ||
const popoverCenter = new Point(popoverOrigin.x + (viewWidth / 2), | ||
popoverOrigin.y + (viewHeight / 2)); | ||
const shiftHorizantal = anchorPoint.x - popoverCenter.x; | ||
const shiftVertical = anchorPoint.y - popoverCenter.y; | ||
return new Point(popoverOrigin.x + shiftHorizantal, popoverOrigin.y + shiftVertical); | ||
} | ||
@@ -454,28 +487,34 @@ | ||
componentWillReceiveProps(nextProps:any) { | ||
let willBeVisible = nextProps.isVisible; | ||
let { | ||
isVisible, | ||
displayArea | ||
} = this.props; | ||
componentWillReceiveProps(nextProps) { | ||
if (willBeVisible !== isVisible) { | ||
if (willBeVisible) { | ||
// We want to start the show animation only when contentSize is known | ||
// so that we can have some logic depending on the geometry | ||
this.calculateRect(nextProps, fromRect => this.setState({fromRect, isAwaitingShow: true, visible: true})); | ||
} else { | ||
this.animateOut(); | ||
// Make sure a value we care about has actually changed | ||
let importantProps = ["isVisible", "fromRect", "displayArea", "verticalOffset", "placement"] | ||
if (!importantProps.reduce((acc, key) => acc || this.props[key] !== nextProps[key], false)) | ||
return; | ||
let willBeVisible = nextProps.isVisible; | ||
let { | ||
isVisible, | ||
displayArea | ||
} = this.props; | ||
if (willBeVisible !== isVisible) { | ||
if (willBeVisible) { | ||
// We want to start the show animation only when contentSize is known | ||
// so that we can have some logic depending on the geometry | ||
this.calculateRect(nextProps, fromRect => this.setState({fromRect, isAwaitingShow: true, visible: true})); | ||
} else { | ||
this.animateOut(); | ||
} | ||
} else if (willBeVisible) { | ||
this.calculateRect(nextProps, fromRect => { | ||
if (rectChanged(fromRect, this.state.fromRect) | ||
|| (nextProps.displayArea && !this.props.displayArea) | ||
|| rectChanged(nextProps.displayArea, this.props.displayArea) | ||
|| rectChanged(this.getDisplayArea(), this.displayAreaStore)) { | ||
this.displayAreaStore = this.getDisplayArea(); | ||
this.setState({fromRect}, () => this.handleGeomChange()); | ||
} | ||
} else if (willBeVisible) { | ||
this.calculateRect(nextProps, fromRect => { | ||
if (rectChanged(fromRect, this.state.fromRect) | ||
|| (nextProps.displayArea && !this.props.displayArea) | ||
|| rectChanged(nextProps.displayArea, this.props.displayArea) | ||
|| rectChanged(this.getDisplayArea(), this.displayAreaStore)) { | ||
this.displayAreaStore = this.getDisplayArea(); | ||
this.setState({fromRect}, () => this.handleGeomChange(Object.assign({}, nextProps, {fromRect}))) | ||
} | ||
}) | ||
} | ||
}) | ||
} | ||
} | ||
@@ -495,17 +534,28 @@ | ||
handleGeomChange({displayArea, fromRect, requestedContentSize}) { | ||
handleGeomChange(requestedContentSize) { | ||
const { forcedContentSize, placement, anchorPoint, popoverOrigin, animatedValues } = this.state; | ||
requestedContentSize = requestedContentSize || Object.assign({}, this.state.requestedContentSize); | ||
let geom = this.computeGeometry({requestedContentSize, displayArea, fromRect}); | ||
if (DEBUG) console.log("handleGeomChange - requestedContentSize: " + JSON.stringify(requestedContentSize)); | ||
if (pointChanged(geom.popoverOrigin, popoverOrigin)) { | ||
// handleGeomChange may be called more than one times before the first has a chance to finish, | ||
// so we use updateCount to make sure that we only trigger an animation on the last one | ||
if (!this.updatesCount || this.updatesCount < 0) this.updateCount = 0; | ||
this.updateCount++; | ||
let geom = this.computeGeometry({requestedContentSize}); | ||
if (pointChanged(geom.popoverOrigin, popoverOrigin) || rectChanged(geom.forcedContentSize, forcedContentSize)) { | ||
this.setState(Object.assign(geom, {requestedContentSize}), () => { | ||
this.animateTo({ | ||
values: animatedValues, | ||
fade: 1, | ||
scale: 1, | ||
translatePoint: new Point(geom.popoverOrigin.x, geom.popoverOrigin.y), | ||
easing: Easing.inOut(Easing.quad) | ||
}); | ||
if (this.updateCount <= 1) { | ||
this.updateCount--; | ||
if (DEBUG) console.log("handleGeomChange - Triggering popover move") | ||
this.animateTo({ | ||
values: animatedValues, | ||
fade: 1, | ||
scale: 1, | ||
translatePoint: new Point(geom.popoverOrigin.x, geom.popoverOrigin.y), | ||
easing: Easing.inOut(Easing.quad) | ||
}); | ||
} | ||
}); | ||
@@ -597,105 +647,105 @@ } | ||
render() { | ||
var { popoverOrigin, placement, forcedHeight, animatedValues, anchorPoint, forcedContentSize } = this.state; | ||
const { popoverStyle, arrowStyle } = this.props; | ||
const { arrowWidth, arrowHeight } = this.getCalculatedArrowDims(); | ||
var { popoverOrigin, placement, forcedHeight, animatedValues, anchorPoint, forcedContentSize } = this.state; | ||
const { popoverStyle, arrowStyle } = this.props; | ||
const { arrowWidth, arrowHeight } = this.getCalculatedArrowDims(); | ||
let arrowScale = animatedValues.scale.interpolate({ | ||
inputRange: [0, 1], | ||
outputRange: [0, 1], | ||
extrapolate: 'clamp', | ||
}) | ||
let arrowScale = animatedValues.scale.interpolate({ | ||
inputRange: [0, 1], | ||
outputRange: [0, 1], | ||
extrapolate: 'clamp', | ||
}) | ||
var arrowViewStyle = { | ||
position: 'absolute', | ||
top: 0, | ||
left: 0, | ||
width: arrowWidth, | ||
height: arrowHeight, | ||
var arrowViewStyle = { | ||
position: 'absolute', | ||
top: 0, | ||
left: 0, | ||
width: arrowWidth, | ||
height: arrowHeight, | ||
transform: [ | ||
{translateX: animatedValues.translateArrow.x}, | ||
{translateY: animatedValues.translateArrow.y}, | ||
{scale: arrowScale}, | ||
] | ||
}; | ||
let arrowInnerStyle = [ | ||
styles.arrow, | ||
this.getArrowDynamicStyle(), | ||
{ | ||
borderTopColor: arrowStyle.backgroundColor || popoverStyle.backgroundColor || styles.popoverContent.backgroundColor, | ||
transform: [ | ||
{translateX: animatedValues.translateArrow.x}, | ||
{translateY: animatedValues.translateArrow.y}, | ||
{scale: arrowScale}, | ||
{rotate: this.getArrowRotation(placement)} | ||
] | ||
}; | ||
} | ||
]; | ||
let arrowInnerStyle = [ | ||
styles.arrow, | ||
this.getArrowDynamicStyle(), | ||
{ | ||
borderTopColor: arrowStyle.backgroundColor || popoverStyle.backgroundColor || styles.popoverContent.backgroundColor, | ||
transform: [ | ||
{rotate: this.getArrowRotation(placement)} | ||
] | ||
} | ||
]; | ||
// Temp fix for useNativeDriver issue | ||
let backgroundShift = animatedValues.fade.interpolate({ | ||
inputRange: [0, 0.0001, 1], | ||
outputRange: [0, FIX_SHIFT, FIX_SHIFT] | ||
}) | ||
// Temp fix for useNativeDriver issue | ||
let backgroundShift = animatedValues.fade.interpolate({ | ||
inputRange: [0, 0.0001, 1], | ||
outputRange: [0, FIX_SHIFT, FIX_SHIFT] | ||
}) | ||
let backgroundStyle = { | ||
...styles.background, | ||
transform: [ | ||
{translateX: backgroundShift} | ||
] | ||
}; | ||
if (this.props.showBackground) | ||
backgroundStyle.backgroundColor = 'rgba(0,0,0,0.5)' | ||
let backgroundStyle = { | ||
...styles.background, | ||
transform: [ | ||
{translateX: backgroundShift} | ||
] | ||
}; | ||
if (this.props.showBackground) | ||
backgroundStyle.backgroundColor = 'rgba(0,0,0,0.5)' | ||
let containerStyle = { | ||
...styles.container, | ||
opacity: animatedValues.fade | ||
}; | ||
let containerStyle = { | ||
...styles.container, | ||
opacity: animatedValues.fade | ||
}; | ||
let popoverViewStyle = Object.assign({ | ||
maxWidth: forcedContentSize.width, | ||
maxHeight: forcedContentSize.height, | ||
position: 'absolute', | ||
}, styles.dropShadow, styles.popoverContent, popoverStyle, { | ||
transform: [ | ||
{translateX: animatedValues.translate.x}, | ||
{translateY: animatedValues.translate.y}, | ||
{scale: animatedValues.scale}, | ||
{perspective: 1000} | ||
], | ||
}); | ||
let popoverViewStyle = Object.assign({ | ||
maxWidth: forcedContentSize.width, | ||
maxHeight: forcedContentSize.height, | ||
position: 'absolute', | ||
}, styles.dropShadow, styles.popoverContent, popoverStyle, { | ||
transform: [ | ||
{translateX: animatedValues.translate.x}, | ||
{translateY: animatedValues.translate.y}, | ||
{scale: animatedValues.scale}, | ||
{perspective: 1000} | ||
], | ||
}); | ||
let contentView = ( | ||
<View style={[styles.container, {left: 0}]}> | ||
<SafeAreaView pointerEvent="none" style={{position: 'absolute', top: 0, left: 0, right: 0, bottom: 0}}> | ||
<View style={{flex: 1}} onLayout={evt => this.setDefaultDisplayArea(evt)} /> | ||
</SafeAreaView> | ||
let contentView = ( | ||
<View style={[styles.container, {left: 0}]}> | ||
<SafeAreaView pointerEvent="none" style={{position: 'absolute', top: 0, left: 0, right: 0, bottom: 0}}> | ||
<View style={{flex: 1}} onLayout={evt => this.setDefaultDisplayArea(evt)} /> | ||
</SafeAreaView> | ||
<Animated.View style={containerStyle}> | ||
<TouchableWithoutFeedback onPress={this.props.onClose}> | ||
<Animated.View style={backgroundStyle}/> | ||
</TouchableWithoutFeedback> | ||
<Animated.View style={containerStyle}> | ||
<TouchableWithoutFeedback onPress={this.props.onClose}> | ||
<Animated.View style={backgroundStyle}/> | ||
</TouchableWithoutFeedback> | ||
<View style={{top: 0, left: 0}}> | ||
<Animated.View style={popoverViewStyle} onLayout={evt => this.measureContent(evt.nativeEvent.layout)}> | ||
{this.props.children} | ||
</Animated.View> | ||
<View style={{top: 0, left: 0}}> | ||
<Animated.View style={popoverViewStyle} onLayout={evt => this.measureContent(evt.nativeEvent.layout)}> | ||
{this.props.children} | ||
</Animated.View> | ||
{(this.props.fromRect || this.state.fromRect) && | ||
<Animated.View style={arrowViewStyle}> | ||
<View style={arrowInnerStyle}/> | ||
</Animated.View> | ||
} | ||
</View> | ||
</Animated.View> | ||
</View> | ||
); | ||
{(this.props.fromRect || this.state.fromRect) && | ||
<Animated.View style={arrowViewStyle}> | ||
<View style={arrowInnerStyle}/> | ||
</Animated.View> | ||
} | ||
</View> | ||
</Animated.View> | ||
</View> | ||
if (this.props.showInModal) { | ||
return ( | ||
<Modal transparent={true} supportedOrientations={['portrait', 'landscape']} hardwareAccelerated={true} visible={this.state.visible} onRequestClose={this.props.onClose}> | ||
{contentView} | ||
</Modal> | ||
); | ||
if (this.props.showInModal) { | ||
return ( | ||
<Modal transparent={true} supportedOrientations={['portrait', 'landscape']} hardwareAccelerated={true} visible={this.state.visible} onRequestClose={this.props.onClose}> | ||
{contentView} | ||
</Modal> | ||
); | ||
} else { | ||
return contentView; | ||
} | ||
} else { | ||
return contentView; | ||
} | ||
} | ||
@@ -702,0 +752,0 @@ } |
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
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
133518
0
1445
0
0
26
- Removedfs@^0.0.1-security
- Removedfs@0.0.1-security(transitive)
- Removedreact-navigation@5.0.0(transitive)