Skip to content

Instantly share code, notes, and snippets.

@evanrs
Created May 7, 2020 19:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save evanrs/feb637cdb6e79cd0eb013aa7c5707cc9 to your computer and use it in GitHub Desktop.
Save evanrs/feb637cdb6e79cd0eb013aa7c5707cc9 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
const todoMachine = Machine({
id: "todo",
initial: "reading",
context: {
id: undefined,
title: "",
prevTitle: "",
},
on: {
TOGGLE_COMPLETE: {
target: ".reading.completed",
actions: [
assign({ completed: true }),
sendParent((ctx) => (console.log("commit"), { type: "TODO.COMMIT", todo: ctx })),
],
},
DELETE: "deleted",
},
states: {
reading: {
initial: "unknown",
states: {
unknown: {
on: {
"": [{ target: "completed", cond: (ctx) => ctx.completed }, { target: "pending" }],
},
},
pending: {
on: {
SET_COMPLETED: {
target: "completed",
actions: [
assign({ completed: true }),
sendParent((ctx) => ({ type: "TODO.COMMIT", todo: ctx })),
],
},
},
},
completed: {
on: {
TOGGLE_COMPLETE: {
target: "pending",
actions: [
assign({ completed: false }),
sendParent((ctx) => ({ type: "TODO.COMMIT", todo: ctx })),
],
},
SET_ACTIVE: {
target: "pending",
actions: [
assign({ completed: false }),
sendParent((ctx) => ({ type: "TODO.COMMIT", todo: ctx })),
],
},
},
},
hist: {
type: "history",
},
},
on: {
EDIT: {
target: "editing",
actions: "focusInput",
},
},
},
editing: {
onEntry: assign({ prevTitle: (ctx) => ctx.title }),
on: {
CHANGE: {
actions: assign({
title: (ctx, e) => e.value,
}),
},
COMMIT: [
{
target: "reading.hist",
actions: sendParent((ctx) => ({ type: "TODO.COMMIT", todo: ctx })),
cond: (ctx) => ctx.title && ctx.title.trim().length > 0,
},
{ target: "deleted" },
],
BLUR: {
target: "reading",
actions: sendParent((ctx) => ({ type: "TODO.COMMIT", todo: ctx })),
},
CANCEL: {
target: "reading",
actions: assign({ title: (ctx) => ctx.prevTitle }),
},
},
},
deleted: {
onEntry: sendParent((ctx) => ({ type: "TODO.DELETE", id: ctx.id })),
},
},
});
const uuid = () => `${Math.random()}`.replace(/\d+\./, "");
const createTodo = (title) => {
return {
id: uuid(),
title: title,
completed: false,
};
};
const todosMachine = Machine({
id: "todos",
context: {
todo: "", // new todo
todos: [],
},
initial: "initializing",
states: {
initializing: {
entry: assign({
todos: (ctx, e) => {
return ctx.todos.map((todo) => ({
...todo,
ref: spawn(todoMachine.withContext(todo)),
}));
},
}),
on: {
"": "all",
},
},
all: {},
active: {},
completed: {},
},
on: {
"NEWTODO.CHANGE": {
actions: assign({
todo: (ctx, e) => e.value,
}),
},
"NEWTODO.COMMIT": {
actions: [
assign({
todo: "", // clear todo
todos: (ctx, e) => {
if (e.value == null) {
return;
}
const newTodo = createTodo(e.value.trim());
return ctx.todos.concat({
...newTodo,
ref: spawn(todoMachine.withContext(newTodo)),
});
},
}),
"persist",
],
cond: (ctx, e) => e.value && e.value.trim().length,
},
"TODO.COMMIT": {
actions: [
assign({
todos: (ctx, e) =>
ctx.todos.map((todo) => {
return todo.id === e.todo.id ? { ...todo, ...e.todo, ref: todo.ref } : todo;
}),
}),
"persist",
],
},
"TODO.DELETE": {
actions: [
assign({
todos: (ctx, e) => ctx.todos.filter((todo) => todo.id !== e.id),
}),
"persist",
],
},
"SHOW.all": ".all",
"SHOW.active": ".active",
"SHOW.completed": ".completed",
"MARK.completed": {
actions: (ctx) => {
ctx.todos.forEach((todo) => todo.ref.send("SET_COMPLETED"));
},
},
"MARK.active": {
actions: (ctx) => {
ctx.todos.forEach((todo) => todo.ref.send("SET_ACTIVE"));
},
},
CLEAR_COMPLETED: {
actions: assign({
todos: (ctx) => ctx.todos.filter((todo) => !todo.completed),
}),
},
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment