3.0.0 • Published 2 years ago

@lytics/wiz v3.0.0

Weekly downloads
33
License
MIT
Repository
-
Last release
2 years ago

@lytics/wiz

A specification for modeling wizard workflows, like the ones used in Lytics products, and a library for consuming these models.

installation

npm install @lytics/wiz

playground

examples

Importing the enter function from the library:

import { enter } from "@lytics/wiz";

Define and navigate immutable wizards:

// Simple case of a wizard with no branches
const entry = enter([{ id: "1" }, { id: "2" }, { id: "3" }]);

const secondStep = entry.next();

const thirdStep = entry.next().next();

assert(secondStep.next() === thirdStep);

assert(thirdStep.prev() === secondStep);

assert(thirdStep.prev().prev() === entry);

Wizards can have alternate steps:

const entry = enter([{ id: "1", alt: "1.5" }, { id: "1.5"}, { id: "2" }]);

const secondStep = entry.next();

const alternateStep = entry.alt();

// Subsequent steps have distinct identities...
assert(secondStep.next() !== alternateStep.next());

// ...because you need to be able to navigate back to the correct previous step...
assert(secondStep.next().prev() === secondStep);
assert(alternateStep.next().prev() === alternateStep);

// ...but they both point the same underlying spec...
assert(secondStep.next().spec === alternateStep.next().spec);

// ...going backwards we can arrive at the same entry node...
assert(secondStep.prev() === alternateStep.prev());

Wizards can have choicepoints:

const entry = enter({
  entrypoint: "choice",
  choices: [
    {
      id: "choice",
      options: ["wimp", "shrimp"]
    }
  ],
  steps: [
    { id: "wimp" },
    { id: "shrimp" }
  ],
});

entry.next(); // Throws! a selection is required.
entry.next("opus"); // Throws! valid options are wimp, shrimp

const wimpCard = entry.next("wimp");
const shrimpCard = entry.next("shrimp");

// ...you can navigate to the previous card
assert(wimpCard.prev() === shrimpCard.prev());

// ...there is no "memory"
wimpCard.prev().next(); // Throws! a selection is required.

// ...for "memory", retain a reference in your program...
assert(wimpCard === entry.next("wimp"));

Wizards can specify flows, which are sequences of steps:

const { enter } = LyticsWiz;

const simpleFlow = enter({
  entrypoint: "flow",
  flows: [
    {
      id: "flow",
      steps: ["one", "two", "three"],
    },
  ],
  steps: [{ id: "one" }, { id: "two" }, { id: "three" }],
});

These features compose orthogonally to one another. Here is kitchen sink example using flows, choices, and alts:

const { enter } = LyticsWiz;

const checkoutFlow = enter({
  entrypoint: "gratuity",
  choices: [
    {
      id: "gratuity",
      options: [
        { when: "10-percent", goto: "payment-method" },
        { when: "20-percent", goto: "payment-method" },
        { when: "30-percent", goto: "heavy-tipper" },
      ],
    },
  ],
  flows: [
    {
      id: "heavy-tipper",
      steps: ["thanks-dude", "payment-method"],
    },
  ],
  steps: [
    { id: "payment-method" },
    { id: "thanks-dude", alt: "secret-promo" },
    { id: "secret-promo" },
  ],
});

// normal tip amounts route to the payment-method step
assert(step.next("10-percent").spec.id === "payment-method");
assert(step.next("20-percent").spec.id === "payment-method");

// 30-percent routes to the heavy-tipper flow
assert(step.next("30-percent").spec.id === "thanks-dude");

// "next" continuation routes back to the payment-method step
assert(step.next("30-percent").next().spec.id === "payment-method");

// "alt" continution routes to the secret-promo step before the payment-method step
assert(step.next("30-percent").alt().spec.id === "secret-promo");
assert(step.next("30-percent").alt().next().spec.id === "payment-method");

docs

specification

3.0.0

2 years ago

2.0.0

2 years ago

1.1.0

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago