diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationAnimatedExample.js b/Examples/UIExplorer/NavigationExperimental/NavigationAnimatedExample.js deleted file mode 100644 index 020408a5d0f..00000000000 --- a/Examples/UIExplorer/NavigationExperimental/NavigationAnimatedExample.js +++ /dev/null @@ -1,164 +0,0 @@ -/** - * Copyright (c) 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * 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'; - -const React = require('react'); -const ReactNative = require('react-native'); - -const { - Animated, - NavigationExperimental, - StyleSheet, - ScrollView, -} = ReactNative; - -const NavigationExampleRow = require('./NavigationExampleRow'); - -const { - AnimatedView: NavigationAnimatedView, - Card: NavigationCard, - Header: NavigationHeader, - Reducer: NavigationReducer, -} = NavigationExperimental; - -const ExampleReducer = NavigationReducer.StackReducer({ - getPushedReducerForAction: (action) => { - if (action.type === 'push') { - return (state) => state || {key: action.key}; - } - return null; - }, - getReducerForState: (initialState) => (state) => state || initialState, - initialState: { - key: 'AnimatedExampleStackKey', - index: 0, - routes: [ - {key: 'First Route'}, - ], - }, -}); - -class NavigationAnimatedExample extends React.Component { - constructor(props, context) { - super(props, context); - this.state = ExampleReducer(); - } - - componentWillMount() { - this._renderCard = this._renderCard.bind(this); - this._renderHeader = this._renderHeader.bind(this); - this._renderScene = this._renderScene.bind(this); - this._renderTitleComponent = this._renderTitleComponent.bind(this); - this._handleAction = this._handleAction.bind(this); - } - - _handleAction(action): boolean { - if (!action) { - return false; - } - const newState = ExampleReducer(this.state, action); - if (newState === this.state) { - return false; - } - this.setState(newState); - return true; - } - - handleBackAction(): boolean { - return this._handleAction({ type: 'BackAction', }); - } - - render() { - return ( - { - Animated.timing(pos, {toValue: navState.index, duration: 500}).start(); - }} - renderScene={this._renderCard} - /> - ); - } - - _renderHeader(/*NavigationSceneRendererProps*/ props) { - return ( - - ); - } - - _renderTitleComponent(/*NavigationSceneRendererProps*/ props) { - return ( - - {props.scene.route.key} - - ); - } - - _renderCard(/*NavigationSceneRendererProps*/ props) { - return ( - - ); - } - - _renderScene(/*NavigationSceneRendererProps*/ props) { - return ( - - - { - props.onNavigate({ - type: 'push', - key: 'Route #' + props.scenes.length, - }); - }} - /> - - - ); - } -} - -const styles = StyleSheet.create({ - animatedView: { - flex: 1, - }, - scrollView: { - marginTop: NavigationHeader.HEIGHT, - }, -}); - -module.exports = NavigationAnimatedExample; diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationBasicExample.js b/Examples/UIExplorer/NavigationExperimental/NavigationBasicExample.js deleted file mode 100644 index d296ebbd771..00000000000 --- a/Examples/UIExplorer/NavigationExperimental/NavigationBasicExample.js +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Copyright (c) 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * 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'; - -const React = require('react'); -const ReactNative = require('react-native'); -const { - NavigationExperimental, - ScrollView, - StyleSheet, -} = ReactNative; -const NavigationExampleRow = require('./NavigationExampleRow'); -const { - Reducer: NavigationReducer, -} = NavigationExperimental; - -const ExampleReducer = NavigationReducer.StackReducer({ - getPushedReducerForAction: (action) => { - if (action.type === 'push') { - return (state) => state || {key: action.key}; - } - return null; - }, - getReducerForState: (initialState) => (state) => state || initialState, - initialState: { - key: 'BasicExampleStackKey', - index: 0, - routes: [ - {key: 'First Route'}, - ], - }, -}); - -const NavigationBasicExample = React.createClass({ - - getInitialState: function() { - return ExampleReducer(); - }, - - render: function() { - return ( - - - { - this._handleAction({ type: 'push', key: 'page #' + this.state.routes.length }); - }} - /> - { - this._handleAction({ type: 'BackAction' }); - }} - /> - - - ); - }, - - _handleAction(action) { - if (!action) { - return false; - } - const newState = ExampleReducer(this.state, action); - if (newState === this.state) { - return false; - } - this.setState(newState); - return true; - }, - - handleBackAction() { - return this._handleAction({ type: 'BackAction' }); - }, - -}); - -const styles = StyleSheet.create({ - topView: { - backgroundColor: '#E9E9EF', - flex: 1, - paddingTop: 30, - }, -}); - -module.exports = NavigationBasicExample; diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationCardStack-example.js b/Examples/UIExplorer/NavigationExperimental/NavigationCardStack-example.js new file mode 100644 index 00000000000..c54cc1ba9e9 --- /dev/null +++ b/Examples/UIExplorer/NavigationExperimental/NavigationCardStack-example.js @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * 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'; + +const NavigationExampleRow = require('./NavigationExampleRow'); +const React = require('react'); +const ReactNative = require('react-native'); + +const emptyFunction = require('fbjs/lib/emptyFunction'); + +/** + * Basic example that shows how to use to build + * an app with controlled navigation system. + */ +const { + NavigationExperimental, + ScrollView, + StyleSheet, +} = ReactNative; + +const { + CardStack: NavigationCardStack, + StateUtils: NavigationStateUtils, +} = NavigationExperimental; + +// Step 1: +// Define a component for your application. +class YourApplication extends React.Component { + + // This sets up the initial navigation state. + constructor(props, context) { + super(props, context); + + this.state = { + // This defines the initial navigation state. + navigationState: { + index: 0, // starts with first route focused. + routes: [{key: 'Welcome'}], // starts with only one route. + }, + }; + + this._exit = this._exit.bind(this); + this._onNavigationChange = this._onNavigationChange.bind(this); + } + + // User your own navigator (see Step 2). + render(): ReactElement { + return ( + + ); + } + + // This handles the navigation state changes. You're free and responsible + // to define the API that changes that navigation state. In this exmaple, + // we'd simply use a `function(type: string)` to update the navigation state. + _onNavigationChange(type: string): void { + let {navigationState} = this.state; + switch (type) { + case 'push': + // push a new route. + const route = {key: Date.now()}; + navigationState = NavigationStateUtils.push(navigationState, route); + break; + + case 'pop': + navigationState = NavigationStateUtils.pop(navigationState); + break; + } + + // NavigationStateUtils gives you back the same `navigationState` if nothing + // has changed. You could use that to avoid redundant re-rendering. + if (this.state.navigationState !== navigationState) { + this.setState({navigationState}); + } + } + + // Exits the example. `this.props.onExampleExit` is provided + // by the UI Explorer. + _exit(): void { + this.props.onExampleExit && this.props.onExampleExit(); + } + + // This public method is optional. If exists, the UI explorer will call it + // the "back button" is pressed. Normally this is the cases for Android only. + handleBackAction(): boolean { + return this._onNavigationChange('pop'); + } +} + +// Step 2: +// Define your own controlled navigator. +// +// +------------+ +// +-+ | +// +-+ | | +// | | | | +// | | | Active | +// | | | Scene | +// | | | | +// +-+ | | +// +-+ | +// +------------+ +// +class YourNavigator extends React.Component { + + // This sets up the methods (e.g. Pop, Push) for navigation. + constructor(props: any, context: any) { + super(props, context); + + this._onPushRoute = this.props.onNavigationChange.bind(null, 'push'); + this._onPopRoute = this.props.onNavigationChange.bind(null, 'pop'); + + this._renderScene = this._renderScene.bind(this); + } + + // Now use the `NavigationCardStack` to render the scenes. + render(): ReactElement { + // TODO(hedger): prop `onNavigate` will be deprecated soon. For now, + // use `emptyFunction` as a placeholder. + return ( + + ); + } + + // Render a scene for route. + // The detailed spec of `sceneProps` is defined at `NavigationTypeDefinition` + // as type `NavigationSceneRendererProps`. + _renderScene(sceneProps: Object): ReactElement { + return ( + + ); + } +} + +// Step 3: +// Define your own scene. +class YourScene extends React.Component { + render() { + return ( + + + + + + + ); + } +} + +const styles = StyleSheet.create({ + navigator: { + flex: 1, + }, + scrollView: { + marginTop: 64 + }, +}); + +module.exports = YourApplication; diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationCardStackExample.js b/Examples/UIExplorer/NavigationExperimental/NavigationCardStackExample.js deleted file mode 100644 index bf00ad739ba..00000000000 --- a/Examples/UIExplorer/NavigationExperimental/NavigationCardStackExample.js +++ /dev/null @@ -1,165 +0,0 @@ -/** - * Copyright (c) 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * 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'; - -const NavigationExampleRow = require('./NavigationExampleRow'); -const React = require('react'); -const ReactNative = require('react-native'); - -const { - NavigationExperimental, - StyleSheet, - ScrollView, -} = ReactNative; - -const { - CardStack: NavigationCardStack, - StateUtils: NavigationStateUtils, -} = NavigationExperimental; - -function createReducer(initialState) { - return (currentState = initialState, action) => { - switch (action.type) { - case 'push': - return NavigationStateUtils.push(currentState, {key: action.key}); - - case 'BackAction': - case 'back': - case 'pop': - return currentState.index > 0 ? - NavigationStateUtils.pop(currentState) : - currentState; - - default: - return currentState; - } - }; -} - -const ExampleReducer = createReducer({ - index: 0, - key: 'exmaple', - routes: [{key: 'First Route'}], -}); - -class NavigationCardStackExample extends React.Component { - - constructor(props, context) { - super(props, context); - this.state = { - isHorizontal: true, - navState: ExampleReducer(undefined, {}), - }; - } - - componentWillMount() { - this._renderScene = this._renderScene.bind(this); - this._toggleDirection = this._toggleDirection.bind(this); - this._handleAction = this._handleAction.bind(this); - } - - render() { - return ( - - ); - } - - _handleAction(action): boolean { - if (!action) { - return false; - } - const newState = ExampleReducer(this.state.navState, action); - if (newState === this.state.navState) { - return false; - } - this.setState({ - navState: newState, - }); - return true; - } - - handleBackAction(): boolean { - return this._handleAction({ type: 'BackAction', }); - } - - _renderScene(/*NavigationSceneRendererProps*/ props) { - return ( - - - - { - props.onNavigate({ - type: 'push', - key: 'Route ' + props.scenes.length, - }); - }} - /> - { - props.onNavigate({ - type: 'pop', - }); - }} - /> - - - ); - } - - _toggleDirection() { - this.setState({ - isHorizontal: !this.state.isHorizontal, - }); - } - -} - -const styles = StyleSheet.create({ - main: { - flex: 1, - }, - scrollView: { - marginTop: 64 - }, -}); - -module.exports = NavigationCardStackExample; diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationCompositionExample.js b/Examples/UIExplorer/NavigationExperimental/NavigationCompositionExample.js deleted file mode 100644 index 261e8060dff..00000000000 --- a/Examples/UIExplorer/NavigationExperimental/NavigationCompositionExample.js +++ /dev/null @@ -1,321 +0,0 @@ -/** - * Copyright (c) 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * 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. - * - * @flow - */ -'use strict'; - -const React = require('react'); -const ReactNative = require('react-native'); -const NavigationExampleRow = require('./NavigationExampleRow'); -const NavigationExampleTabBar = require('./NavigationExampleTabBar'); - -const { - NavigationExperimental, - ScrollView, - StyleSheet, - View, -} = ReactNative; - -const { - CardStack: NavigationCardStack, - Header: NavigationHeader, - Reducer: NavigationReducer, -} = NavigationExperimental; - - -import type { - NavigationState, - NavigationSceneRenderer, - NavigationSceneRendererProps, -} from 'NavigationTypeDefinition'; - -type Action = { - isExitAction?: boolean, -}; - -const ExampleExitAction = () => ({ - isExitAction: true, -}); - -ExampleExitAction.match = (action: Action) => ( - action && action.isExitAction === true -); - -const PageAction = (type) => ({ - type, - isPageAction: true, -}); - -PageAction.match = (action) => ( - action && action.isPageAction === true -); - -const ExampleProfilePageAction = (type) => ({ - ...PageAction(type), - isProfilePageAction: true, -}); - -ExampleProfilePageAction.match = (action) => ( - action && action.isProfilePageAction === true -); - -const ExampleInfoAction = () => PageAction('InfoPage'); - -const ExampleNotifProfileAction = () => ExampleProfilePageAction('NotifProfilePage'); - -const _jsInstanceUniqueId = '' + Date.now(); - -let _uniqueIdCount = 0; - -function pageStateActionMap(action) { - return { - key: 'page-' + _jsInstanceUniqueId + '-' + (_uniqueIdCount++), - type: action.type, - }; -} - -const ExampleAppReducer = NavigationReducer.TabsReducer({ - key: 'AppNavigationState', - initialIndex: 0, - tabReducers: [ - NavigationReducer.StackReducer({ - getPushedReducerForAction: (action) => { - if (PageAction.match(action) && !ExampleProfilePageAction.match(action)) { - return (state) => (state || pageStateActionMap(action)); - } - return null; - }, - initialState: { - key: 'notifs', - index: 0, - routes: [ - {key: 'base', type: 'NotifsPage'}, - ], - }, - }), - NavigationReducer.StackReducer({ - getPushedReducerForAction: (action) => { - if (PageAction.match(action) && !ExampleProfilePageAction.match(action)) { - return (state) => (state || pageStateActionMap(action)); - } - return null; - }, - initialState: { - key: 'settings', - index: 0, - routes: [ - {key: 'base', type: 'SettingsPage'}, - ], - }, - }), - NavigationReducer.StackReducer({ - getPushedReducerForAction: (action) => { - if (PageAction.match(action) || ExampleProfilePageAction.match(action)) { - return (state) => (state || pageStateActionMap(action)); - } - return null; - }, - initialState: { - key: 'profile', - index: 0, - routes: [ - {key: 'base', type: 'ProfilePage'}, - ], - }, - }), - ], -}); - -function stateTypeTitleMap(pageState: any) { - switch (pageState.type) { - case 'ProfilePage': - return 'Profile Page'; - case 'NotifsPage': - return 'Notifications'; - case 'SettingsPage': - return 'Settings'; - case 'InfoPage': - return 'Info Page'; - case 'NotifProfilePage': - return 'Page in Profile'; - } -} - -class ExampleTabScreen extends React.Component { - _renderCard: NavigationSceneRenderer; - _renderHeader: NavigationSceneRenderer; - _renderScene: NavigationSceneRenderer; - - componentWillMount() { - this._renderHeader = this._renderHeader.bind(this); - this._renderScene = this._renderScene.bind(this); - } - - render() { - return ( - - ); - } - _renderHeader(props: NavigationSceneRendererProps) { - return ( - - ); - } - - _renderTitleComponent(props: NavigationSceneRendererProps) { - return ( - - {stateTypeTitleMap(props.scene.route)} - - ); - } - - _renderScene(props: NavigationSceneRendererProps) { - const {onNavigate} = props; - return ( - - { - onNavigate(ExampleInfoAction()); - }} - /> - { - onNavigate(ExampleNotifProfileAction()); - }} - /> - { - onNavigate(ExampleExitAction()); - }} - /> - - ); - } -} - -class NavigationCompositionExample extends React.Component { - state: NavigationState; - constructor() { - super(); - this.state = ExampleAppReducer(undefined, {}); - } - handleAction(action: Object): boolean { - if (!action) { - return false; - } - const newState = ExampleAppReducer(this.state, action); - if (newState === this.state) { - return false; - } - this.setState(newState); - return true; - } - handleBackAction(): boolean { - return this.handleAction({ type: 'BackAction' }); - } - render() { - if (!this.state) { - return null; - } - return ( - - - - - ); - } -} - -class ExampleMainView extends React.Component { - _renderScene: Function; - _handleNavigation: Function; - - componentWillMount() { - this._renderScene = this._renderScene.bind(this); - this._handleNavigation = this._handleNavigation.bind(this); - } - - render() { - return ( - - {this._renderScene()} - - ); - } - - _renderScene(): ReactElement { - const {navigationState} = this.props; - const childState = navigationState.routes[navigationState.index]; - return ( - - ); - } - - _handleNavigation(action: Object) { - if (ExampleExitAction.match(action)) { - this.props.onExampleExit(); - return; - } - this.props.onNavigate(action); - } -} - -const styles = StyleSheet.create({ - topView: { - flex: 1, - }, - tabsContent: { - flex: 1, - }, - scrollView: { - marginTop: NavigationHeader.HEIGHT - }, - tabContent: { - flex: 1, - }, -}); - -module.exports = NavigationCompositionExample; diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationExampleTabBar.js b/Examples/UIExplorer/NavigationExperimental/NavigationExampleTabBar.js deleted file mode 100644 index 40f525466f9..00000000000 --- a/Examples/UIExplorer/NavigationExperimental/NavigationExampleTabBar.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (c) 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * 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'; - -const NavigationExperimental = require('NavigationExperimental'); -const React = require('react'); -const StyleSheet = require('StyleSheet'); -const Text = require('Text'); -const TouchableOpacity = require('TouchableOpacity'); -const View = require('View'); -const { - Reducer: NavigationReducer, -} = NavigationExperimental; -const { - JumpToAction, -} = NavigationReducer.TabsReducer; - -const NavigationExampleTabBar = React.createClass({ - render: function() { - return ( - - {this.props.tabs.map(this._renderTab)} - - ); - }, - _renderTab: function(tab, index) { - const textStyle = [styles.tabButtonText]; - if (this.props.index === index) { - textStyle.push(styles.selectedTabButtonText); - } - return ( - { - this.props.onNavigate(JumpToAction(index)); - }}> - - {tab.key} - - - ); - }, -}); - -const styles = StyleSheet.create({ - tabBar: { - height: 50, - flexDirection: 'row', - }, - tabButton: { - flex: 1, - }, - tabButtonText: { - paddingTop: 20, - textAlign: 'center', - fontSize: 17, - fontWeight: '500', - }, - selectedTabButtonText: { - color: 'blue', - }, -}); - -module.exports = NavigationExampleTabBar; diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js b/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js index f0b0f922ed1..12bb5664361 100644 --- a/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js +++ b/Examples/UIExplorer/NavigationExperimental/NavigationExperimentalExample.js @@ -33,12 +33,7 @@ const View = require('View'); * To learn how to use the Navigation API, take a look at the following example files: */ const EXAMPLES = { - 'Tabs': require('./NavigationTabsExample'), - 'Basic': require('./NavigationBasicExample'), - 'Animated Example': require('./NavigationAnimatedExample'), - 'Composition': require('./NavigationCompositionExample'), - 'Card Stack Example': require('./NavigationCardStackExample'), - 'Tic Tac Toe': require('./NavigationTicTacToeExample'), + 'NavigationCardStack Example': require('./NavigationCardStack-example'), }; const EXAMPLE_STORAGE_KEY = 'NavigationExperimentalExample'; diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationTabsExample.js b/Examples/UIExplorer/NavigationExperimental/NavigationTabsExample.js deleted file mode 100644 index f89e1ae5bc1..00000000000 --- a/Examples/UIExplorer/NavigationExperimental/NavigationTabsExample.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright (c) 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * 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'; - -const React = require('react'); -const ReactNative = require('react-native'); -const { - NavigationExperimental, - ScrollView, - StyleSheet, - View, -} = ReactNative; -const { - Reducer: NavigationReducer, -} = NavigationExperimental; - -const NavigationExampleRow = require('./NavigationExampleRow'); -const NavigationExampleTabBar = require('./NavigationExampleTabBar'); - -class ExmpleTabPage extends React.Component { - render() { - const currentTabRoute = this.props.tabs[this.props.index]; - return ( - - - {this.props.tabs.map((tab, index) => ( - { - this.props.onNavigate(NavigationReducer.TabsReducer.JumpToAction(index)); - }} - /> - ))} - - - ); - } -} - -const ExampleTabsReducer = NavigationReducer.TabsReducer({ - tabReducers: [ - (lastRoute) => lastRoute || {key: 'one'}, - (lastRoute) => lastRoute || {key: 'two'}, - (lastRoute) => lastRoute || {key: 'three'}, - ], -}); - -class NavigationTabsExample extends React.Component { - constructor() { - super(); - this.state = ExampleTabsReducer(undefined, {}); - } - render() { - return ( - - - - - ); - } - handleAction(action) { - if (!action) { - return false; - } - const newState = ExampleTabsReducer(this.state, action); - if (newState === this.state) { - return false; - } - this.setState(newState); - return true; - } - handleBackAction() { - return this.handleAction({ type: 'BackAction' }); - } -} - -const styles = StyleSheet.create({ - topView: { - flex: 1, - paddingTop: 30, - }, - tabPage: { - backgroundColor: '#E9E9EF', - }, -}); - -module.exports = NavigationTabsExample; diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationTicTacToeExample.js b/Examples/UIExplorer/NavigationExperimental/NavigationTicTacToeExample.js deleted file mode 100644 index 24ea3aee5ca..00000000000 --- a/Examples/UIExplorer/NavigationExperimental/NavigationTicTacToeExample.js +++ /dev/null @@ -1,326 +0,0 @@ -/** - * Copyright (c) 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * 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. - * - * @providesModule NavigationTicTacToeExample - * @flow - */ -'use strict'; - -const React = require('react'); -const StyleSheet = require('StyleSheet'); -const Text = require('Text'); -const TouchableHighlight = require('TouchableHighlight'); -const View = require('View'); - -type GameGrid = Array>; - -const evenOddPlayerMap = ['O', 'X']; -const rowLetterMap = ['a', 'b', 'c']; - -function parseGame(game: string): GameGrid { - const gameTurns = game ? game.split('-') : []; - const grid = Array(3); - for (let i = 0; i < 3; i++) { - const row = Array(3); - for (let j = 0; j < 3; j++) { - const turnIndex = gameTurns.indexOf(rowLetterMap[i] + j); - if (turnIndex === -1) { - row[j] = null; - } else { - row[j] = evenOddPlayerMap[turnIndex % 2]; - } - } - grid[i] = row; - } - return grid; -} - -function playTurn(game: string, row: number, col: number): string { - const turn = rowLetterMap[row] + col; - return game ? (game + '-' + turn) : turn; -} - -function getWinner(gameString: string): ?string { - const game = parseGame(gameString); - for (let i = 0; i < 3; i++) { - if (game[i][0] !== null && game[i][0] === game[i][1] && - game[i][0] === game[i][2]) { - return game[i][0]; - } - } - for (let i = 0; i < 3; i++) { - if (game[0][i] !== null && game[0][i] === game[1][i] && - game[0][i] === game[2][i]) { - return game[0][i]; - } - } - if (game[0][0] !== null && game[0][0] === game[1][1] && - game[0][0] === game[2][2]) { - return game[0][0]; - } - if (game[0][2] !== null && game[0][2] === game[1][1] && - game[0][2] === game[2][0]) { - return game[0][2]; - } - return null; -} - -function isGameOver(gameString: string): boolean { - if (getWinner(gameString)) { - return true; - } - const game = parseGame(gameString); - for (let i = 0; i < 3; i++) { - for (let j = 0; j < 3; j++) { - if (game[i][j] === null) { - return false; - } - } - } - return true; -} - -class Cell extends React.Component { - props: any; - cellStyle() { - switch (this.props.player) { - case 'X': - return styles.cellX; - case 'O': - return styles.cellO; - default: - return null; - } - } - textStyle() { - switch (this.props.player) { - case 'X': - return styles.cellTextX; - case 'O': - return styles.cellTextO; - default: - return {}; - } - } - render() { - return ( - - - - {this.props.player} - - - - ); - } -} - -function GameEndOverlay(props) { - if (!isGameOver(props.game)) { - return ; - } - const winner = getWinner(props.game); - return ( - - - {winner ? winner + ' wins!' : 'It\'s a tie!'} - - props.onNavigate(GameActions.Reset())} - underlayColor="transparent" - activeOpacity={0.5}> - - New Game - - - - ); -} - -function TicTacToeGame(props) { - const rows = parseGame(props.game).map((cells, row) => - - {cells.map((player, col) => - props.onNavigate(GameActions.Turn(row, col))} - /> - )} - - ); - return ( - - - Close - - EXTREME T3 - - {rows} - - - - ); -} - -const GameActions = { - Turn: (row, col) => ({type: 'TicTacToeTurnAction', row, col }), - Reset: (row, col) => ({type: 'TicTacToeResetAction' }), -}; - -function GameReducer(lastGame: ?string, action: Object): string { - if (!lastGame) { - lastGame = ''; - } - if (action.type === 'TicTacToeResetAction') { - return ''; - } - if (!isGameOver(lastGame) && action.type === 'TicTacToeTurnAction') { - return playTurn(lastGame, action.row, action.col); - } - return lastGame; -} - -type AppState = { - game: string, -}; - -class NavigationTicTacToeExample extends React.Component { - _handleAction: Function; - state: AppState; - constructor() { - super(); - this._handleAction = this._handleAction.bind(this); - this.state = { - game: '' - }; - } - _handleAction(action: Object) { - const newState = GameReducer(this.state.game, action); - if (newState !== this.state.game) { - this.setState({ - game: newState, - }); - } - } - render() { - return ( - - ); - } -} - -const styles = StyleSheet.create({ - closeButton: { - position: 'absolute', - left: 10, - top: 30, - fontSize: 14, - }, - container: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: 'white' - }, - title: { - fontFamily: 'Chalkduster', - fontSize: 39, - marginBottom: 20, - }, - board: { - padding: 5, - backgroundColor: '#47525d', - borderRadius: 10, - }, - row: { - flexDirection: 'row', - }, - cell: { - width: 80, - height: 80, - borderRadius: 5, - backgroundColor: '#7b8994', - margin: 5, - flex: 1, - justifyContent: 'center', - alignItems: 'center', - }, - cellX: { - backgroundColor: '#72d0eb', - }, - cellO: { - backgroundColor: '#7ebd26', - }, - cellText: { - fontSize: 50, - fontFamily: 'AvenirNext-Bold', - }, - cellTextX: { - color: '#19a9e5', - }, - cellTextO: { - color: '#b9dc2f', - }, - overlay: { - position: 'absolute', - top: 0, - bottom: 0, - left: 0, - right: 0, - backgroundColor: 'rgba(221, 221, 221, 0.5)', - flex: 1, - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - }, - overlayMessage: { - fontSize: 40, - marginBottom: 20, - marginLeft: 20, - marginRight: 20, - fontFamily: 'AvenirNext-DemiBold', - textAlign: 'center', - }, - newGame: { - backgroundColor: '#887766', - padding: 20, - borderRadius: 5, - }, - newGameText: { - color: 'white', - fontSize: 20, - fontFamily: 'AvenirNext-DemiBold', - }, -}); - -module.exports = NavigationTicTacToeExample; diff --git a/Libraries/NavigationExperimental/NavigationStateUtils.js b/Libraries/NavigationExperimental/NavigationStateUtils.js index 4ef94cbadf6..8ff97e8447f 100644 --- a/Libraries/NavigationExperimental/NavigationStateUtils.js +++ b/Libraries/NavigationExperimental/NavigationStateUtils.js @@ -65,6 +65,9 @@ function push(state: NavigationState, newChildState: NavigationRoute): Navigatio } function pop(state: NavigationState): NavigationState { + if (state.index <= 0) { + return state; + } const lastChildren = state.routes; return { ...state,