<div id="app"></div>
window.xs = window.xstream.default;
window.xs.fromEvent = window.fromEvent.default;

const { div, label, input, button, p, makeDOMDriver } = CycleDOM;

function view(state$) {
  return state$.map(state => {
    return div(".labeled-slider", [
      label(".label", `${state.label}: ${state.value} ${state.unit}`),
      input(".slider", {
        attrs: {
          type: "range",
          min: state.min,
          max: state.max,
          value: state.value
        }
      })
    ]);
  });
}
function intent(sources) {
  const domSource = sources.DOM;
  const value$ = domSource
    .select(".slider")
    .events("input")
    .map(ev => ev.target.value);
  return { value: value$ };
}
function model(intents, props) {
  const { value } = intents;
  return props
    .map(props =>
      value.startWith(props.init).map(value => ({ ...props, value }))
    )
    .flatten();
}
function Slider(sources) {
  const actions = intent(sources);
  const state$ = model(actions, sources.props);
  const vdom$ = view(state$);
  return { DOM: vdom$ };
}

function main(sources) {
  const { isolateSource, isolateSink } = sources.DOM;
  const weightProps = xs.of({
    label: "Weight",
    min: 40,
    max: 100,
    init: 58,
    unit: "kg"
  });
  const weightDOMSource = isolateSource(sources.DOM, ".weight");
  const weightSinks = Slider({
    ...sources,
    DOM: weightDOMSource,
    props: weightProps
  });
  const weightVDOM$ = isolateSink(weightSinks.DOM, ".weight");
  const heightProps = xs.of({
    label: "Height",
    min: 140,
    max: 220,
    init: 165,
    unit: "cm"
  });
  const heightDOMSource = isolateSource(sources.DOM, ".height");
  const heightSinks = Slider({
    ...sources,
    DOM: heightDOMSource,
    props: heightProps
  });
  const heightVDOM$ = isolateSink(heightSinks.DOM, ".height");
  const vdom$ = xs
    .combine(weightVDOM$, heightVDOM$)
    .map(([weightVDOM, heightVDOM]) => div([weightVDOM, heightVDOM]));
  return { DOM: vdom$ };
}
const drivers = {
  DOM: makeDOMDriver("#app")
};

Cycle.run(main, drivers);
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://static.jonirrings.com/xstream/xstream.min.js
  2. https://static.jonirrings.com/xstream/extra/fromEvent.js
  3. https://unpkg.com/@cycle/run@4.4.0/dist/cycle-run.min.js
  4. https://unpkg.com/@cycle/dom@20.4.0/dist/cycle-dom.min.js