Skip to content
This repository has been archived by the owner on Feb 15, 2019. It is now read-only.

Commit

Permalink
Migrate portions of the drawer item implementations to the child and …
Browse files Browse the repository at this point in the history
…item components

DrawerNavigation{Child,Item} drawerItems are now rendered directly instead of being used as plain JS objects.
  • Loading branch information
dantman committed Mar 3, 2017
1 parent 24c86cd commit 2f29650
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 139 deletions.
75 changes: 13 additions & 62 deletions src/drawer/ExNavigationDrawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
} from 'react-native';
import DrawerLayout from 'react-native-drawer-layout';
import PureComponent from '../utils/PureComponent';
import StaticContainer from 'react-static-container';

import invariant from 'invariant';
import _ from 'lodash';
Expand Down Expand Up @@ -78,7 +77,7 @@ type Props = {
type State = {
id: string,
navigatorUID: string,
drawerItems: Array<ExNavigationDrawerItem, ExNavigationDrawerChild>,
drawerItems: Array<React.Element<any>>,
parentNavigatorUID: string,
renderedItemKeys: Array<string>,
};
Expand Down Expand Up @@ -148,6 +147,7 @@ class ExNavigationDrawer extends PureComponent<any, Props, State> {
drawerPosition: this.props.drawerPosition,
width: this.props.drawerWidth,
renderNavigationView: this.props.renderNavigationView,
setActiveItem: this.setActiveItem,
style: [
this.props.drawerStyle,
],
Expand All @@ -164,7 +164,7 @@ class ExNavigationDrawer extends PureComponent<any, Props, State> {

renderContent = () => {
const items = this.state.renderedItemKeys.map(key => {
return this.state.drawerItems.find(i => i.id === key);
return this.state.drawerItems.find(i => i.props.id === key);
});

return (
Expand All @@ -174,26 +174,16 @@ class ExNavigationDrawer extends PureComponent<any, Props, State> {
);
};

renderItemContent(drawerItem: Object) {
if (!drawerItem.element) {
return null;
}

renderItemContent(drawerItem: React.Element<any>) {
const navState = this._getNavigationState();
const selectedChild = navState.routes[navState.index];
const isSelected = drawerItem.id === selectedChild.key;
const isSelected = drawerItem.props.id === selectedChild.key;

return (
<View
key={drawerItem.id}
removeClippedSubviews={!isSelected}
style={[styles.itemContentInner, {opacity: isSelected ? 1 : 0}]}
pointerEvents={isSelected ? 'auto' : 'none'}>
<StaticContainer shouldUpdate={isSelected}>
{drawerItem.element}
</StaticContainer>
</View>
);
return React.cloneElement(drawerItem, {
key: drawerItem.props.id,
isSelected,
renderTo: 'content',
});
}

componentWillMount() {
Expand Down Expand Up @@ -270,52 +260,20 @@ class ExNavigationDrawer extends PureComponent<any, Props, State> {
'All children of DrawerNavigation must be DrawerNavigationItems or DrawerNavigationChilds.',
);

if (child.type === ExNavigationDrawerChild) {
const drawerChildProps = child.props;

let drawerItem = {
drawerChildren: drawerChildProps.children,
};

return drawerItem;
} else {
const drawerItemProps = child.props;

let drawerItem = {
..._.omit(drawerItemProps, ['children']),
};

if (Children.count(drawerItemProps.children) > 0) {
drawerItem.element = Children.only(drawerItemProps.children);
}

const drawerItemOnPress = () => {
this._setActiveItem(drawerItemProps.id, index);
};

if (typeof drawerItemProps.onPress === 'function') {
drawerItem.onPress = drawerItem.onPress.bind(this, drawerItemOnPress);
} else {
drawerItem.onPress = drawerItemOnPress;
}

drawerItem.onLongPress = drawerItemProps.onLongPress;

return drawerItem;
}
return child;
});

this.setState({
drawerItems,
});
}

_setActiveItem(id, index) {
setActiveItem = (id) => {
this._getNavigatorContext().jumpToItem(id);
if (typeof this.props.onPress === 'function') {
this.props.onPress(id);
}
}
};

toggleDrawer = () => {
this._drawerLayout && this._drawerLayout.toggle();
Expand Down Expand Up @@ -357,11 +315,4 @@ const styles = StyleSheet.create({
itemContentOuter: {
flex: 1,
},
itemContentInner: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
});
69 changes: 68 additions & 1 deletion src/drawer/ExNavigationDrawerChild.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,74 @@
import React from 'react';
import {
StyleSheet,
View,
} from 'react-native';
import StaticContainer from 'react-static-container';

export type Props = {
children: React.Element<any>,
renderTo: 'drawer' | 'content',
showsTouches: ?boolean,
isSelected: boolean,
selectedStyle: any,
};

export default class ExNavigationDrawerChild extends React.Component {
render() {
props: Props;
hasContent: boolean = false;

renderDrawerItem() {
let { children } = this.props;
return React.createElement(View, null, children);
}

renderContent() {
return null;
}

_renderContent() {
const { isSelected } = this.props;
let content = this.renderContent();

if (content === null) {
return null;
}

return (
<View
removeClippedSubviews={!isSelected}
style={[styles.itemContentInner, {opacity: isSelected ? 1 : 0}]}
pointerEvents={isSelected ? 'auto' : 'none'}>
<StaticContainer shouldUpdate={isSelected}>
{content}
</StaticContainer>
</View>
);
}

render() {
let { renderTo } = this.props;

if (renderTo === 'drawer') {
return this.renderDrawerItem();
} else if (renderTo === 'content') {
return this._renderContent();
} else {
console.warn('renderTo must be "drawer" or "content"');
return null;
}
}
}

const styles = StyleSheet.create({
itemContentOuter: {
flex: 1,
},
itemContentInner: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
});
86 changes: 84 additions & 2 deletions src/drawer/ExNavigationDrawerItem.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,89 @@
import React from 'react';
import {
TouchableWithoutFeedback,
StyleSheet,
View,
} from 'react-native';
import TouchableNativeFeedbackSafe from '@exponent/react-native-touchable-native-feedback-safe';
import ExNavigationDrawerChild from './ExNavigationDrawerChild';
import type { Props } from './ExNavigationDrawerChild';

export default class ExNavigationDrawerItem extends ExNavigationDrawerChild {
props: Props;

renderDrawerItem() {
let { showsTouches, isSelected, renderIcon, renderTitle, renderRight, onPress, onLongPress } = this.props;
const icon = renderIcon && renderIcon(isSelected);
const title = renderTitle && renderTitle(isSelected);
const rightElement = renderRight && renderRight(isSelected);

if (showsTouches !== false) {
return (
<TouchableNativeFeedbackSafe
onPress={onPress}
onLongPress={onLongPress}
delayPressIn={0}
style={[isSelected ? this.props.selectedStyle : this.props.style]}
background={this.props.nativeFeedbackBackground}>
<View style={styles.buttonContainer}>
{
icon && <View style={[styles.elementContainer]}>{icon}</View>
}
{
title && <View style={[styles.elementContainer]}>{title}</View>
}
{
rightElement && <View style={[styles.elementContainer, styles.rightElementContainer]}>{rightElement}</View>
}
</View>
</TouchableNativeFeedbackSafe>
);
} else {
return (
<TouchableWithoutFeedback
onPress={onPress}
onLongPress={onLongPress}>
<View style={[styles.buttonContainer, isSelected ? this.props.selectedStyle : this.props.style]}>
{
icon && <View style={[styles.elementContainer]}>{icon}</View>
}
{
title && <View style={[styles.elementContainer]}>{title}</View>
}
{
rightElement && <View style={[styles.elementContainer, styles.rightElementContainer]}>{rightElement}</View>
}
</View>
</TouchableWithoutFeedback>
);
}
}

renderContent() {
if (React.Children.count(this.props.children) > 0) {
return React.Children.only(this.props.children);
}

export default class ExNavigationDrawerItem extends React.Component {
render() {
return null;
}
}

const styles = StyleSheet.create({
buttonContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
paddingVertical: 10,
paddingHorizontal: 15,
},
elementContainer: {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
},
rightElementContainer: {
flex: 1,
justifyContent: 'flex-end',
},
});
Loading

0 comments on commit 2f29650

Please sign in to comment.