Skip to content

Instantly share code, notes, and snippets.

@staltz
Created August 6, 2015 21:15
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save staltz/b9850c4e620946edf14e to your computer and use it in GitHub Desktop.
Save staltz/b9850c4e620946edf14e to your computer and use it in GitHub Desktop.
Hierarchical Cycle.js
import {Rx} from '@cycle/core'
import {h} from '@cycle/dom'
import _ from 'lodash'
import makeSlider from './slider'
function makeBMICalculator(namespace) {
const name = _.last(namespace)
const model = (weightState$, heightState$) => {
return Rx.Observable.combineLatest(weightState$, heightState$,
(weightState, heightState) => {
let heightMeters = heightState.value * 0.01
let bmi = Math.round(weightState.value / (heightMeters * heightMeters))
return {bmi}
})
.shareReplay(1)
}
const view = (state$, weightVTree$, heightVTree$) => state$.map(({bmi}) => {
return h('div' + name, [
weightVTree$,
heightVTree$,
h('h2', 'BMI is ' + bmi)
])
})
return function minimain(DOM) {
const weightSlider = makeSlider(namespace.concat('.weight'))
const heightSlider = makeSlider(namespace.concat('.height'))
const weightProps$ = Rx.Observable.just(
{label: 'Weight', unit: 'kg', initial: 75, min: 40, max: 150}
)
const heightProps$ = Rx.Observable.just(
{label: 'Height', unit: 'cm', initial: 170, min: 130, max: 210}
)
const {DOM: weightVTree$, state$: weightState$} = weightSlider(DOM, weightProps$)
const {DOM: heightVTree$, state$: heightState$} = heightSlider(DOM, heightProps$)
return {
DOM: view(model(weightState$, heightState$), weightVTree$, heightVTree$)
}
}
}
export default makeBMICalculator
import {Rx} from '@cycle/core'
import {h} from '@cycle/dom'
import _ from 'lodash'
import makeBMICalculator from '../components/bmi-calculator'
function makeBMIPage(namespace) {
const name = _.last(namespace)
const view = (calcVTree$) => Rx.Observable.just(
h('div' + name, [
calcVTree$
])
)
return function minimain(DOM) {
const calc = makeBMICalculator(namespace.concat('.bmi-calculator'))
const calcVTree$ = calc(DOM).DOM
return {
DOM: view(calcVTree$)
}
}
}
export default makeBMIPage
import {Rx, run} from '@cycle/core'
import {makeDOMDriver} from '@cycle/dom'
import makeBMIPage from './pages/bmi-page'
function main({DOM}) {
const bmiPage = makeBMIPage(['.bmi-page'])
return bmiPage(DOM)
}
const drivers = {
DOM: makeDOMDriver('.js-container')
}
run(main, drivers)
import {Rx} from '@cycle/core'
import {h} from '@cycle/dom'
import _ from 'lodash'
function makeSlider(namespace) {
const name = _.last(namespace)
const intent = (DOM) => ({
change$: DOM.get(`${namespace.join(' ')} input`, 'input')
.map(ev => ev.target.value)
})
const model = (actions, props$) => (
props$.map(({initial}) => initial).first()
.concat(actions.change$)
.combineLatest(props$, (value, props) => ({
value,
unit: props.unit,
min: props.min,
max: props.max,
label: props.label
}))
.shareReplay(1)
)
const view = (state$) => state$.map(({value, unit, label, min, max}) => {
return h(`div${name}`, [
`${label} ${value}${unit}`,
h('input', {type: 'range', min, max, value})
])
})
return function minimain(DOM, props$) {
const state$ = model(intent(DOM), props$)
return {
DOM: view(state$),
state$
}
}
}
export default makeSlider
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment