Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/liamfiddler/friendly-wizard

A class for managing steps in a wizard, and their responses.
https://github.com/liamfiddler/friendly-wizard

Last synced: 12 days ago
JSON representation

A class for managing steps in a wizard, and their responses.

Awesome Lists containing this project

README

        

# 🧙‍♂️ Friendly Wizard

A class for managing steps in a wizard, and their responses.

## Quick start

Install this package:

```sh
npm install --save liamfiddler/friendly-wizard
```

Then import the Wizard class and start using it:

```js
import Wizard from 'friendly-wizard/Wizard.js';

const wizard = new Wizard({
steps: [
{
id: 'step-1',
type: 'text',
data: {
title: 'Step 1',
body: 'Welcome to the first step',
},
},
{
id: 'step-2',
type: 'text',
data: {
title: 'Step 2',
body: 'This is the second step',
},
},
],
});

// output the first step title
console.log(wizard.activeStep.data.title);

// navigate to the next step
wizard.next();

// output the second step title
console.log(wizard.activeStep.data.title);
```

## Configuration

The Wizard class constructor takes an object for configuration:

| Param | Type | Description |
| --- | --- | --- |
| steps | `Step[]` | An array of [_Step objects_](#step-objects), representing the screens in the wizard flow |
| startAtId | `string` | The ID of the step which should initially be active (defaults to the first step if not supplied) |
| responses | `Map.<string, any>` \| `Record.<string, any>` | The initial set of answers/responses to the wizard (defaults to an empty object if not supplied) |


## Defining steps

The `steps` value passed the Wizard class constructor is an array of _Step objects_.

_Step objects_ are a generic javascript object with whatever keys you like, however the following keys have special functionality attached to them:

### id

A unique identifier for the step. If it is not supplied a random string will be generated as the ID (note: this is randomly generated every time a new Wizard is created, it will be different every time and does not persist across multiple instantiations).

### skip

*skip* contains the logic for skipping the step. This could be a boolean, a function that returns a boolean, or a mongo-style object that compares against the wizard responses.

If you pass an object as the value for *skip* you can use mongo-style syntax to compare responses and response values. Under the hood it uses [sift.js](https://github.com/crcn/sift.js) and supports a variety of operators. Refer to the list of [supported operators in the sift.js documentation](https://github.com/crcn/sift.js#supported-operators).

```js
const wizard = new Wizard({
steps: [
{
id: 'step1',
},
{
id: 'step2',
// skip the step if 'something' === 'test'
skip: {
something: {
$eq: 'test',
},
},
},
{
id: 'step3',
},
],
});

// outputs 'step2', because the second step is not skipped
console.log(wizard.nextStep.id);

// set the response for 'something' to 'test'
wizard.responses.set('something', 'test');

// outputs 'step3' because the second step is now skipped
console.log(wizard.nextStep.id);
```

## Events

The Wizard class is an [EventTarget](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget). Event listeners can be added to the class, and will trigger functionality when certain circumstances occur in usage.

| Event | Description |
| --- | --- |
| *step:change* | Triggered when the wizard moves to a different step |
| *step:next* | Triggered when the wizard moves forward a step |
| *step:previous* | Triggered when the wizard moves back a step |
| *responses:change* | Triggered when a response value is created, updated, or deleted |

The event listeners are particularly useful in Single Page Apps, they allow libraries and frameworks to listen for changes and render updates as they occur.

```js
const wizard = new Wizard({
steps: [{}, {}, {}, {}],
});

wizard.addEventListener('step:change', () => {
console.log('hello world');
});

// Change to the next step, triggering the event listener and outputting 'hello world'
wizard.next();
```

## Usage in React

Example usage is demonstrated in the [React example project](./react) in this repo.

A custom hook called [useFriendlyWizard](./react/useFriendlyWizard.jsx) wraps the Wizard class for usage in React. It manages event listeners and updates the wizard step to component state when the step changes.

## Usage in Vue

Example usage is demonstrated in the [Vue example project](./vue) in this repo.

The Wizard class is instantiated as a [global property](https://vuejs.org/api/application.html#app-config-globalproperties) making it available inside any component template in the application, and also on `this` of any component instance.

Components accessing it can implement event listeners to render when the step changes. See [App.vue](./vue/App.vue) for an example.

## Reading/writing responses to localStorage or sessionStorage

A version of the Wizard class that is extended to automatically read/write the responses to/from browser storage is included in this repo.

To use it import from the `WizardStorage.js` file instead of `Wizard.js`:

```diff
- import Wizard from 'friendly-wizard/Wizard.js';
+ import Wizard from 'friendly-wizard/WizardStorage.js';
```

Additionally, two new options will be available when instantiating the class:

| Name | Type | Description |
| --- | --- | --- |
| [persist] | `boolean` | Whether the responses should persist when the window/tab is closed (`localStorage`), or not (`sessionStorage`). Defaults to `true` |
| [storageKey] | `string` | The key under which the responses should be stored. Defaults to `"wizard"` |

# API Documentation

{{>main}}