UNPKG

@gssfed/vital-ui-kit-react

Version:
300 lines (274 loc) 11.2 kB
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** * * Copyright © 2018 Galaxy Software Services https://github.com/GSS-FED/vital-ui-kit-react * MIT license */ import * as React from 'react'; import ResizeObserver from 'resize-observer-polyfill'; import Icon from '../Icon'; import { Root, Wrapper, Handler, Button } from './styled'; import Tooltip from '../Tooltip'; import Track from '../Track'; import constants from './constants'; /** * @render react * @name Slider * @description Define the value by dragging the handle or side buttons * @example * <Slider * size="large" * hasButton * value={50} * max={100} * min={0} * step={5} * /> */ var Slider = function (_React$Component) { _inherits(Slider, _React$Component); function Slider() { var _ref; var _temp, _this, _ret; _classCallCheck(this, Slider); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Slider.__proto__ || Object.getPrototypeOf(Slider)).call.apply(_ref, [this].concat(args))), _this), _this.state = { active: false, position: -constants[_this.props.size].handlerSize / 2, // limit of the handle drag limit: 0, // handle offset grab: 0, // cache the mouse down postion x startX: 0, value: _this.props.value || 0 }, _this.start = 700, _this.timeout = undefined, _this.handleUpdate = function () { if (!_this.slider || !_this.track || !_this.handle) { return; } var trackWidth = _this.track.offsetWidth; var handleWith = _this.handle.offsetWidth; _this.setState(function (prevState) { return { limit: trackWidth - handleWith, grab: -handleWith / 2, position: _this.getPositionFromValue(prevState.value) }; }); }, _this.handleStart = function (e) { if (_this.props.disabled) return; if (_this.props.onChangeStart) _this.props.onChangeStart(e); _this.setState({ active: true, startX: e.clientX }); // $FlowFixMe document.addEventListener('mousemove', _this.handleDrag); // $FlowFixMe document.addEventListener('mouseup', _this.handleEnd); }, _this.handleTrack = function (e) { if (_this.props.disabled) return; e.stopPropagation(); // $FlowFixMe var percentage = e.nativeEvent.offsetX / _this.track.clientWidth; var value = _this.props.step * Math.round(percentage * (_this.props.max - _this.props.min) / _this.props.step); _this.setState({ value: value }); if (_this.props.onChange) _this.props.onChange(value, e); }, _this.handleDrag = function (e) { e.stopPropagation(); var value = _this.getValueFromPosition(e.clientX); _this.setState({ value: value }); if (_this.props.onChange) _this.props.onChange(value, e); }, _this.handleEnd = function (e) { if (_this.props.onChangeComplete) _this.props.onChangeComplete(e); _this.setState(function (prevState) { return { active: false, position: _this.getPositionFromValue(prevState.value) }; }); // $FlowFixMe document.removeEventListener('mousemove', _this.handleDrag); // $FlowFixMe document.removeEventListener('mouseup', _this.handleEnd); }, _this.handleIncrease = function () { if (_this.props.disabled) return; _this.increaseByStep(); _this.timeout = setTimeout(_this.handleIncrease, _this.start); _this.start = _this.start / 2; }, _this.handleDecrease = function () { if (_this.props.disabled) return; _this.decreaseByStep(); _this.timeout = setTimeout(_this.handleDecrease, _this.start); _this.start = _this.start / 2; }, _this.increaseByStep = function () { _this.setState(function (prevState) { return { value: _this.clamp(prevState.value + _this.props.step, _this.props.max, _this.props.min) }; }); }, _this.decreaseByStep = function () { _this.setState(function (prevState) { return { value: _this.clamp(prevState.value - _this.props.step, _this.props.max, _this.props.min) }; }); }, _this.getPositionFromValue = function (value) { var _this$props = _this.props, min = _this$props.min, max = _this$props.max; var limit = _this.state.limit; var diffMaxMin = max - min; var diffValMin = value - min; var percentage = diffValMin / diffMaxMin; var pos = Math.round(percentage * limit); return pos; }, _this.getValueFromPosition = function (pos) { var _this$state = _this.state, startX = _this$state.startX, limit = _this$state.limit, grab = _this$state.grab, position = _this$state.position; var diff = pos - startX; var newHandlerLeft = _this.clamp(position + diff, limit, grab); var percentage = (newHandlerLeft - grab) / (limit - grab); var value = _this.props.step * Math.round(percentage * (_this.props.max - _this.props.min) / _this.props.step); return value; }, _this.clamp = function (value, max, min) { return Math.min(Math.max(value, min), max); }, _this.renderDecreaseButton = function () { var buttonShow = _this.props.hasButton; if (_this.props.decreaseButton) buttonShow = true; if (buttonShow) { var buttonProps = { onMouseDown: _this.handleDecrease, onMouseUp: function onMouseUp() { clearTimeout(_this.timeout); _this.start = 700; }, style: { marginRight: '12px', flex: '0 0 auto' } }; if (_this.props.decreaseButton) { return React.cloneElement(_this.props.decreaseButton, _extends({}, buttonProps)); } return React.createElement( Button, _extends({}, buttonProps, { circle: true, size: 'xsmall' }), React.createElement(Icon, { name: 'chevron-left', size: '13' }) ); } return null; }, _this.renderIncreaseButton = function () { var buttonShow = _this.props.hasButton; if (_this.props.increaseButton) buttonShow = true; if (buttonShow) { var buttonProps = { onMouseDown: _this.handleIncrease, onMouseUp: function onMouseUp() { clearTimeout(_this.timeout); _this.start = 700; }, style: { marginLeft: '12px', flex: '0 0 auto' } }; if (_this.props.increaseButton) { return React.cloneElement(_this.props.increaseButton, _extends({}, buttonProps)); } return React.createElement( Button, _extends({}, buttonProps, { circle: true, size: 'xsmall' }), React.createElement(Icon, { name: 'chevron-right', size: '13' }) ); } return null; }, _temp), _possibleConstructorReturn(_this, _ret); } // delay timeout of the button calling function _createClass(Slider, [{ key: 'componentDidMount', value: function componentDidMount() { this.handleUpdate(); var resizeObserver = new ResizeObserver(this.handleUpdate); resizeObserver.observe(this.track); } }, { key: 'render', value: function render() { var _this2 = this; // var position = this.getPositionFromValue(this.state.value); return React.createElement( Root, { innerRef: function innerRef(s) { _this2.slider = s; }, disabled: this.props.disabled, 'aria-valuemin': this.props.min, 'aria-valuemax': this.props.max, 'aria-valuenow': this.props.value }, this.renderDecreaseButton(), React.createElement( Wrapper, { size: this.props.size, disabled: this.props.disabled }, React.createElement(Track, { size: this.props.size, onMouseDown: this.handleTrack, onMouseUp: function onMouseUp(e) { _this2.setState({ startX: e.clientX }); _this2.handleEnd(e); }, onTouchStart: this.handleStart, onTouchEnd: this.handleEnd, trackRef: function trackRef(s) { _this2.track = s; }, disabled: this.props.disabled, selectionWidth: position - this.state.grab }), React.createElement( Tooltip, { placement: 'bottom', overlay: this.state.value, trigger: ['hover'] }, React.createElement(Handler, { size: this.props.size, innerRef: function innerRef(s) { _this2.handle = s; }, style: { left: position + 'px' }, active: this.state.active, onMouseDown: this.handleStart }) ) ), this.renderIncreaseButton() ); } }]); return Slider; }(React.Component); Slider.defaultProps = { size: 'medium', disabled: false, hasButton: false, decreaseButton: null, increaseButton: null, trackLabel: false, onChangeStart: null, onChangeComplete: null }; export default Slider;