Skip to content

Instantly share code, notes, and snippets.

@GirlBossRush
Created November 26, 2016 13:37
Show Gist options
  • Select an option

  • Save GirlBossRush/a5b898e94663a83fdb11ebfb6ff75cf6 to your computer and use it in GitHub Desktop.

Select an option

Save GirlBossRush/a5b898e94663a83fdb11ebfb6ff75cf6 to your computer and use it in GitHub Desktop.
Skate.js WebComponents and Baobab
import {props as setProps} from 'skatejs'
export default function branch (tree, WebComponent, {actions = {}, cursors = {}}) {
const originalPropsGetter = Object.getOwnPropertyDescriptor(WebComponent, 'props').get || (() => {})
const branchedProps = {}
const cursorsEntries = []
// Define dynamic props.
Object.keys(cursors).forEach(propName => {
const cursor = tree.select(cursors[propName])
branchedProps[propName] = {
initial: cursor.get()
}
cursorsEntries.push({cursor, propName})
})
class BranchedWebComponent extends WebComponent {
constructor () {
super(...arguments)
this.actions = {}
Object.keys(actions).forEach(key => {
this.actions[key] = actions[key].bind(this, tree)
})
// Bind Cursors.
cursorsEntries.forEach(({cursor, propName}) => {
cursor.on('update', event => setProps(this, {[propName]: event.data.currentData}))
})
}
}
Object.defineProperty(BranchedWebComponent, 'props', {
get () {
// Blend original and dynamic props.
return {...originalPropsGetter(), ...branchedProps}
}
})
return BranchedWebComponent
}
@treshugart

Copy link
Copy Markdown

Hey, this looks pretty cool! I had a look, and have some thoughts on how to make it a bit closer to the patterns I've seen coming from Polymer and my views how how we should be handling mixins in Skate. It mostly revolves around making data retrievable off of the web component class rather than passing it in as arguments.

import {props as setProps} from 'skatejs'

export default function branch (WebComponent) {
  const branchedProps = {}
  const cursorsEntries = []
  const { cursors, props, tree } = WebComponent

  // Define dynamic props.
  Object.keys(WebComponent.cursors || []).forEach(propName => {
    const cursor = tree.select(cursors[propName])

    branchedProps[propName] = {
      initial: cursor.get()
    }

    cursorsEntries.push({cursor, propName})
  })

  return class class extends WebComponent {
    static props = {...props, ...branchedProps},

    constructor () {
      super(...arguments)

      const { actions } = this.constructor;

      this.actions = {}
      Object.keys(actions).forEach(key => {
        this.actions[key] = actions[key].bind(this, tree)
      })

      // Bind Cursors.
      cursorsEntries.forEach(({cursor, propName}) => {
        cursor.on('update', event => setProps(this, {[propName]: event.data.currentData}))
      })
    }
  }
}

The following are nits and don't impact the importance of the logic:

  • You might be able to do Object.keys().reduce() or map() instead of .forEach() for the branchProps and cursor generation. This of course changes the logic in the constructor.
  • You could use a symbol for the actions object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment