uchcode
2/13/2019 - 11:18 PM

hyperapp web components example

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>