@lytics/wiz
v3.0.0
Published
A specification for modeling wizard workflows, like the ones used in Lytics products, and a library for consuming these models.
Downloads
19
Readme
@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");