<p>The lightbulb is <span id="lightbulb">lit (1)</span></p>
<div>
<button hidden id="turn-on">turn on</button>
<button id="turn-off">turn off</button>
<button id="break">break</button>
<button hidden id="reset" onclick="history.go(0)">
Reset
</button>
</div>
body {
display: grid;
place-content: center;
height: 90vh;
background: gold;
color: black;
}
body[data-state='unlit'] {
background: #040a0f;
color: gray
}
body[data-state='broken'] {
background: gray;
}
#turn-on {
background: gold;
color: black;
}
#break {
background: gray;
}
View Compiled
import {
assign,
createMachine,
interpret
} from "https://cdn.skypack.dev/[email protected]";
const lightbulb = document.getElementById("lightbulb");
const turnBulbOn = document.getElementById("turn-on");
const turnBulbOff = document.getElementById("turn-off");
const breakBulb = document.getElementById("break");
const reset = document.getElementById("reset");
const machine = createMachine({
initial: "lit",
context: { switchCount: 0 },
states: {
lit: {
entry: "switched",
on: {
OFF: "unlit",
BREAK: { target: "broken", cond: "goodLightBulb" },
},
},
unlit: {
entry: "switched",
on: {
ON: "lit",
BREAK: { target: "broken", cond: "goodLightBulb" },
},
},
broken: {},
},
}).withConfig({
actions: {
switched: assign({ switchCount: (context) => context.switchCount + 1 }),
},
guards: {
goodLightBulb: (context) => context.switchCount <= 3,
},
})
const service = interpret(machine);
service.start();
service.subscribe((state) => {
lightbulb.innerText = `${state.value} (${state.context.switchCount})`;
document.body.dataset.state = state.value;
turnBulbOn.hidden = !state.can("ON");
turnBulbOff.hidden = !state.can("OFF");
breakBulb.hidden = !state.can("BREAK");
reset.hidden = !state.matches("broken");
});
turnBulbOn.addEventListener("click", () => {
service.send("ON");
});
turnBulbOff.addEventListener("click", () => {
service.send("OFF");
});
breakBulb.addEventListener("click", () => {
service.send("BREAK");
});
This Pen doesn't use any external JavaScript resources.