bindings/jupyter-modules/jupyter-ma-causal/src/containers/line-indicator-container/index.js (93 lines of code) (raw):

import React, {Component} from 'react'; import {connect} from 'react-redux'; import {scaleLinear} from 'd3-scale'; import {format as d3Format} from 'd3-format'; import {clamp} from '../../utils'; import {getSliderValueFactory} from '../../selectors/factories'; import { getChartWidth, getChartPadding, } from '../../selectors/indicator-line-selectors'; import {updateSliderValues} from '../../actions'; const mapStateToProps = (state, props) => { const {index} = props; const getSliderValue = getSliderValueFactory(index); return { width: getChartWidth(state), padding: getChartPadding(state), sliderValue: getSliderValue(state), }; }; const mapDispatchToProps = {updateSliderValues}; class Chart extends Component { _getScale() { const { width, padding: {left, right}, } = this.props; return scaleLinear() .domain([0, 1]) .range([left, width - right]); } _getEventMouse = event => { const {clientX, clientY} = event; const {left, top} = this.div.parentNode.getBoundingClientRect(); return [clientX - left, clientY - top]; }; render() { const { width, sliderValue, padding: {top, bottom, left, right}, index, } = this.props; const scale = this._getScale(); const x = scale( sliderValue === null || sliderValue === undefined ? 1 : sliderValue ); return ( <React.Fragment> <div ref={input => (this.div = input)} style={{ position: 'absolute', left: x, top, width: 0, height: `calc(100% - ${bottom}px)`, borderLeft: '1px dotted black', cursor: 'ew-resize', }} onPointerDown={event => { event.target.setPointerCapture(event.pointerId); this.move = this._getEventMouse(event); }} onPointerMove={event => { if (this.move) { const [x, y] = this._getEventMouse(event); const [sx] = this.move; const dx = x - sx; const mx = Math.min(Math.max(x + dx, left), width - right); this.move = [x, y]; const value = clamp(scale.invert(mx)); this.props.updateSliderValues({[index]: value}); } }} onPointerUp={event => { this.move = null; }} /> <div style={{ position: 'absolute', left: x - 13, top: 'calc(100% - 3px)', }} > {`${d3Format('2d')( (sliderValue === null || sliderValue === undefined ? 1 : sliderValue) * 100 )}%`} </div> </React.Fragment> ); } } export default connect( mapStateToProps, mapDispatchToProps )(Chart);