Skip to content

Instantly share code, notes, and snippets.

@gt3
Created December 24, 2016 21:59
Show Gist options
  • Save gt3/989efc4a819e906b8302cb32dfca39a7 to your computer and use it in GitHub Desktop.
Save gt3/989efc4a819e906b8302cb32dfca39a7 to your computer and use it in GitHub Desktop.
Tracks factory function, object literal => component
import {Component, PropTypes} from 'react'
import {beginPolling, putter, endPolling, endPollingAll, tryCloseAll} from './csp-utils'
const goPropKey = '$green'
let _isGreen = ctx => (props = ctx.props) => props[goPropKey] && ctx === props[goPropKey]
let _go = (outlet, mapper) => {
let put = putter(outlet)
return props => put(mapper(props, props[goPropKey])())
}
let trackPropTypes = {
inlets: PropTypes.object.isRequired,
[goPropKey]: PropTypes.any.isRequired,
outlet: PropTypes.object
}
let trackDefaultProps = { inlets: {}, [goPropKey]: {} }
let defineTrackProps = (C, {propTypes, defaultProps}) => {
C.propTypes = propTypes ? Object.assign({}, trackPropTypes, propTypes) : trackPropTypes
C.defaultProps = defaultProps ? Object.assign({}, trackDefaultProps, defaultProps): trackDefaultProps
return C
}
let createTrack = (domainProvider, mapper) => {
class Track extends Component {
constructor(props) {
super(props)
let domain = domainProvider(this)
let {handlers, outlet=props.outlet} = domain
let {isGreen=_isGreen(this), go=_go(outlet, mapper)} = domain
let finish = (...keys) => keys.length ? endPolling(this.pollHandlers, ...keys) : endPollingAll(this.pollHandlers)
Object.assign(this, {handlers, isGreen, go, pollHandlers: {}, finish})
}
componentWillMount() {
this.pollHandlers = beginPolling(this.handlers, null, this.props.inlets)
}
shouldComponentUpdate(nextP) {
return this.isGreen(nextP)
}
render() {
if(this.isGreen()) this.go(this.props)
return null
}
}
return defineTrackProps(Track, domainProvider)
}
let createTerminal = domainProvider => {
class Terminal extends Component {
constructor(props) {
super(props)
let {handlers, subscribe=props.subscribe, awaitMount} = domainProvider(this)
Object.assign(this, {handlers, subscribe, awaitMount})
}
subscriber() {
let handler = key => msg => {
let nextState = this.handlers[key](msg)
return nextState && this.setState(nextState)
}
return Object.keys(this.subscribe).map(k => this.subscribe[k](handler(k)))
}
componentWillMount() {
if(!this.awaitMount) this.handles = this.subscriber()
}
componentDidMount() {
if(this.awaitMount) this.handles = this.subscriber()
}
componentWillUnmount() {
if(this.handles) tryCloseAll(this.handles)
}
shouldComponentUpdate(nextP, nextS) {
return nextS !== this.state
}
render() {
return this.props.children(this.state)
}
}
Terminal.propTypes = {
children: PropTypes.func.isRequired,
subscribe: PropTypes.object.isRequired
}
Terminal.defaultProps = {
children: () => null,
subscribe: {}
}
return Terminal
}
export {createTrack, goPropKey, createTerminal}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment