Skip to content

Instantly share code, notes, and snippets.

@medelman17
Created February 17, 2020 20:19
Show Gist options
  • Save medelman17/0fce69ca09f501c5c0dfa346b573d95f to your computer and use it in GitHub Desktop.
Save medelman17/0fce69ca09f501c5c0dfa346b573d95f to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
// Available variables:
// - Machine
// - interpret
// - assign
// - send
// - sendParent
// - spawn
// - raise
// - actions
// - XState (all XState exports)
const dummyClick = e => console.log("clicked", e);
function createButtonMachine(context, options) {
const { clickHandler = dummyClick } = options;
return Machine(
{
id: "button",
initial: "idle",
type: "parallel",
context: {
isActive: true,
isPressed: false,
isHovered: false,
isLoading: false,
isFocused: false,
isSuccess: false,
isFailure: false,
successCount: 0,
failureCount: 0,
...context
},
states: {
interaction: {
initial: "idle",
states: {
idle: {
on: {
MOUSE_ENTER: {
target: "hover",
cond: "isActive",
actions: assign({ isHovered: true })
}
}
},
pressed: {
on: {
MOUSE_UP: {
target: ["idle", "#button.activity.loading"],
actions: assign({ isPressed: false })
}
}
},
hover: {
on: {
MOUSE_LEAVE: {
target: "idle",
actions: assign({ isHovered: false })
},
MOUSE_DOWN: [
{
target: "pressed",
cond: "isBlurred",
actions: ["toggleHover", "togglePressed", "toggleFocus"]
},
{
target: "pressed",
actions: ["toggleHover", "togglePressed", "toggleFocus"]
}
]
}
}
}
},
functionality: {
initial: "active",
states: {
active: {
entry: assign({ isActive: true }),
on: {
DISABLE: {
target: [
"disabled",
"#button.activity.idle",
"#button.interaction.idle"
]
}
}
},
disabled: {
entry: assign({ isActive: false }),
on: {
ACTIVE: { target: "active" }
}
}
}
},
activity: {
initial: "idle",
states: {
idle: {
on: {
CLICK: {
target: "loading",
actions: ["toggleLoading"],
cond: "isActive"
}
}
},
loading: {
invoke: {
id: "clickService",
src: (context, event) => {
return new Promise((resolve, reject) => {
try {
const res = clickHandler({ context, event });
resolve(res);
} catch (error) {
reject(error);
}
});
},
onDone: {
target: "success"
},
onError: {
target: "failure"
}
},
on: {
ERROR: "failure",
SUCCESS: "success"
},
exit: "toggleLoading"
},
success: {
after: {
1000: "idle"
},
exit: "logSuccess"
},
failure: {
after: { 1000: "idle" },
exit: "logFailure"
}
}
},
focus: {
initial: "blurred",
states: {
blurred: {
on: {
FOCUS: { target: "focused", actions: ["toggleFocus"] }
}
},
focused: {
on: {
BLUR: { target: "blurred", actions: ["toggleFocus"] }
}
}
}
}
}
},
{
guards: {
isActive: (context, event) => context.isActive === true,
isLoading: (context, event) => context.isLoading === true,
isBlurred: (context, event) => context.isFocused === false,
...options.guards
},
actions: {
logSuccess: assign({
successCount: context => context.successCount + 1
}),
logFailure: assign({
failureCount: context => context.failureCount + 1
}),
toggleFocus: assign({
isFocused: (c, e) => !c.isFocused
}),
toggleHover: assign((context, event) => ({
isHovered: !context.isHovered
})),
togglePress: assign((context, event) => ({
isPressed: !context.isPressed
})),
handleClick: (context, event) => {},
...options.actions
}
}
);
}
const buttonMachine = createButtonMachine({}, {})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment