mirror of
https://github.com/zhigang1992/react-native-popover-view.git
synced 2026-01-12 09:24:01 +08:00
Major changes (not working yet)
This commit is contained in:
10
.tern-project
Normal file
10
.tern-project
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"plugins": {
|
||||
"es_modules": {}
|
||||
},
|
||||
"libs": [
|
||||
"ecma5",
|
||||
"ecma6"
|
||||
],
|
||||
"ecmaVersion": 6
|
||||
}
|
||||
5296
package-lock.json
generated
Normal file
5296
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -86,20 +86,24 @@ class Popover extends React.Component {
|
||||
}
|
||||
|
||||
measureContent(requestedContentSize) {
|
||||
if (!this.state.skipNextMeasure) {
|
||||
if (requestedContentSize.width && requestedContentSize.height) {
|
||||
if (this.state.isAwaitingShow) {
|
||||
if ((this.props.fromView && !this.state.fromRect) || !this.getDisplayArea()) {
|
||||
setTimeout(() => this.measureContent(requestedContentSize), 100);
|
||||
} else {
|
||||
let geom = this.computeGeometry({requestedContentSize});
|
||||
this.setState(Object.assign(geom, {requestedContentSize, isAwaitingShow: false}), this.animateIn);
|
||||
this.setState(Object.assign(geom, {requestedContentSize, isAwaitingShow: false, skipNextMeasure: geom.forcedContentSize.width || geom.forcedContentSize.height}), this.animateIn);
|
||||
}
|
||||
} else if (requestedContentSize.width !== this.state.requestedContentSize.width || requestedContentSize.height !== this.state.requestedContentSize.height) {
|
||||
if (Math.round(requestedContentSize.width) === Math.round(this.state.forcedContentSize.width)) requestedContentSize.width = this.state.requestedContentSize.width;
|
||||
if (Math.round(requestedContentSize.height) === Math.round(this.state.forcedContentSize.height)) requestedContentSize.height = this.state.requestedContentSize.height;
|
||||
if (Math.abs(requestedContentSize.width - this.state.forcedContentSize.width) < 1) requestedContentSize.width = this.state.requestedContentSize.width;
|
||||
if (Math.abs(requestedContentSize.height - this.state.forcedContentSize.height) < 1) requestedContentSize.height = this.state.requestedContentSize.height;
|
||||
this.handleGeomChange({requestedContentSize});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.setState({skipNextMeasure: true});
|
||||
}
|
||||
}
|
||||
|
||||
computeGeometry({requestedContentSize, placement, fromRect, displayArea}) {
|
||||
@@ -432,7 +436,7 @@ class Popover extends React.Component {
|
||||
let geom = this.computeGeometry({requestedContentSize, displayArea, fromRect});
|
||||
|
||||
this.setState(Object.assign(geom, {requestedContentSize}), () => {
|
||||
if (geom.popoverOrigin !== popoverOrigin) {
|
||||
if (rectChanged(geom.popoverOrigin, popoverOrigin)) {
|
||||
this.animateTo({
|
||||
values: animatedValues,
|
||||
fade: 1,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Popover from './Popover'
|
||||
import { popoverTransitionConfig, Rect, isIOS } from './Utility'
|
||||
import { popoverTransitionConfig, Rect, isIOS, isTablet } from './Utility'
|
||||
import React, { Component } from 'react'
|
||||
import { View, BackHandler, Animated, findNodeHandle, NativeModules, Alert, Dimensions } from 'react-native'
|
||||
import { View, BackHandler, Animated, findNodeHandle, NativeModules, Alert } from 'react-native'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
export default class PopoverNavigation extends Component {
|
||||
@@ -19,7 +19,7 @@ export default class PopoverNavigation extends Component {
|
||||
}
|
||||
|
||||
goBack() {
|
||||
if (this.constructor.shouldShowInPopover())
|
||||
if (this.props.showInPopover)
|
||||
this.setState({visible: false});
|
||||
else
|
||||
this.props.children.props.navigation.goBack();
|
||||
@@ -41,9 +41,9 @@ export default class PopoverNavigation extends Component {
|
||||
|
||||
render() {
|
||||
const child = React.cloneElement(this.props.children, {goBack: () => this.goBack()});
|
||||
const { preferedWidth, preferedHeight, arrowSize, placement, showInModal, layoutRtl, showArrow, showBackground, viewName, displayArea } = this.props;
|
||||
const { contentContainerStyle, arrowSize, placement, showInModal, layoutRtl, showArrow, showBackground, getRegisteredView, displayArea, showInPopover, backgroundColor } = this.props;
|
||||
|
||||
if (this.constructor.shouldShowInPopover()) {
|
||||
if (showInPopover) {
|
||||
return (
|
||||
<Popover
|
||||
arrowSize={arrowSize}
|
||||
@@ -56,27 +56,23 @@ export default class PopoverNavigation extends Component {
|
||||
onClose={() => this.goBack()}
|
||||
displayArea={displayArea || this.getParam('displayArea')}
|
||||
doneClosingCallback={() => this.props.children.props.navigation.goBack()}
|
||||
fromView={this.constructor.registeredViews.hasOwnProperty(viewName) ? this.constructor.registeredViews[viewName] : this.getParam('showFromView')}
|
||||
fromView={getRegisteredView() || this.getParam('showFromView')}
|
||||
calculateRect={this.getParam('calculateRect')}
|
||||
fromRect={this.getParam('fromRect')}>
|
||||
<View style={{width: preferedWidth, height: preferedHeight}}>{child}</View>
|
||||
<View style={{backgroundColor, ...contentContainerStyle}}>{child}</View>
|
||||
</Popover>
|
||||
)
|
||||
} else {
|
||||
return child;
|
||||
return <View style={{backgroundColor, flex: 1}}>{child}</View>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PopoverNavigation.shouldShowInPopover = () => Dimensions.get('window').height / Dimensions.get('window').width < 1.6;
|
||||
PopoverNavigation.registeredViews = {};
|
||||
PopoverNavigation.registerRefForView = (ref, viewName) => {
|
||||
if (!PopoverNavigation.registeredViews.hasOwnProperty(viewName))
|
||||
PopoverNavigation.registeredViews[viewName] = ref;
|
||||
}
|
||||
|
||||
|
||||
PopoverNavigation.defaultProps = {
|
||||
preferedWidth: 380
|
||||
preferedWidth: 380,
|
||||
showInPopover: true
|
||||
}
|
||||
|
||||
PopoverNavigation.propTypes = {
|
||||
|
||||
@@ -1,25 +1,69 @@
|
||||
import React from 'react'
|
||||
import { View } from 'react-native'
|
||||
import { StackNavigator } from '../../react-navigation'
|
||||
import { popoverTransitionConfig } from './Utility'
|
||||
import { popoverTransitionConfig, isTablet } from './Utility'
|
||||
import PopoverNavigation from './PopoverNavigation'
|
||||
|
||||
export let withPopoverNavigation = (Comp, popoverOptions) => props => <PopoverNavigation {...popoverOptions}><Comp {...props} /></PopoverNavigation>;
|
||||
|
||||
export default function PopoverStackNavigator(RouteConfigs, StackNavigatorConfig) {
|
||||
function PopoverStackNavigator(RouteConfigs, StackNavigatorConfig) {
|
||||
let routeKeys = Object.keys(RouteConfigs);
|
||||
let firstRouteKey = routeKeys.splice(0, 1)[0];
|
||||
let newRouteConfigs = {};
|
||||
newRouteConfigs[firstRouteKey] = RouteConfigs[firstRouteKey];
|
||||
routeKeys.forEach(route => newRouteConfigs[route] = Object.assign({}, RouteConfigs[route], { screen: withPopoverNavigation(RouteConfigs[route].screen, Object.assign({}, RouteConfigs[route].popoverOptions, {viewName: route})) }));
|
||||
let shouldShowInPopover = StackNavigatorConfig.showInPopover || isTablet;
|
||||
routeKeys.forEach((route, i) => {
|
||||
let getRegisteredView = () => PopoverStackNavigator.registeredViews.hasOwnProperty(route) ? PopoverStackNavigator.registeredViews[route] : null;
|
||||
newRouteConfigs[route] = Object.assign({},
|
||||
RouteConfigs[route],
|
||||
{
|
||||
screen: withPopoverNavigation(RouteConfigs[route].screen, Object.assign({},
|
||||
RouteConfigs[route].popoverOptions,
|
||||
{
|
||||
showInPopover: i > 0,
|
||||
getRegisteredView,
|
||||
backgroundColor: StackNavigatorConfig.cardStyle ? StackNavigatorConfig.cardStyle.backgroundColor : (i > 0 ? 'white' : '#E9E9EF')
|
||||
}
|
||||
))
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
let nonPopoverStack = StackNavigator(newRouteConfigs, StackNavigatorConfig);
|
||||
const popoverStackConfig = Object.assign({}, StackNavigatorConfig, {transitionConfig: popoverTransitionConfig, headerMode: 'screen', cardStyle: {backgroundColor: 'transparent'}});
|
||||
let popoverStack = StackNavigator(newRouteConfigs, popoverStackConfig);
|
||||
const nonPopoverStack = StackNavigator(RouteConfigs, StackNavigatorConfig);
|
||||
const popoverStackConfig = Object.assign({}, StackNavigatorConfig, {transitionConfig: popoverTransitionConfig, headerMode: 'screen', cardStyle: {backgroundColor: 'transparent', ...StackNavigatorConfig.cardStyle}});
|
||||
const popoverStack = StackNavigator(newRouteConfigs, popoverStackConfig);
|
||||
|
||||
return props => {
|
||||
let { navigatorRef, ...other } = props;
|
||||
let Stack = nonPopoverStack;
|
||||
if (PopoverNavigation.shouldShowInPopover()) Stack = popoverStack;
|
||||
return <Stack ref={props.navigatorRef} {...other} />;
|
||||
class InternalPopoverStackNavigator extends React.Component {
|
||||
state = {
|
||||
width: 0,
|
||||
height: 0
|
||||
}
|
||||
|
||||
updateLayout(evt) {
|
||||
this.setState({
|
||||
width: evt.nativeEvent.layout.width,
|
||||
height: evt.nativeEvent.layout.height
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
let { navigatorRef, ...other } = this.props;
|
||||
let Stack = nonPopoverStack;
|
||||
if (shouldShowInPopover(this.state.width, this.state.height)) Stack = popoverStack;
|
||||
return (
|
||||
<View
|
||||
onLayout={this.updateLayout.bind(this)}
|
||||
style={{position: 'absolute', top: 0, left: 0, bottom: 0, right: 0}}>
|
||||
<Stack ref={navigatorRef} {...other} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return InternalPopoverStackNavigator;
|
||||
}
|
||||
|
||||
PopoverStackNavigator.registeredViews = {};
|
||||
PopoverStackNavigator.registerRefForView = (ref, view) => {
|
||||
PopoverStackNavigator.registeredViews[view] = ref;
|
||||
}
|
||||
|
||||
export default PopoverStackNavigator;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Platform, Animated, NativeModules, findNodeHandle } from 'react-native'
|
||||
import { Platform, Animated, NativeModules, findNodeHandle, Dimensions } from 'react-native'
|
||||
|
||||
export function Point(x, y) {
|
||||
this.x = x;
|
||||
@@ -21,6 +21,10 @@ export function isIOS() {
|
||||
return Platform.OS === 'ios';
|
||||
}
|
||||
|
||||
export function isTablet() {
|
||||
return Dimensions.get('window').height / Dimensions.get('window').width < 1.6;
|
||||
}
|
||||
|
||||
// Transition config needed on tablets for popover to work
|
||||
export let popoverTransitionConfig = () => ({
|
||||
transitionSpec: {
|
||||
|
||||
15
src/index.js
15
src/index.js
@@ -1,11 +1,4 @@
|
||||
import Popover from './Popover'
|
||||
import PopoverNavigation from './PopoverNavigation'
|
||||
import PopoverStackNavigator, { withPopoverNavigation } from './PopoverStackNavigator'
|
||||
import { Rect, popoverTransitionConfig } from './Utility'
|
||||
|
||||
export default Popover
|
||||
export { PopoverNavigation as PopoverNavigation }
|
||||
export { Rect as Rect }
|
||||
export { popoverTransitionConfig as popoverTransitionConfig }
|
||||
export { PopoverStackNavigator as PopoverStackNavigator }
|
||||
export { withPopoverNavigation as withPopoverNavigation }
|
||||
export { default as default } from './Popover.js'
|
||||
export { default as PopoverNavigation } from './PopoverNavigation.js'
|
||||
export { default as PopoverStackNavigator, withPopoverNavigation as withPopoverNavigation } from './PopoverStackNavigator.js'
|
||||
export { Rect as Rect, popoverTransitionConfig as popoverTransitionConfig } from './Utility.js'
|
||||
|
||||
Reference in New Issue
Block a user