Skip to content

RFC: api proposal #1

Description

@Hotell

this tweet speaks really out for itself, lot of truth in there so let's use it in practice shall we ?! :D
https://twitter.com/housecor/status/938805364442718210?s=17

boardJS api proposal:

  • we don't need mixins like skate ( deep prototype chains meh, for our usecase we wanna use all in )

  • base Component class which should handle

    • async rendering via render()
    • props API ( component public API, immutable ala React )
    • state API ( for internal state ala React )
    • configurable turning on/off for shadowDOM
    • shouldUpdate and willUpdate LC hooks
    • fine grained LC hooks like skates provides ?
    • instance emitter so we don't have to emit(this,'foo',...config) all the time
    • configurable style API ( which will use shadyCSS in non supported browsers)
  • base Component will be created from function mixin which will configure Base component

import {h} from 'preact'
import { withComponent } from 'boardjs'

// standard Component
const Component = withComponent()

// no shadow dom
const NoShadowComponent = withComponent({shadow: false })

// this might be used if consumer want's to use css in js
const NoScopedStyles = withComponent({styleScoping: false})

API

import { withComponent } from 'boardjs'

// standard Component
const Component = withComponent()

type Props = {
  greeting: string
  startTimer: boolean
}
type State = {
  count: number
}

type Events = {
  timerToggle: CustomEvent
}

class Hello extends Component<Props, State, Events> {
  static is = 'x-hello'
  static get props() {
    return {
      greeting: { type: String },
      startTimer: { type: Boolean, reflect: true },
    }
  }
  static get events() {
    return {
      timerToggle: {
        // ...eventConfig  as CustomEventInit -> detail: MyModel // MyModel is a class
      },
    }
  }
  state = {
    count: 0,
  }
  get styles() {
    return `
      :host { display: block; }
      h1 { font-size: 1rem; }
      button { color: white; backgound-color: blue; }
    `
  }
  render() {
    return (
      <div>
        <h1>Hello {this.props.greeting}</h1>
        <div>
          Counter: {this.state.count}
          <br />
          <button onClick={_ => (this.state.count = this.state.count + 1)}>+</button>
          <button onClick={_ => (this.state.count = this.state.count - 1)}>-</button>
          <button onClick={_ => this.events.timerToggle()}>Toggle Timer</button>
        </div>
      </div>
    )
  }

  shouldComponentUpdate(nextProps, nextState) {
    return true
  }
  forceUpdate() {
    // Calling forceUpdate() will cause render() to be called on the component, skipping shouldComponentUpdate()
  }

  // Called when props/state have been set regardless of if they've changed.
  componentWillUpdate() {
    console.log('The component did update')
  }

  // Called if shouldUpdate returned true.
  componentDidUpdate() {
    console.log('The component did update')
  }

  componentWillMount() {
    console.log('The component is gona been rendered')
  }
  componentDidMount() {
    console.log('The component has been rendered')
  }
  componentWillUnmount() {
    console.log('The view is gonna be removed from the DOM')
  }
  componentDidUnmount() {
    console.log('The view has been removed from the DOM')
  }

  componentChildrenDidUpdate() {
    // react to changes to your component's children
  }
}

customElements.define(Hello.is, Hello)

export default Hello

Renderer

  • preact
  • stencil customized preact VDOM ( this would allow us to return arrays from render - win ! )
  • may switch to lit-html when it will have cross browser support

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions