├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── LICENSE.md ├── README.md ├── example ├── .babelrc ├── .buckconfig ├── .eslintrc ├── .watchmanconfig ├── App.js ├── README.md ├── app.json ├── package.json ├── rn-cli.config.js ├── src │ └── Fade.js └── yarn.lock ├── jest-setup.js ├── package.json ├── src ├── index.js ├── navigators │ ├── __tests__ │ │ └── switchRouter-test.js │ ├── createContainedSwitchNavigator.js │ ├── createSwitchNavigator.js │ └── switchRouter.js ├── utils │ └── withTransition.js └── views │ ├── FadeTransition.js │ └── Transitioner.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react-native"] 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # we recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | jest-setup.js 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": ["airbnb", "prettier"], 4 | "env": { 5 | "jest": true 6 | }, 7 | "globals": { 8 | "__DEV__": false 9 | }, 10 | "rules": { 11 | "react/jsx-filename-extension": [1, { "extensions": [".js"] }], 12 | "react/no-unescaped-entities": ["error", { "forbid": [">", "}"] }], 13 | "react/destructuring-assignment": [ 14 | "on", 15 | "always", 16 | { "ignoreClassFields": true } 17 | ], 18 | "react/prop-types": [0], 19 | "no-underscore-dangle": "off", 20 | "no-console": "off" 21 | }, 22 | "settings": { 23 | "import/resolver": { 24 | "node": { 25 | "extensions": [".js", ".ios.js", ".android.js"] 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # XDE 6 | .expo/ 7 | 8 | # VSCode 9 | .vscode/ 10 | tsconfig.json 11 | jsconfig.json 12 | 13 | # Xcode 14 | # 15 | build/ 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | xcuserdata 25 | *.xccheckout 26 | *.moved-aside 27 | DerivedData 28 | *.hmap 29 | *.ipa 30 | *.xcuserstate 31 | project.xcworkspace 32 | 33 | # Android/IJ 34 | # 35 | .idea 36 | .gradle 37 | local.properties 38 | 39 | # node.js 40 | # 41 | node_modules/ 42 | npm-debug.log 43 | yarn-debug.log 44 | yarn-error.log 45 | 46 | # BUCK 47 | buck-out/ 48 | \.buckd/ 49 | android/app/libs 50 | android/keystores/debug.keystore 51 | 52 | # Build 53 | dist/ 54 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 React Native Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Navigation Switch Transitioner 2 | 3 | Switch navigator for use on iOS and Android, allowing custom transitions on switching. 4 | 5 | It also includes a FadeTransition to use in your screens to get cross-fading for the switch navigator 6 | 7 | ## Installation 8 | 9 | Open a Terminal in your project's folder and run, 10 | 11 | ```sh 12 | yarn add react-navigation-switch-transitioner 13 | ``` 14 | 15 | ## Usage 16 | 17 | Create your Switch Navigator with the same parameters than the react-navigation one. 18 | 19 | There are 2 options to add transitions to your Screens: 20 | 21 | ### Option 1: Using the provided HOC 22 | 23 | This library provides two HOCs: `withTransition` and `withFadeTransition` which you can use to wrap your screens. The first one allows you to inject any transition to your screen, while the second one uses the provided FadeTransition. 24 | 25 | ```js 26 | import { createSwitchNavigator, FadeTransition, withTransition, withFadeTransition } from 'react-navigation-switch-transitioner' 27 | 28 | export default createSwitchNavigator({ 29 | Inbox: withTransition(FadeTransition)(InboxScreen) 30 | Drafts: withFadeTransition(DraftsScreen), 31 | }, { 32 | initialRouteName: 'Inbox', 33 | }) 34 | ``` 35 | 36 | ### Option 2: Wrap your screens with a transition component 37 | 38 | If you want your screens to Fade on transitioning to/from them, wrap them in the FadeTransition component and expose its navigationOptions (don't forget to pass the received props to the FadeTransition) 39 | 40 | ```js 41 | import { FadeTransition } from 'react-navigation-switch-transitioner' 42 | 43 | class DraftScreen extends React.Component { 44 | static navigationOptions = FadeTransition.navigationOptions 45 | 46 | render() { 47 | return ( 48 | 49 | 56 | Drafts 57 | 58 | 59 | ) 60 | } 61 | } 62 | ``` 63 | 64 | ## Docs 65 | 66 | It is mostly compatible with the react-navigation `SwitchNavigator` so the best place to start while documention is created is the [React Navigation website](https://reactnavigation.org/docs/en/switch-navigator.html). 67 | 68 | ## Implementing your own Transitions 69 | 70 | If you want to implement your own transition take a look at the source code for the FadeTransition. 71 | 72 | ## Run the example app 73 | 74 | To run the example app do the following: 75 | 76 | ```sh 77 | git clone https://github.com/elyalvarado/react-navigation-switch-transitioner 78 | cd react-navigation-switch-transitioner 79 | yarn install 80 | cd examples 81 | yarn install 82 | yarn start 83 | ``` 84 | -------------------------------------------------------------------------------- /example/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "expo" 4 | ], 5 | "plugins": [ 6 | ["module-resolver", { 7 | "alias": { 8 | "react-navigation-switch-transitioner": "../src" 9 | } 10 | }] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /example/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /example/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc", 3 | 4 | "settings": { 5 | "import/core-modules": [ "expo", "react-navigation-stack" ] 6 | }, 7 | 8 | "rules": { 9 | "react/prop-types": "off" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Expo from 'expo' 3 | import { StyleSheet, View } from 'react-native' 4 | import Fade from './src/Fade' 5 | 6 | // Comment the following two lines to stop using react-native-screens 7 | import { useScreens } from 'react-native-screens' // eslint-disable-line 8 | useScreens() 9 | 10 | const styles = StyleSheet.create({ 11 | container: { 12 | flex: 1, 13 | backgroundColor: '#fff', 14 | alignItems: 'center', 15 | justifyContent: 'center', 16 | }, 17 | }) 18 | 19 | // eslint-disable-next-line react/prefer-stateless-function 20 | class App extends React.Component { 21 | render() { 22 | return ( 23 | 24 | 25 | 26 | ) 27 | } 28 | } 29 | 30 | Expo.registerRootComponent(App) 31 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | ## Run the example 2 | 3 | - Run the example locally 4 | - Clone the repository and `cd` to this directory 5 | - Run `yarn` to install the dependencies 6 | - Run `yarn start` to start the packager 7 | - Scan the QR Code with the Expo app 8 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "React Navigation Switch Transitioner Example", 4 | "description": "Demonstrates the various capabilities of react-navigation-switch-transitioner", 5 | "slug": "react-navigation-switch-transitioner-demo", 6 | "sdkVersion": "30.0.0", 7 | "version": "1.0.0", 8 | "primaryColor": "#2196f3", 9 | "packagerOpts": { 10 | "assetExts": [ 11 | "ttf" 12 | ], 13 | "config": "./rn-cli.config.js", 14 | "projectRoots": "" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stackexample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo start --android", 8 | "ios": "expo start --ios", 9 | "postinstall": "rm -rf node_modules/expo-react-native-adapter/node_modules/react && rm -rf node_modules/expo-gl/node_modules/react" 10 | }, 11 | "dependencies": { 12 | "expo": "~30.0.0", 13 | "hoist-non-react-statics": "^2.5.0", 14 | "prop-types": "^15.6.0", 15 | "react": "16.3.1", 16 | "react-native": "~0.55.4", 17 | "react-native-screens": "^1.0.0-alpha.12", 18 | "react-navigation": "^2.11.1" 19 | }, 20 | "devDependencies": { 21 | "babel-plugin-module-resolver": "^3.0.0", 22 | "babel-preset-expo": "^4.0.0", 23 | "glob-to-regexp": "^0.3.0" 24 | }, 25 | "main": "App.js", 26 | "resolutions": { 27 | "**/react": "16.3.1", 28 | "**/prop-types": "15.6.0", 29 | "**/react-lifecycles-compat": "3.0.4", 30 | "**/hoist-non-react-statics": "2.5.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example/rn-cli.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-commonjs, import/no-extraneous-dependencies */ 2 | 3 | const path = require('path'); 4 | const glob = require('glob-to-regexp'); 5 | const blacklist = require('metro/src/blacklist'); 6 | const pak = require('../package.json'); 7 | 8 | const dependencies = Object.keys(pak.dependencies); 9 | const peerDependencies = Object.keys(pak.peerDependencies); 10 | 11 | module.exports = { 12 | getProjectRoots() { 13 | return [__dirname, path.resolve(__dirname, '..')]; 14 | }, 15 | getProvidesModuleNodeModules() { 16 | return [...dependencies, ...peerDependencies]; 17 | }, 18 | getBlacklistRE() { 19 | return blacklist([glob(`${path.resolve(__dirname, '..')}/node_modules/*`)]); 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /example/src/Fade.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/no-multi-comp, import/no-unresolved, react/prefer-stateless-function */ 2 | import React from 'react' 3 | import { 4 | Button, 5 | Text as UnstyledText, 6 | View as UnstyledView, 7 | } from 'react-native' 8 | import { 9 | FadeTransition, 10 | createContainedSwitchNavigator, 11 | withFadeTransition, 12 | } from 'react-navigation-switch-transitioner' 13 | import { createStackNavigator } from 'react-navigation' 14 | 15 | const View = props => { 16 | const { style, ...propsNoStyle } = props 17 | return ( 18 | 27 | ) 28 | } 29 | const Text = props => ( 30 | 31 | ) 32 | 33 | // Screen without transition 34 | class HomeScreen extends React.Component { 35 | render() { 36 | const { navigation } = this.props 37 | return ( 38 | 39 | Home Screen 40 |