From 24c86cdbfe67304cc64b6d365573f93deb9b6ed2 Mon Sep 17 00:00:00 2001 From: Daniel Friesen Date: Wed, 9 Nov 2016 23:33:45 -0800 Subject: [PATCH 1/6] Add DrawerNavigationChild to insert non-item children into DrawerNavigation --- README.md | 9 ++++ example/components/DrawerNavigationExample.js | 10 ++++ src/ExNavigation.js | 1 + src/drawer/ExNavigationDrawer.js | 51 +++++++++++-------- src/drawer/ExNavigationDrawerChild.js | 7 +++ src/drawer/ExNavigationDrawerLayout.js | 6 ++- 6 files changed, 63 insertions(+), 21 deletions(-) create mode 100644 src/drawer/ExNavigationDrawerChild.js diff --git a/README.md b/README.md index 4292911..e480b76 100644 --- a/README.md +++ b/README.md @@ -523,6 +523,7 @@ import { StackNavigation, DrawerNavigation, DrawerNavigationItem, + DrawerNavigationChild, } from '@exponent/ex-navigation'; // Treat the DrawerNavigationLayout route like any other route -- you may want to set @@ -554,6 +555,10 @@ class DrawerNavigationLayout extends React.Component { /> + + Meta + + + + Meta + , + drawerItems: Array, parentNavigatorUID: string, renderedItemKeys: Array, }; @@ -265,33 +266,43 @@ class ExNavigationDrawer extends PureComponent { } invariant( - child.type === ExNavigationDrawerItem, - 'All children of DrawerNavigation must be DrawerNavigationItems.', + child.type === ExNavigationDrawerItem || child.type === ExNavigationDrawerChild, + 'All children of DrawerNavigation must be DrawerNavigationItems or DrawerNavigationChilds.', ); - const drawerItemProps = child.props; + if (child.type === ExNavigationDrawerChild) { + const drawerChildProps = child.props; - let drawerItem = { - ..._.omit(drawerItemProps, ['children']), - }; + let drawerItem = { + drawerChildren: drawerChildProps.children, + }; - if (Children.count(drawerItemProps.children) > 0) { - drawerItem.element = Children.only(drawerItemProps.children); - } + return drawerItem; + } else { + const drawerItemProps = child.props; - const drawerItemOnPress = () => { - this._setActiveItem(drawerItemProps.id, index); - }; + let drawerItem = { + ..._.omit(drawerItemProps, ['children']), + }; - if (typeof drawerItemProps.onPress === 'function') { - drawerItem.onPress = drawerItem.onPress.bind(this, drawerItemOnPress); - } else { - drawerItem.onPress = drawerItemOnPress; - } + if (Children.count(drawerItemProps.children) > 0) { + drawerItem.element = Children.only(drawerItemProps.children); + } - drawerItem.onLongPress = drawerItemProps.onLongPress; + const drawerItemOnPress = () => { + this._setActiveItem(drawerItemProps.id, index); + }; - return drawerItem; + if (typeof drawerItemProps.onPress === 'function') { + drawerItem.onPress = drawerItem.onPress.bind(this, drawerItemOnPress); + } else { + drawerItem.onPress = drawerItemOnPress; + } + + drawerItem.onLongPress = drawerItemProps.onLongPress; + + return drawerItem; + } }); this.setState({ diff --git a/src/drawer/ExNavigationDrawerChild.js b/src/drawer/ExNavigationDrawerChild.js new file mode 100644 index 0000000..f18c87a --- /dev/null +++ b/src/drawer/ExNavigationDrawerChild.js @@ -0,0 +1,7 @@ +import React from 'react'; + +export default class ExNavigationDrawerChild extends React.Component { + render() { + return null; + } +} diff --git a/src/drawer/ExNavigationDrawerLayout.js b/src/drawer/ExNavigationDrawerLayout.js index 51c1d4a..6ceaa8a 100644 --- a/src/drawer/ExNavigationDrawerLayout.js +++ b/src/drawer/ExNavigationDrawerLayout.js @@ -78,12 +78,16 @@ export default class ExNavigationDrawerLayout extends React.Component { } return this.props.items.map((item, index) => { - let { renderIcon, renderTitle, renderRight } = item; + let { drawerChildren, renderIcon, renderTitle, renderRight } = item; let isSelected = this.props.selectedItem === item.id; const icon = renderIcon && renderIcon(isSelected); const title = renderTitle && renderTitle(isSelected); const rightElement = renderRight && renderRight(isSelected); + if (drawerChildren) { + return React.createElement(View, {key: index}, drawerChildren); + } + if (item.showsTouches !== false) { return ( Date: Thu, 10 Nov 2016 11:54:57 -0800 Subject: [PATCH 2/6] Migrate portions of the drawer item implementations to the child and item components DrawerNavigation{Child,Item} drawerItems are now rendered directly instead of being used as plain JS objects. --- src/drawer/ExNavigationDrawer.js | 75 ++++------------------ src/drawer/ExNavigationDrawerChild.js | 69 +++++++++++++++++++- src/drawer/ExNavigationDrawerItem.js | 86 ++++++++++++++++++++++++- src/drawer/ExNavigationDrawerLayout.js | 89 +++++--------------------- 4 files changed, 180 insertions(+), 139 deletions(-) diff --git a/src/drawer/ExNavigationDrawer.js b/src/drawer/ExNavigationDrawer.js index 45d8077..3b66807 100644 --- a/src/drawer/ExNavigationDrawer.js +++ b/src/drawer/ExNavigationDrawer.js @@ -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'; @@ -78,7 +77,7 @@ type Props = { type State = { id: string, navigatorUID: string, - drawerItems: Array, + drawerItems: Array>, parentNavigatorUID: string, renderedItemKeys: Array, }; @@ -148,6 +147,7 @@ class ExNavigationDrawer extends PureComponent { drawerPosition: this.props.drawerPosition, width: this.props.drawerWidth, renderNavigationView: this.props.renderNavigationView, + setActiveItem: this.setActiveItem, style: [ this.props.drawerStyle, ], @@ -164,7 +164,7 @@ class ExNavigationDrawer extends PureComponent { 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 ( @@ -174,26 +174,16 @@ class ExNavigationDrawer extends PureComponent { ); }; - renderItemContent(drawerItem: Object) { - if (!drawerItem.element) { - return null; - } - + renderItemContent(drawerItem: React.Element) { const navState = this._getNavigationState(); const selectedChild = navState.routes[navState.index]; - const isSelected = drawerItem.id === selectedChild.key; + const isSelected = drawerItem.props.id === selectedChild.key; - return ( - - - {drawerItem.element} - - - ); + return React.cloneElement(drawerItem, { + key: drawerItem.props.id, + isSelected, + renderTo: 'content', + }); } componentWillMount() { @@ -270,39 +260,7 @@ class ExNavigationDrawer extends PureComponent { '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({ @@ -310,12 +268,12 @@ class ExNavigationDrawer extends PureComponent { }); } - _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(); @@ -357,11 +315,4 @@ const styles = StyleSheet.create({ itemContentOuter: { flex: 1, }, - itemContentInner: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, - }, }); diff --git a/src/drawer/ExNavigationDrawerChild.js b/src/drawer/ExNavigationDrawerChild.js index f18c87a..b163e3b 100644 --- a/src/drawer/ExNavigationDrawerChild.js +++ b/src/drawer/ExNavigationDrawerChild.js @@ -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, + 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 ( + + + {content} + + + ); + } + + 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, + }, +}); diff --git a/src/drawer/ExNavigationDrawerItem.js b/src/drawer/ExNavigationDrawerItem.js index dfcdba1..54ad118 100644 --- a/src/drawer/ExNavigationDrawerItem.js +++ b/src/drawer/ExNavigationDrawerItem.js @@ -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 ( + + + { + icon && {icon} + } + { + title && {title} + } + { + rightElement && {rightElement} + } + + + ); + } else { + return ( + + + { + icon && {icon} + } + { + title && {title} + } + { + rightElement && {rightElement} + } + + + ); + } + } + + 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', + }, +}); diff --git a/src/drawer/ExNavigationDrawerLayout.js b/src/drawer/ExNavigationDrawerLayout.js index 6ceaa8a..d4210a3 100644 --- a/src/drawer/ExNavigationDrawerLayout.js +++ b/src/drawer/ExNavigationDrawerLayout.js @@ -4,15 +4,11 @@ import React from 'react'; import { - NativeModules, ScrollView, StyleSheet, - Text, - TouchableWithoutFeedback, View, } from 'react-native'; import DrawerLayout from 'react-native-drawer-layout'; -import TouchableNativeFeedbackSafe from '@exponent/react-native-touchable-native-feedback-safe'; type Props = { renderHeader: () => React.Element, @@ -21,6 +17,7 @@ type Props = { drawerBackgroundColor: string, drawerPosition: 'left' | 'right', selectedItem: any, + setActiveItem: (id: string) => void, }; type State = { @@ -78,58 +75,15 @@ export default class ExNavigationDrawerLayout extends React.Component { } return this.props.items.map((item, index) => { - let { drawerChildren, renderIcon, renderTitle, renderRight } = item; - let isSelected = this.props.selectedItem === item.id; - const icon = renderIcon && renderIcon(isSelected); - const title = renderTitle && renderTitle(isSelected); - const rightElement = renderRight && renderRight(isSelected); - - if (drawerChildren) { - return React.createElement(View, {key: index}, drawerChildren); - } - - if (item.showsTouches !== false) { - return ( - { this._handlePress(item); }} - onLongPress={() => { this._handleLongPress(item); }} - delayPressIn={0} - style={[isSelected ? item.selectedStyle : item.style]} - background={item.nativeFeedbackBackground}> - - { - icon && {icon} - } - { - title && {title} - } - { - rightElement && {rightElement} - } - - - ); - } else { - return ( - { this._handlePress(item); }} - onLongPress={() => { this._handleLongPress(item); }}> - - { - icon && {icon} - } - { - title && {title} - } - { - rightElement && {rightElement} - } - - - ); - } + let isSelected = this.props.selectedItem === item.props.id; + + return React.cloneElement(item, { + key: index, + isSelected, + onPress: () => { this._handlePress(item.props); }, + onLongPress: () => { this._handleLongPress(item.props); }, + renderTo: 'drawer', + }); }); } @@ -137,7 +91,11 @@ export default class ExNavigationDrawerLayout extends React.Component { // onPress and onLongPress should fire after close drawer! // _handlePress = (item: any) => { - item.onPress(); + if (item.onPress) { + item.onPress(); + } else { + this.props.setActiveItem(item.id); + } this._component.closeDrawer(); } @@ -159,21 +117,4 @@ const styles = StyleSheet.create({ navigationViewScrollableContentContainer: { paddingTop: 8, }, - 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' - } }); From 895923cd81ba532e702df6114d18a6177c4f416a Mon Sep 17 00:00:00 2001 From: Daniel Friesen Date: Thu, 10 Nov 2016 12:47:54 -0800 Subject: [PATCH 3/6] Use a reactElement.type prototype check instead of direct type equivalence This allows DrawerNavigationChild and DrawerNavigationItem to be extended with a project's patterns. --- example/components/DrawerNavigationExample.js | 13 +++++++++---- src/drawer/ExNavigationDrawer.js | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/example/components/DrawerNavigationExample.js b/example/components/DrawerNavigationExample.js index 7b9e96f..7d5a73f 100644 --- a/example/components/DrawerNavigationExample.js +++ b/example/components/DrawerNavigationExample.js @@ -1,7 +1,6 @@ import React, { Component } from 'react'; import { StyleSheet, - View, Text, Image, } from 'react-native'; @@ -14,6 +13,14 @@ import { import { Ionicons } from '@exponent/vector-icons'; import { Router } from '../main'; +class Heading extends DrawerNavigationChild { + renderDrawerItem() { + return ( + {this.props.title} + ); + } +} + export default class DrawerNavigationExample extends Component { _renderHeader = () => { @@ -69,9 +76,7 @@ export default class DrawerNavigationExample extends Component { initialRoute={Router.getRoute('home')} /> - - Meta - + { } invariant( - child.type === ExNavigationDrawerItem || child.type === ExNavigationDrawerChild, - 'All children of DrawerNavigation must be DrawerNavigationItems or DrawerNavigationChilds.', + child.type instanceof Object && ExNavigationDrawerChild.prototype.isPrototypeOf(child.type.prototype), + 'All children of DrawerNavigation must be DrawerNavigationChild descendant components.' ); return child; From 55e5c4bade2f6eb98d4fd8ecefd7c6a38a067c06 Mon Sep 17 00:00:00 2001 From: Daniel Friesen Date: Tue, 15 Nov 2016 16:03:35 -0800 Subject: [PATCH 4/6] Fix for isPrototypeOf not applying to itself --- src/drawer/ExNavigationDrawer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/drawer/ExNavigationDrawer.js b/src/drawer/ExNavigationDrawer.js index fd520b0..7e45c1c 100644 --- a/src/drawer/ExNavigationDrawer.js +++ b/src/drawer/ExNavigationDrawer.js @@ -256,7 +256,8 @@ class ExNavigationDrawer extends PureComponent { } invariant( - child.type instanceof Object && ExNavigationDrawerChild.prototype.isPrototypeOf(child.type.prototype), + child.type.prototype === ExNavigationDrawerChild.prototype || + child.type instanceof Object && ExNavigationDrawerChild.prototype.isPrototypeOf(child.type.prototype), 'All children of DrawerNavigation must be DrawerNavigationChild descendant components.' ); From 8cfc4dca1b938527ee3c2e4918f3efffb2f7349b Mon Sep 17 00:00:00 2001 From: Daniel Friesen Date: Tue, 15 Nov 2016 16:05:01 -0800 Subject: [PATCH 5/6] Allow DrawerNavigationItem props to be overwritten in subclasses using getters or methods on the class --- example/components/DrawerNavigationExample.js | 108 +++++++++++------- src/drawer/ExNavigationDrawerItem.js | 30 ++++- 2 files changed, 92 insertions(+), 46 deletions(-) diff --git a/example/components/DrawerNavigationExample.js b/example/components/DrawerNavigationExample.js index 7d5a73f..e737798 100644 --- a/example/components/DrawerNavigationExample.js +++ b/example/components/DrawerNavigationExample.js @@ -1,6 +1,7 @@ import React, { Component } from 'react'; import { StyleSheet, + View, Text, Image, } from 'react-native'; @@ -21,72 +22,93 @@ class Heading extends DrawerNavigationChild { } } -export default class DrawerNavigationExample extends Component { - - _renderHeader = () => { +class DrawerItem extends DrawerNavigationItem { + renderIcon = (isSelected: bool) => { + let extraStyle = {marginTop: 2}; + if (this.props.icon === 'md-alert') { + extraStyle = {...extraStyle, marginLeft: -3}; + } return ( - - - + ); }; - _renderTitle = (text: string, isSelected: bool) => { + renderTitle = (isSelected: bool) => { return ( - {text} + {this.props.title} ); }; - _renderIcon = (name: string, isSelected: bool) => { - let extraStyle = {marginTop: 2}; - if (name === 'md-alert') { - extraStyle = {...extraStyle, marginLeft: -3}; - } + get selectedItemStyle() { + return styles.selectedItemStyle; + } + + get children() { + let { defaultRouteConfig } = this.props; + return ( - ); + } +} + +export default class DrawerNavigationExample extends Component { + renderHeader = () => { + return ( + + + + ); }; render() { return ( - this._renderTitle('Examples', isSelected)} - renderIcon={isSelected => this._renderIcon('md-apps', isSelected)}> - - - - + + this._renderTitle('About', isSelected)} - renderIcon={isSelected => this._renderIcon('md-alert', isSelected)}> - - + icon="md-alert" + title="About" + defaultRouteConfig={{ + navigationBar: { + backgroundColor: '#0084FF', + tintColor: '#fff', + }, + }} + stack={{ + id: 'root', + initialRoute: Router.getRoute('about'), + }} + /> ); } diff --git a/src/drawer/ExNavigationDrawerItem.js b/src/drawer/ExNavigationDrawerItem.js index 54ad118..4f0d26e 100644 --- a/src/drawer/ExNavigationDrawerItem.js +++ b/src/drawer/ExNavigationDrawerItem.js @@ -8,11 +8,34 @@ import TouchableNativeFeedbackSafe from '@exponent/react-native-touchable-native import ExNavigationDrawerChild from './ExNavigationDrawerChild'; import type { Props } from './ExNavigationDrawerChild'; +function _set(self, name, fn) { + // Stop use of `get` from interfering with `renderTitle => ...` in subclasses + Object.defineProperty(self, name, { + value: fn, + }); +} + export default class ExNavigationDrawerItem extends ExNavigationDrawerChild { props: Props; + get showsTouches() { return this.props.showsTouches; } + get renderIcon() { return this.props.renderIcon; } + get renderTitle() { return this.props.renderTitle; } + get renderRight() { return this.props.renderRight; } + get onPress() { return this.props.onPress; } + get onLongPress() { return this.props.onLongPress; } + get children() { return this.props.children; } + set showsTouches(fn) { _set(this, 'showsTouches', fn); } + set renderIcon(fn) { _set(this, 'renderIcon', fn); } + set renderTitle(fn) { _set(this, 'renderTitle', fn); } + set renderRight(fn) { _set(this, 'renderRight', fn); } + set onPress(fn) { _set(this, 'onPress', fn); } + set onLongPress(fn) { _set(this, 'onLongPress', fn); } + set children(fn) { _set(this, 'children', fn); } + renderDrawerItem() { - let { showsTouches, isSelected, renderIcon, renderTitle, renderRight, onPress, onLongPress } = this.props; + let { isSelected } = this.props; + let { showsTouches, renderIcon, renderTitle, renderRight, onPress, onLongPress } = this; const icon = renderIcon && renderIcon(isSelected); const title = renderTitle && renderTitle(isSelected); const rightElement = renderRight && renderRight(isSelected); @@ -60,8 +83,9 @@ export default class ExNavigationDrawerItem extends ExNavigationDrawerChild { } renderContent() { - if (React.Children.count(this.props.children) > 0) { - return React.Children.only(this.props.children); + const children = this.children; + if (React.Children.count(children) > 0) { + return React.Children.only(children); } return null; From 5c3b7582d07ab55f4d2bd3facf9f99d0a48e5fb9 Mon Sep 17 00:00:00 2001 From: Daniel Friesen Date: Thu, 17 Nov 2016 10:36:31 -0800 Subject: [PATCH 6/6] =?UTF-8?q?Add=20options=20to=20DrawerNavigationLayout?= =?UTF-8?q?=E2=80=99s=20renderNavigationView=20prop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Include renderHeader and renderDrawerItems so the replacement function is able to replicate the standard drawer navigation view layout - Include the internal styles used as containerStyle and scrollableContentContainerStyle so the styles can also be replicated - Make renderDrawerItems accept items from an arg instead of a prop so that the items list can be filtered --- src/drawer/ExNavigationDrawerLayout.js | 39 ++++++++++++++++++++------ 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/drawer/ExNavigationDrawerLayout.js b/src/drawer/ExNavigationDrawerLayout.js index d4210a3..4d24ab3 100644 --- a/src/drawer/ExNavigationDrawerLayout.js +++ b/src/drawer/ExNavigationDrawerLayout.js @@ -10,9 +10,19 @@ import { } from 'react-native'; import DrawerLayout from 'react-native-drawer-layout'; +type NavigationViewOptions = { + renderHeader: () => React.Element, + renderDrawerItems: (items: Array>) => Array>, + items: Array>, + containerStyle: Array, + scrollableContentContainerStyle: Array, +}; + type Props = { renderHeader: () => React.Element, + renderNavigationView: (options:NavigationViewOptions) => React.Element, width: number, + items: Array>, children: React.Element, drawerBackgroundColor: string, drawerPosition: 'left' | 'right', @@ -41,7 +51,7 @@ export default class ExNavigationDrawerLayout extends React.Component { drawerBackgroundColor={this.props.drawerBackgroundColor} drawerWidth={this.props.width} drawerPosition={DrawerLayout.positions[position]} - renderNavigationView={this.props.renderNavigationView || this._renderNavigationView}> + renderNavigationView={this._renderNavigationView}> {this.props.children} ); @@ -56,25 +66,36 @@ export default class ExNavigationDrawerLayout extends React.Component { } _renderNavigationView = () => { + const renderNavigationView = this.props.renderNavigationView || this.renderNavigationView; + return renderNavigationView({ + renderHeader: this.props.renderHeader, + renderDrawerItems: this.renderDrawerItems, + items: this.props.items, + containerStyle: [styles.navigationViewContainer, this.props.style], + scrollableContentContainerStyle: [styles.navigationViewScrollableContentContainer], + }); + } + + renderNavigationView = ({renderHeader, renderDrawerItems, items, containerStyle, scrollableContentContainerStyle}:NavigationViewOptions) => { return ( - + - {this.props.renderHeader()} + {renderHeader()} - - {this._renderDrawerItems()} + + {renderDrawerItems(items)} ); } - _renderDrawerItems = () => { - if (!this.props.items) { - return null; + renderDrawerItems = (items: Array>) => { + if (!items) { + return []; } - return this.props.items.map((item, index) => { + return items.map((item, index) => { let isSelected = this.props.selectedItem === item.props.id; return React.cloneElement(item, {