<main id="app"></main>
* {
margin: 0;
padding: 0;
}
html,
body {
background: #330033;
color: #fff;
font-family: sans-serif;
width: 100%;
height: 100%;
position: relative;
}
h1 {
font-size: 48px;
font-weight: normal;
line-height: 90px;
}
main {
padding: 40px;
background-color: #555;
width: 360px;
margin: 30px auto auto auto;
text-align: center;
border-radius: 30px;
}
button {
display: block;
border: 2px orangered solid;
background: orange;
font-size: 36px;
color: #fff;
border-radius: 10px;
padding: 10px 20px;
min-width: 70px;
cursor: pointer;
margin: 20px auto auto auto;
}
.counter {
background: #111;
width: 160px;
margin-right: auto;
margin-left: auto;
}
.counter h1 {
margin-bottom: 0px;
}
.counter button {
display: inline-block;
border-color: cornflowerblue;
background: aquamarine;
color: cornflowerblue;
padding: 5px;
min-width: 55px;
margin: 10px;
}
main > p {
margin: 40px auto 40px auto;
line-height: 48px;
font-size: 36px;
font-weight: bold;
color: hotpink;
}
import { app } from "https://cdn.skypack.dev/hyperapp";
import html from "https://cdn.skypack.dev/hyperlit";
const Counter = ({ get, set, onChange }) => {
const Init = (state) => set(state, 0);
const Incr = (state) => [
set(state, get(state) + 1),
(dispatch) => dispatch(onChange, get(state) + 1)
];
const Decr = (state) => [
set(state, get(state) - 1),
(dispatch) => dispatch(onChange, get(state) - 1)
];
const view = (state) => html`
<div class="counter">
<h1>${get(state)}</h1>
<button onclick=${Decr}>-</button>
<button onclick=${Incr}>+</button>
</div>
`;
return { Init, view };
};
const Game = ({ get, set, onFinish }) => {
const OnCounterChange = (state, value) => [
state,
(dispatch) => dispatch(ScorePoint),
value === 10 && ((dispatch) => dispatch(onFinish))
];
const counter = Counter({
get: (state) => get(state).counter,
set: (state, counter) => set(state, { ...get(state), counter }),
onChange: OnCounterChange
});
const ScorePoint = (state) => {
const game = { ...get(state) };
game.score = game.score + 1;
return set(state, game);
};
const Init = (state) => [
set(state, { score: 0 }),
(dispatch) => dispatch(counter.Init)
];
const view = counter.view;
const score = (state) => get(state).score;
return { Init, view, score };
};
const Flow = ({ get, set, score, game, onPlay }) => {
const Init = (state) => set(state, "start");
const Play = (state) => [set(state, "play"), (dispatch) => dispatch(onPlay)];
const Finish = (state) => set(state, "finish");
const view = (state) => {
let mode = get(state);
return mode === "start"
? html`
<main>
<h1>Play a game?</h1>
<button onclick=${Play}>Sure!</button>
</main>
`
: mode === "finish"
? html`
<main>
<h1>Game Over</h1>
<p>Score: ${score(state)}</p>
<button onclick=${Init}>Start over</button>
</main>
`
: html`
<main>
${game(state)}
<p>Score: ${score(state)}</p>
<button onclick=${Init}>Cancel</button>
</main>
`;
};
return { Init, view, Finish };
};
const game = Game({
get: (state) => state.game,
set: (state, game) => ({ ...state, game }),
onFinish: () => flow.Finish
});
const flow = Flow({
get: (state) => state.flow,
set: (state, flow) => ({ ...state, flow }),
game: game.view,
score: game.score,
onPlay: game.Init
});
app({
init: flow.Init,
view: (state) => flow.view(state),
node: document.getElementById("app")
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.