diff --git a/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/BreadcrumbNavSample.js b/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/BreadcrumbNavSample.js new file mode 100644 index 000000000..15251a4cf --- /dev/null +++ b/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/BreadcrumbNavSample.js @@ -0,0 +1,164 @@ +/** + * The examples provided by Facebook are for non-commercial testing and + * evaluation purposes only. + * + * Facebook reserves all rights not expressly granted. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL + * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +'use strict'; + +var React = require('react-native'); +var { + NavigationExperimental, + StyleSheet, + ScrollView, + Text, + TouchableHighlight, + TouchableOpacity +} = React; + +var _getRandomRoute = function() { + return { + title: '#' + Math.ceil(Math.random() * 1000), + }; +}; + +var Navigator = NavigationExperimental.LegacyNavigator; + +class NavButton extends React.Component { + render() { + return ( + + {this.props.text} + + ); + } +} + +var BreadcrumbNavSample = React.createClass({ + + componentWillMount: function() { + this._navBarRouteMapper = { + rightContentForRoute: function(route, navigator) { + return null; + }, + titleContentForRoute: function(route, navigator) { + return ( + navigator.push(_getRandomRoute())}> + {route.title} + + ); + }, + iconForRoute: function(route, navigator) { + return ( + { navigator.popToRoute(route); }} + style={styles.crumbIconPlaceholder} + /> + ); + }, + separatorForRoute: function(route, navigator) { + return ( + + ); + } + }; + }, + + _renderScene: function(route, navigator) { + return ( + + { navigator.push(_getRandomRoute()); }} + text="Push" + /> + { navigator.immediatelyResetRouteStack([_getRandomRoute(), _getRandomRoute()]); }} + text="Reset w/ 2 scenes" + /> + { navigator.popToTop(); }} + text="Pop to top" + /> + { navigator.replace(_getRandomRoute()); }} + text="Replace" + /> + { this.props.navigator.pop(); }} + text="Close breadcrumb example" + /> + + ); + }, + + render: function() { + return ( + + } + /> + ); + }, + + + +}); + +var styles = StyleSheet.create({ + scene: { + paddingTop: 50, + flex: 1, + }, + button: { + backgroundColor: 'white', + padding: 15, + borderBottomWidth: StyleSheet.hairlineWidth, + borderBottomColor: '#CDCDCD', + }, + buttonText: { + fontSize: 17, + fontWeight: '500', + }, + container: { + overflow: 'hidden', + backgroundColor: '#dddddd', + flex: 1, + }, + titleText: { + fontSize: 18, + color: '#666666', + textAlign: 'center', + fontWeight: 'bold', + lineHeight: 32, + }, + crumbIconPlaceholder: { + flex: 1, + backgroundColor: '#666666', + }, + crumbSeparatorPlaceholder: { + flex: 1, + backgroundColor: '#aaaaaa', + }, +}); + +module.exports = BreadcrumbNavSample; diff --git a/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/JumpingNavSample.js b/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/JumpingNavSample.js new file mode 100644 index 000000000..aa2b9fd7d --- /dev/null +++ b/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/JumpingNavSample.js @@ -0,0 +1,218 @@ +/** + * The examples provided by Facebook are for non-commercial testing and + * evaluation purposes only. + * + * Facebook reserves all rights not expressly granted. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL + * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +'use strict'; + +var React = require('react-native'); +var { + NavigationExperimental, + StyleSheet, + ScrollView, + TabBarIOS, + Text, + TouchableHighlight, + View, +} = React; + +var _getRandomRoute = function() { + return { + randNumber: Math.ceil(Math.random() * 1000), + }; +}; + +var Navigator = NavigationExperimental.LegacyNavigator; + +class NavButton extends React.Component { + render() { + return ( + + {this.props.text} + + ); + } +} + +var ROUTE_STACK = [ + _getRandomRoute(), + _getRandomRoute(), + _getRandomRoute(), +]; +var INIT_ROUTE_INDEX = 1; + +class JumpingNavBar extends React.Component { + constructor(props) { + super(props); + this.state = { + tabIndex: props.initTabIndex, + }; + } + handleWillFocus(route) { + var tabIndex = ROUTE_STACK.indexOf(route); + this.setState({ tabIndex, }); + } + render() { + return ( + + + { + this.props.onTabIndex(0); + this.setState({ tabIndex: 0, }); + }}> + + + { + this.props.onTabIndex(1); + this.setState({ tabIndex: 1, }); + }}> + + + { + this.props.onTabIndex(2); + this.setState({ tabIndex: 2, }); + }}> + + + + + ); + } +} + +var JumpingNavSample = React.createClass({ + render: function() { + return ( + { + this._navigator = navigator; + }} + initialRoute={ROUTE_STACK[INIT_ROUTE_INDEX]} + initialRouteStack={ROUTE_STACK} + renderScene={this.renderScene} + configureScene={() => ({ + ...Navigator.SceneConfigs.HorizontalSwipeJump, + })} + navigationBar={ + { this.navBar = navBar; }} + initTabIndex={INIT_ROUTE_INDEX} + routeStack={ROUTE_STACK} + onTabIndex={(index) => { + this._navigator.jumpTo(ROUTE_STACK[index]); + }} + /> + } + /> + ); + }, + + renderScene: function(route, navigator) { + var backBtn; + var forwardBtn; + if (ROUTE_STACK.indexOf(route) !== 0) { + backBtn = ( + { + navigator.jumpBack(); + }} + text="jumpBack" + /> + ); + } + if (ROUTE_STACK.indexOf(route) !== ROUTE_STACK.length - 1) { + forwardBtn = ( + { + navigator.jumpForward(); + }} + text="jumpForward" + /> + ); + } + return ( + + #{route.randNumber} + {backBtn} + {forwardBtn} + { + navigator.jumpTo(ROUTE_STACK[1]); + }} + text="jumpTo middle route" + /> + { + this.props.navigator.pop(); + }} + text="Exit Navigation Example" + /> + { + this.props.navigator.push({ + message: 'Came from jumping example', + }); + }} + text="Nav Menu" + /> + + ); + }, +}); + +var styles = StyleSheet.create({ + button: { + backgroundColor: 'white', + padding: 15, + borderBottomWidth: StyleSheet.hairlineWidth, + borderBottomColor: '#CDCDCD', + }, + buttonText: { + fontSize: 17, + fontWeight: '500', + }, + appContainer: { + overflow: 'hidden', + backgroundColor: '#dddddd', + flex: 1, + }, + messageText: { + fontSize: 17, + fontWeight: '500', + padding: 15, + marginTop: 50, + marginLeft: 15, + }, + scene: { + flex: 1, + paddingTop: 20, + backgroundColor: '#EAEAEA', + }, + tabs: { + height: 50, + } +}); + +module.exports = JumpingNavSample; diff --git a/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/LegacyNavigatorExample.js b/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/LegacyNavigatorExample.js new file mode 100644 index 000000000..ed4169751 --- /dev/null +++ b/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/LegacyNavigatorExample.js @@ -0,0 +1,212 @@ +/** + * The examples provided by Facebook are for non-commercial testing and + * evaluation purposes only. + * + * Facebook reserves all rights not expressly granted. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL + * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +'use strict'; + +var React = require('react-native'); +var { + NavigationExperimental, + ScrollView, + StyleSheet, + Text, + TouchableHighlight, +} = React; + +var BreadcrumbNavSample = require('./BreadcrumbNavSample'); +var NavigationBarSample = require('./NavigationBarSample'); +var JumpingNavSample = require('./JumpingNavSample'); + +var Navigator = NavigationExperimental.LegacyNavigator; + +class NavButton extends React.Component { + render() { + return ( + + {this.props.text} + + ); + } +} + +class NavMenu extends React.Component { + render() { + return ( + + {this.props.message} + { + this.props.navigator.push({ + message: 'Swipe right to dismiss', + sceneConfig: Navigator.SceneConfigs.FloatFromRight, + }); + }} + text="Float in from right" + /> + { + this.props.navigator.push({ + message: 'Swipe down to dismiss', + sceneConfig: Navigator.SceneConfigs.FloatFromBottom, + }); + }} + text="Float in from bottom" + /> + { + this.props.navigator.pop(); + }} + text="Pop" + /> + { + this.props.navigator.popToTop(); + }} + text="Pop to top" + /> + { + this.props.navigator.push({ id: 'navbar' }); + }} + text="Navbar Example" + /> + { + this.props.navigator.push({ id: 'jumping' }); + }} + text="Jumping Example" + /> + { + this.props.navigator.push({ id: 'breadcrumbs' }); + }} + text="Breadcrumbs Example" + /> + { + this.props.onExampleExit(); + }} + text="Exit Example" + /> + + ); + } +} + +var TabBarExample = React.createClass({ + + statics: { + title: ' (Experimental)', + description: 'Experimental navigator that ports the API of the current ' + + 'Navigator component', + }, + + renderScene: function(route, nav) { + switch (route.id) { + case 'navbar': + return ; + case 'breadcrumbs': + return ; + case 'jumping': + return ; + default: + return ( + + ); + } + }, + + render: function() { + return ( + { + if (route.sceneConfig) { + return route.sceneConfig; + } + return Navigator.SceneConfigs.FloatFromBottom; + }} + /> + ); + }, + + + componentWillUnmount: function() { + this._listeners && this._listeners.forEach(listener => listener.remove()); + }, + + _setNavigatorRef: function(navigator) { + if (navigator !== this._navigator) { + this._navigator = navigator; + + if (navigator) { + var callback = (event) => { + console.log( + `TabBarExample: event ${event.type}`, + { + route: JSON.stringify(event.data.route), + target: event.target, + type: event.type, + } + ); + }; + // Observe focus change events from the owner. + this._listeners = [ + navigator.navigationContext.addListener('willfocus', callback), + navigator.navigationContext.addListener('didfocus', callback), + ]; + } + } + }, +}); + +var styles = StyleSheet.create({ + messageText: { + fontSize: 17, + fontWeight: '500', + padding: 15, + marginTop: 50, + marginLeft: 15, + }, + container: { + flex: 1, + }, + button: { + backgroundColor: 'white', + padding: 15, + borderBottomWidth: StyleSheet.hairlineWidth, + borderBottomColor: '#CDCDCD', + }, + buttonText: { + fontSize: 17, + fontWeight: '500', + }, + scene: { + flex: 1, + paddingTop: 20, + backgroundColor: '#ccc', + } +}); + +TabBarExample.external = true; + +module.exports = TabBarExample; diff --git a/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/NavigationBarSample.js b/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/NavigationBarSample.js new file mode 100644 index 000000000..9b9081dd0 --- /dev/null +++ b/Examples/UIExplorer/NavigationExperimental/LegacyNavigator/NavigationBarSample.js @@ -0,0 +1,203 @@ +/** + * The examples provided by Facebook are for non-commercial testing and + * evaluation purposes only. + * + * Facebook reserves all rights not expressly granted. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL + * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +'use strict'; + + +var React = require('react-native'); +var { + NavigationExperimental, + ScrollView, + StyleSheet, + Text, + TouchableHighlight, + TouchableOpacity, +} = React; + +var cssVar = require('cssVar'); + +var Navigator = NavigationExperimental.LegacyNavigator; + +class NavButton extends React.Component { + render() { + return ( + + {this.props.text} + + ); + } +} + +var NavigationBarRouteMapper = { + + LeftButton: function(route, navigator, index, navState) { + if (index === 0) { + return null; + } + + var previousRoute = navState.routeStack[index - 1]; + return ( + navigator.pop()} + style={styles.navBarLeftButton}> + + {previousRoute.title} + + + ); + }, + + RightButton: function(route, navigator, index, navState) { + return ( + navigator.push(newRandomRoute())} + style={styles.navBarRightButton}> + + Next + + + ); + }, + + Title: function(route, navigator, index, navState) { + return ( + + {route.title} [{index}] + + ); + }, + +}; + +function newRandomRoute() { + return { + title: '#' + Math.ceil(Math.random() * 1000), + }; +} + +var NavigationBarSample = React.createClass({ + + componentWillMount: function() { + var navigator = this.props.navigator; + + var callback = (event) => { + console.log( + `NavigationBarSample : event ${event.type}`, + { + route: JSON.stringify(event.data.route), + target: event.target, + type: event.type, + } + ); + }; + + // Observe focus change events from this component. + this._listeners = [ + navigator.navigationContext.addListener('willfocus', callback), + navigator.navigationContext.addListener('didfocus', callback), + ]; + }, + + componentWillUnmount: function() { + this._listeners && this._listeners.forEach(listener => listener.remove()); + }, + + render: function() { + return ( + ( + + {route.content} + { + navigator.immediatelyResetRouteStack([ + newRandomRoute(), + newRandomRoute(), + newRandomRoute(), + ]); + }} + text="Reset w/ 3 scenes" + /> + { + this.props.navigator.pop(); + }} + text="Exit NavigationBar Example" + /> + + )} + navigationBar={ + + } + /> + ); + }, + +}); + +var styles = StyleSheet.create({ + messageText: { + fontSize: 17, + fontWeight: '500', + padding: 15, + marginTop: 50, + marginLeft: 15, + }, + button: { + backgroundColor: 'white', + padding: 15, + borderBottomWidth: StyleSheet.hairlineWidth, + borderBottomColor: '#CDCDCD', + }, + buttonText: { + fontSize: 17, + fontWeight: '500', + }, + navBar: { + backgroundColor: 'white', + }, + navBarText: { + fontSize: 16, + marginVertical: 10, + }, + navBarTitleText: { + color: cssVar('fbui-bluegray-60'), + fontWeight: '500', + marginVertical: 9, + }, + navBarLeftButton: { + paddingLeft: 10, + }, + navBarRightButton: { + paddingRight: 10, + }, + navBarButtonText: { + color: cssVar('fbui-accent-blue'), + }, + scene: { + flex: 1, + paddingTop: 20, + backgroundColor: '#EAEAEA', + }, +}); + +module.exports = NavigationBarSample; diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js b/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js index f15b9926a..f90ab6ef7 100644 --- a/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js +++ b/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js @@ -36,7 +36,7 @@ var EXAMPLES = { 'Tic Tac Toe': require('./NavigationTicTacToeExample'), }; -var EXAMPLE_STORAGE_KEY = 'NavigationExperimentalExample'; +var EXAMPLE_STORAGE_KEY = 'xNavigationExperimentalExample'; var NavigationExperimentalExample = React.createClass({ statics: { diff --git a/Examples/UIExplorer/UIExplorerList.ios.js b/Examples/UIExplorer/UIExplorerList.ios.js index 65781609d..ae7248430 100644 --- a/Examples/UIExplorer/UIExplorerList.ios.js +++ b/Examples/UIExplorer/UIExplorerList.ios.js @@ -200,6 +200,10 @@ var APIExamples: Array = [ key: 'NavigationExperimentalExample', module: require('./NavigationExperimental/NavigationExperimentalExample'), }, + { + key: 'NavigationExperimentalLegacyNavigatorExample', + module: require('./NavigationExperimental/LegacyNavigator/LegacyNavigatorExample'), + }, { key: 'NetInfoExample', module: require('./NetInfoExample'), diff --git a/Libraries/CustomComponents/NavigationExperimental/NavigationLegacyNavigator.js b/Libraries/CustomComponents/NavigationExperimental/NavigationLegacyNavigator.js new file mode 100644 index 000000000..a03bd9f4a --- /dev/null +++ b/Libraries/CustomComponents/NavigationExperimental/NavigationLegacyNavigator.js @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2015, Facebook, Inc. All rights reserved. + * + * Facebook, Inc. ("Facebook") owns all right, title and interest, including + * all intellectual property and other proprietary rights, in and to the React + * Native CustomComponents software (the "Software"). Subject to your + * compliance with these terms, you are hereby granted a non-exclusive, + * worldwide, royalty-free copyright license to (1) use and copy the Software; + * and (2) reproduce and distribute the Software as part of your own software + * ("Your Software"). Facebook reserves all rights not expressly granted to + * you in this license agreement. + * + * THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED. + * IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR + * EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @providesModule NavigationLegacyNavigator + * @flow + */ +'use strict'; + +/** + * NavigationLegacyNavigator is meant to replace Navigator seemlessly without + * API changes. While the APIs remain compatible with Navigator, it should + * be built with the new Navigation API such as `NavigationAnimatedView`...etc. + */ +const NavigationLegacyNavigator = require('Navigator'); + +module.exports = NavigationLegacyNavigator; diff --git a/Libraries/NavigationExperimental/NavigationExperimental.js b/Libraries/NavigationExperimental/NavigationExperimental.js index f9153ea68..ca6bb627d 100644 --- a/Libraries/NavigationExperimental/NavigationExperimental.js +++ b/Libraries/NavigationExperimental/NavigationExperimental.js @@ -16,6 +16,7 @@ const NavigationCard = require('NavigationCard'); const NavigationCardStack = require('NavigationCardStack'); const NavigationContainer = require('NavigationContainer'); const NavigationHeader = require('NavigationHeader'); +const NavigationLegacyNavigator = require('NavigationLegacyNavigator'); const NavigationReducer = require('NavigationReducer'); const NavigationRootContainer = require('NavigationRootContainer'); const NavigationStateUtils = require('NavigationStateUtils'); @@ -35,9 +36,10 @@ const NavigationExperimental = { AnimatedView: NavigationAnimatedView, // CustomComponents: - Header: NavigationHeader, Card: NavigationCard, CardStack: NavigationCardStack, + Header: NavigationHeader, + LegacyNavigator: NavigationLegacyNavigator, }; module.exports = NavigationExperimental;