npm install --save @playframe/componentPure Functional Styled Web Components for PlayFrame. Components are rendered independetly from the rest of the app. By using Shadow DOM provided by ShaDOM we achieve scoped styling and simple css selectors. Please consider using CSS Variables for maximum animation performance and flexibility.
You can create instances manually and keep them in parent state or
you can register them with fp.use or h.use and create them dynamically.
To be able to identify the same dynamic component we use a unique
object mkey as a
WeakMap
key. For a UserView Component actual user object would be a perfect
WeakMap key
import h from '@playframe/h'
import oversync from '@playframe/oversync'
import component from '@playframe/component'
const sync = oversync(Date.now, requestAnimationFrame)
const Component = component(sync)
export default myCounter = (Component)=>
  Component({
    seconds: 0,
    _: {
      reset: ()=> {seconds: 0}
      increment: (x, state)=> {
        state.seconds++
        setTimeout( state._.increment,
          (1000 - Date.now() % 1000) || 1000 )
      }
    }
  })((state)=>
    <my-counter style={ {'--border': state.border} }>
      <style>{`
        :host {
          display: block;
          border: var(--border, 0);
        }
      `}</style>
      <div>
        {props.children}
        <br/>
        {state.seconds} seconds passed
        <br/>
        <button onclick={state._.reset}> Reset </button>
      </div>
    </my-counter>
  )
// our Counter instance with initial props
const MyCounter = myCounter(Component)({seconds: 42})
// reset in 10 seconds
setTimeout(MyCounter._.reset, 10000)
const view = ()=>
  <MyCounter border="1px solid grey">
    <h1>Hello</h1>
  </MyCounter>
// or we can register component as custom element
h.use({'my-counter': (props)=>
  let mkey = props && props.mkey
  makeMyCounter(Component)({mkey})(props)
})
// mkey is used as WeakMap key to cache our statefull component
const mkey = {uniqueObject: true}
const view = ()=>
  <my-counter mkey={mkey} border="1px solid grey">Hello</my-counter>We are going to use statue for managing state of our Component
evolve = require '@playframe/evolve'
statue = require '@playframe/statue'How about using a tree of
WeakMap
instances to cache our Component instances by mkey?
This allows us to cache our components aggresively because our _cache
will be cleaned automatically by Garbage Collector if mkey gets dereferenced
Let's export a higher order function that takes sync engine,
state_actions for statue and a pure view function.
module.exports = (sync)=>(state_actions)=>(view)=> _cache = new WeakMap; (upgrade)=>
  if (mkey = upgrade and upgrade.mkey) and
      Component = _cache.get mkey
    return Component
  _v_dom = null
  _props = null
  _rendering = false
  _state = evolve state_actions, upgradeCreating a statue that will deliver the latest state on
sync.render and patch shadow DOM if needed
  _state = statue _state, sync.render, (state)=>
    _state = state
    do patch_shadow unless _rendering
    _rendering = false
    returnpatch_shadow is responsible for producing new virtual DOM and using
patch method for shadow DOM mutation provided by
ShaDOM.
  patch_shadow = =>
    {patch} = _v_dom
    _v_dom = view _state
    _v_dom.patch = patch
    patch _v_dom
    return
  render = =>
    _v_dom = view _state
    attr = _v_dom[1] or= {}
    attr.attachShadow or= mode: 'open'
    returnHere we create our Component function that mimics your view
function. But first it's checking if props are meant to update _state
  Component = (props)=>
    if _v_dom
      unless props is _props
        # shallow equality check
        for k, v of props when v isnt _state[k]
          # updating state with props and rendering
          _state = _state._ _props = props
          _rendering = true
          do render
          break
    else # first run
      _state = Object.assign _state._(), _props = props
      do render
    _v_domAssigning high level methods from statue, adding instance to cache and our
fresh Component is ready!
  Component._ = _state._
  _cache.set mkey, Component if mkey
  Component