import {app} from 'https://unpkg.com/hyperapp'
import html from 'https://unpkg.com/hyperlit'
const counter = (() => {
const init = x => x
const increment = (x, max) => Math.min(max, x + 1)
const decrement = (x, min) => Math.max(min, x - 1)
const wire = ({
getter,
setter,
onIncrement,
onDecrement,
min=-Infinity,
max=Infinity,
}) => {
const _increment = state => setter(
state,
increment(getter(state), max)
)
const _decrement = state => setter(
state,
decrement(getter(state), min)
)
const _value = state => getter(state)
const Increment = state => {
let old = _value(state)
state = _increment(state)
if (_value(state) === old) return state
else return onIncrement(state)
}
const Decrement = state => {
let old = _value(state)
state = _decrement(state)
if(_value(state) === old) return state
else return onDecrement(state)
}
return {
increment: _increment,
decrement: _decrement,
value: _value,
model: state => ({
value: _value(state),
Increment,
Decrement,
})
}
}
const view = model => html`
<span class="counter">
<button onclick=${model.Decrement}>-</button>
${model.value}
<button onclick=${model.Increment}>+</button>
</span>`
return {init, wire, view}
})()
const init = () => ({
points: 8,
strength: counter.init(1),
dexterity: counter.init(1),
intelligence: counter.init(1),
charisma: counter.init(1),
})
const spendPoint = (state, orElse) =>
!state.points
? orElse(state)
: {
...state,
points: state.points - 1,
}
const returnPoint = state => ({
...state,
points: state.points + 1
})
const strength = counter.wire({
getter: state => state.strength,
setter: (state, strength) => ({...state, strength}),
onIncrement: state => spendPoint(state, strength.decrement),
onDecrement: returnPoint,
min: 1,
max: 5,
})
const dexterity = counter.wire({
getter: state => state.dexterity,
setter: (state, dexterity) => ({...state, dexterity}),
onIncrement: state => spendPoint(state, dexterity.decrement),
onDecrement: returnPoint,
min: 1,
max: 5,
})
const intelligence = counter.wire({
getter: state => state.intelligence,
setter: (state, intelligence) => ({...state, intelligence}),
onIncrement: state => spendPoint(state, intelligence.decrement),
onDecrement: returnPoint,
min: 1,
max: 5,
})
const charisma = counter.wire({
getter: state => state.charisma,
setter: (state, charisma) => ({...state, charisma}),
onIncrement: state => spendPoint(state, charisma.decrement),
onDecrement: returnPoint,
min: 1,
max: 5,
})
app({
init,
view: state => html`
<body>
<p>
Assign points to attributes
(<b>${state.points}</b> remaining):
</p>
<table border="1">
<tr>
<th>STR</th>
<th>DEX</th>
<th>INT</th>
<th>CHA</th>
</tr>
<tr>
<td>
<${counter.view} ${strength.model(state)} />
</td>
<td>
<${counter.view} ${dexterity.model(state)} />
</td>
<td>
<${counter.view} ${intelligence.model(state)} />
</td>
<td>
<${counter.view} ${charisma.model(state)} />
</td>
</tr>
</table>
</body>`,
node: document.body
})
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.