├── .prettierignore ├── .storybook ├── addons.js └── config.js ├── .eslintignore ├── .gitignore ├── .flowconfig ├── .prettierrc.json ├── setupJest.js ├── .editorconfig ├── flow-typed ├── StateManager.js └── WizardTypes.js ├── pages ├── components │ ├── Emoji.js │ ├── InputComponent.js │ ├── StepWithInput.js │ ├── Button.js │ ├── Controls.js │ └── WizardExample.js ├── advancedExample.md └── basicExample.mdx ├── .babelrc ├── src ├── index.js ├── state-managers │ ├── url-state-manager.test.js │ └── url-state-manager.js ├── utils.js ├── Controls.js ├── Step.js ├── Wizard.test.js ├── utils.test.js └── Wizard.js ├── .eslintrc ├── .github └── build-docs.workflow ├── doczrc.js ├── index.html ├── LICENSE ├── package.json └── README.md /.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-actions/register'; 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | /pkg/ 3 | /docs/ 4 | /node_modules/ 5 | setupJest.js 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .eslintcache 3 | .docz 4 | pages/_index.mdx 5 | docs/ 6 | pkg/ 7 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | /dist/.* 3 | 4 | [include] 5 | 6 | [libs] 7 | 8 | [options] 9 | experimental.const_params=true 10 | 11 | [lints] -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "singleQuote": true, 4 | "trailingComma": "all", 5 | "bracketSpacing": true, 6 | "jsxBracketSameLine": true, 7 | "parser": "flow" 8 | } 9 | -------------------------------------------------------------------------------- /setupJest.js: -------------------------------------------------------------------------------- 1 | // Setup Enzyme's React adapter 2 | const Enzyme = require('enzyme'); 3 | const EnzymeAdapter = require('enzyme-adapter-react-16'); 4 | Enzyme.configure({ adapter: new EnzymeAdapter() }); 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 2 10 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from '@storybook/react'; 2 | 3 | const req = require.context('../stories/', true, /\.story\.js$/); 4 | 5 | function loadStories() { 6 | req.keys().forEach(filename => req(filename)); 7 | } 8 | configure(loadStories, module); 9 | -------------------------------------------------------------------------------- /flow-typed/StateManager.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Losen$StateManager = {| 4 | updateStep: (currentStepName: string, nextStepName: string) => void, 5 | getActiveStep: () => string, 6 | getItem: (key: string) => string, 7 | setItem: (key: string, value: string) => void, 8 | |}; 9 | -------------------------------------------------------------------------------- /pages/components/Emoji.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | 4 | type Props = { 5 | emoji: string, 6 | }; 7 | 8 | const Emoji = ({ emoji, ...rest }: Props) => ( 9 | 10 | {emoji} 11 | 12 | ); 13 | 14 | export default Emoji; 15 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-react", 4 | "@babel/preset-flow" 5 | ], 6 | "env": { 7 | "test": { 8 | "presets": [ 9 | ["@babel/preset-env", { "targets": { "node": "current" }}] 10 | ] 11 | } 12 | }, 13 | "plugins": [ 14 | "@babel/plugin-proposal-class-properties" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /flow-typed/WizardTypes.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | type Losen$StepTypes = 'next' | 'previous' | 'complete'; 4 | declare type Losen$Direction = ?Losen$StepTypes; 5 | 6 | declare type Losen$ValidatorFunction = () => Promise; 7 | 8 | declare type Losen$Step = {| 9 | name: string, 10 | validator: ?Losen$ValidatorFunction, 11 | autoSkip: ?boolean, 12 | state: ?Array<{| [string]: string |}>, 13 | |}; 14 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import Controls, { ControlsContext } from './Controls'; 3 | import Step, { StepContext } from './Step'; 4 | import Wizard, { ValidationError } from './Wizard'; 5 | import { UrlStateManager } from './state-managers/url-state-manager'; 6 | 7 | export { 8 | Controls, 9 | ControlsContext, 10 | Step, 11 | StepContext, 12 | ValidationError, 13 | Wizard, 14 | UrlStateManager, 15 | }; 16 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "jest": true 6 | }, 7 | "plugins": ["react-hooks", "flowtype"], 8 | "parser": "babel-eslint", 9 | "extends": "otovo/react-recommended", 10 | "rules": { 11 | "react/default-props-match-prop-types": 0, 12 | "react-hooks/rules-of-hooks": "error", 13 | "react-hooks/exhaustive-deps": "warn", 14 | "flowtype/define-flow-type": 2 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pages/components/InputComponent.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { useState } from 'react'; 3 | 4 | type Props = { 5 | name: string, 6 | }; 7 | 8 | const InputComponent = ({ name }: Props) => { 9 | const [text, setText] = useState(''); 10 | return ( 11 |