├── .babelrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── __tests__ ├── Stager-test.tsx └── __snapshots__ │ └── Stager-test.js.snap ├── example ├── .babelrc ├── .buckconfig ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .watchmanconfig ├── android │ ├── app │ │ ├── BUCK │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── keystores │ │ ├── BUCK │ │ └── debug.keystore.properties │ └── settings.gradle ├── app.json ├── example.js ├── index.android.js ├── index.ios.js ├── ios │ ├── example-tvOS │ │ └── Info.plist │ ├── example-tvOSTests │ │ └── Info.plist │ ├── example.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── example-tvOS.xcscheme │ │ │ └── example.xcscheme │ ├── example │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── exampleTests │ │ ├── Info.plist │ │ └── exampleTests.m └── package.json ├── jsconfig.json ├── package.json ├── src └── index.tsx ├── tsconfig-base.json └── tsconfig.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react-native"] 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | coverage 3 | __tests__/*.js* -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | *.ts 3 | !*.d.ts 4 | tsconfig.json 5 | tsconfig-base.json 6 | src 7 | README.md 8 | .travis.yml 9 | example 10 | coverage -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | before_install: 3 | - npm i npm@4 -g --progress=false 4 | - npm i -g npm-install-peers coveralls --progress=false 5 | before_script: 6 | - npm-install-peers 7 | - npm i react --progress=false || true 8 | - rm -rf node_modules/@types/node 9 | after_success: 10 | - cat ./coverage/lcov.info | coveralls 11 | node_js: 12 | - "9" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Paulo Cesar 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 | [![Build Status](https://travis-ci.org/pocesar/react-native-stager.svg?branch=master)](https://travis-ci.org/pocesar/react-native-stager) [![Coverage Status](https://coveralls.io/repos/github/pocesar/react-native-stager/badge.svg?branch=master)](https://coveralls.io/github/pocesar/react-native-stager?branch=master) [![npm version](https://badge.fury.io/js/react-native-stager.svg)](https://badge.fury.io/js/react-native-stager) 2 | 3 | # react-native-stager 4 | 5 | A performant wizard-like multi stages component for React Native without a router 6 | 7 | ## Why? 8 | 9 | Using a router solution to create a multi-step wizard-like interface is good, but sometimes you want 10 | to keep all your state in just one parent component without having to rely on `redux` for example, 11 | enter the `Stager` 12 | 13 | ## How? 14 | 15 | ```jsx 16 | import React from 'react' 17 | import { View, TouchableOpacity, Text } from 'react-native' 18 | import Stager, { Stage } from 'react-native-stager' 19 | 20 | class MyWizard extends React.Component { 21 | render() { 22 | return ( 23 | { 24 | // stage == step 1 || step 2 25 | // direction = 1 = next | -1 = prev | 0 = reset / initial 26 | }}> 27 | true}> 28 | {({ instance, context }) => ( 29 | 30 | 31 | {'Hello'} 32 | 33 | 34 | )} 35 | 36 | 37 | this.setState({ loaded: true }, cb)}> 38 | {() => ( 39 | {'World'} 40 | )} 41 | 42 | 43 | ) 44 | } 45 | } 46 | 47 | export default MyWizard 48 | ``` 49 | 50 | ## Components and API 51 | 52 | `Stager` 53 | 54 | The root component that will hold the steps. Accepts an `onChange` prop that receives the transitioning stage name and the direction (-1 = prev / 1 = next / 0 = reset/initial). 55 | Can be safely nested. 56 | 57 | ```tsx 58 | { 59 | // do something nice 60 | }}> 61 | 62 | ``` 63 | 64 | `Stage` 65 | 66 | Need to set inside `Stager`. Can use `continue`, `noPrevious` and `loaded` props. 67 | Notice that the children must always be a function. The `key` prop is required. 68 | 69 | It receives an object with `instance` (this current `Stage`) and 70 | `context` (the current `Stager`) 71 | 72 | ```tsx 73 | 74 | 75 | {({ instance, context }) => ( 76 | {'This is step 1'} 77 | )} 78 | 79 | 80 | ``` 81 | 82 | When using `continue`, you always need to signal to the `Stage` that it should re-evaluate the 83 | `continue` function, to see if you're able to continue. This is so the component doesn't 84 | re-render everytime everytime a children changes. 85 | 86 | ```tsx 87 | 88 | this.state.canContinue} 91 | > 92 | {({ instance, context }) => ( 93 | 94 | {'This is step 1'} 95 |