cyclejs/cycle-core

View on GitHub
examples/intermediate/bmi-typescript/src/LabeledSlider.ts

Summary

Maintainability
A
0 mins
Test Coverage
import xs, {Stream, MemoryStream} from 'xstream';
import {div, span, input, VNode, DOMSource} from '@cycle/dom';

export type LabeledSliderProps = {
  label: string;
  unit: string;
  min: number;
  initial: number;
  max: number;
};

export type Sources = {
  DOM: DOMSource,
  props$: Stream<LabeledSliderProps>,
};

export type Sinks = {
  DOM: Stream<VNode>,
  value$: MemoryStream<number>,
};

function LabeledSlider(sources: Sources): Sinks {
  const props$: Stream<LabeledSliderProps> = sources.props$;
  const initialValue$ = props$.map(props => props.initial).take(1);
  const newValue$ = sources.DOM.select('.slider').events('input')
    .map(ev => parseInt((ev.target as HTMLInputElement).value));
  const value$ = xs.merge(initialValue$, newValue$).remember();

  const vdom$ = xs.combine(props$, value$)
    .map(([props, value]) =>
      div('.labeled-slider', [
        span('.label', [ props.label + ' ' + value + props.unit ]),
        input('.slider', {
          attrs: {type: 'range', min: props.min, max: props.max, value: value}
        }),
      ]),
    );

  return {
    DOM: vdom$,
    value$: value$,
  };
}

export default LabeledSlider;