hyperapp web components example
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=2">
<meta name="apple-mobile-web-app-capable" content="yes">
<style>body{margin:0;padding:0;}</style>
<script type="module">
document.addEventListener('touchmove',e=>e.preventDefault(),{passive:false})
import { h, app } from 'https://unpkg.com/hyperapp?module'
!function() {
const state = {
value: 0,
}
const actions = {
increment: value => state => ({ value: state.value + +value }),
decrement: value => state => ({ value: state.value - +value }),
crement: value => state => ({ value: +value }),
}
const view = (light) => (state, actions) =>
h('div', {},
h('style', {}, '*{touch-action:manipulation;}'),
h('input', numberbox(state, actions, light)),
h('button', decrement(actions), '-'),
h('button', increment(actions), '+'),
)
const numberbox = (state, actions, light) => ({
value: state.value,
oninput: (event) => {
if (+event.target.value) actions.crement(event.target.value)
},
onupdate: dispatcher(light),
})
const increment = ({increment}) => ({
onclick: () => increment(1),
})
const decrement = ({decrement}) => ({
onclick: () => decrement(1),
})
const changeEvent = new CustomEvent('change')
const dispatcher = (light) => (element, oldAttributes) => {
const newVal = +element.value
const oldVal = +oldAttributes.value
if (newVal == oldVal) return
light.value = newVal
light.dispatchEvent(changeEvent)
}
customElements.define('hyper-numberbox', class extends HTMLElement {
static get observedAttributes() {
return ['value']
}
attributeChangedCallback(attr, oldValue, newValue) {
if (oldValue == newValue) return
if (attr == 'value') {
this.actions.crement(+newValue)
}
}
constructor() {
super()
this.attachShadow({mode:'open'})
this.actions = app(state, actions, view(this), this.shadowRoot)
}
})
}();
// ===================
const state = {
rate: 109,
dollars: 0,
yen: 0,
}
const actions = {
setRate: rate => state => ({
rate: +rate,
yen : +rate * +state.dollars,
}),
setDollars: dollars => state => ({
dollars: +dollars,
yen : +state.rate * +dollars,
}),
}
const view = (state, actions) =>
h('div', {},
h('h1', {}, 'Currency converter'),
h('h2', {}, '¥ ' + state.yen),
h('span', {}, 'rate'),
h('hyper-numberbox', rate(state, actions)),
h('span', {}, 'dollars'),
h('hyper-numberbox', dollars(state, actions)),
)
const rate = (state, actions) => ({
value: state.rate,
onchange: (event) => actions.setRate(event.target.value)
})
const dollars = (state, actions) => ({
value: state.dollars,
onchange: (event) => actions.setDollars(event.target.value)
})
app(state, actions, view, document.body)
</script>