vcc-ui
Version:
VCC UI is a collection of React UI Components that can be used for developing front-end applications at Volvo Car Corporation.
474 lines (397 loc) • 16.5 kB
JavaScript
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
import React, { Component } from "react";
import PropTypes from "prop-types";
import { withTheme } from "react-fela";
import { Arrow } from "../arrow";
import { Block } from "../block";
import { Click } from "../click";
import { getThemeStyle } from "../../get-theme-style";
var KEY_LEFT = 37;
var KEY_UP = 38;
var KEY_RIGHT = 39;
var KEY_DOWN = 40;
var THUMB_WIDTH = 40;
var THUMB_HEIGHT = 40;
var thumbStyle = function thumbStyle(_ref) {
var left = _ref.left,
isDragging = _ref.isDragging,
theme = _ref.theme,
disabled = _ref.disabled;
return {
position: "absolute",
top: 0,
left: left,
width: THUMB_WIDTH,
height: THUMB_HEIGHT,
border: "1px solid " + theme.tokens.inputBorder,
background: theme.tokens.inputBackground,
cursor: disabled ? "not-allowed" : "ew-resize",
display: "flex",
alignItems: "center",
justifyContent: "center",
outline: 0,
":focus": {
borderColor: theme.tokens.inputBorderFocus
},
extend: {
condition: !isDragging,
style: {
transition: "left 200ms ease-out"
}
}
};
};
var SliderComponent =
/*#__PURE__*/
function (_Component) {
_inherits(SliderComponent, _Component);
function SliderComponent(props) {
var _this;
_classCallCheck(this, SliderComponent);
_this = _possibleConstructorReturn(this, _getPrototypeOf(SliderComponent).call(this, props));
_defineProperty(_assertThisInitialized(_this), "state", {
isDragging: false,
lastStep: 0,
currentLeft: 0
});
_defineProperty(_assertThisInitialized(_this), "componentDidUpdate", function (prevProps) {
var initialValue = _this.props.initialValue;
var prevInitialValue = prevProps.initialValue;
if (initialValue !== prevInitialValue) {
_this.setState(function () {
return {
currentStep: _this.getStepForValue(initialValue)
};
});
}
});
_defineProperty(_assertThisInitialized(_this), "handleChange", function () {
var _this$props$onChange = _this.props.onChange,
onChange = _this$props$onChange === void 0 ? function () {} : _this$props$onChange;
var _this$state = _this.state,
lastStep = _this$state.lastStep,
currentStep = _this$state.currentStep;
var currentValue = _this.getCurrentValue();
if (lastStep !== currentStep && typeof onChange === "function") {
onChange(currentValue);
}
});
_defineProperty(_assertThisInitialized(_this), "getElementProperty", function (element, property) {
return element && element.getBoundingClientRect ? element.getBoundingClientRect()[property] : 0;
});
_defineProperty(_assertThisInitialized(_this), "getElementWidth", function (element) {
return _this.getElementProperty(element, "width");
});
_defineProperty(_assertThisInitialized(_this), "getElementLeft", function (element) {
return _this.getElementProperty(element, "left");
});
_defineProperty(_assertThisInitialized(_this), "getNumberOfSteps", function () {
var _this$props = _this.props,
step = _this$props.step,
minValue = _this$props.minValue,
maxValue = _this$props.maxValue,
_this$props$valueList = _this$props.valueList,
valueList = _this$props$valueList === void 0 ? [] : _this$props$valueList;
if (valueList.length > 0) {
return valueList.length;
} else {
return (maxValue - minValue) / step + 1;
}
});
_defineProperty(_assertThisInitialized(_this), "getStepAtPercentagePosition", function (percentagePosition) {
var steps = _this.getNumberOfSteps();
return Math.round(percentagePosition * (steps - 1));
});
_defineProperty(_assertThisInitialized(_this), "getStepForValue", function (value) {
var _this$props2 = _this.props,
minValue = _this$props2.minValue,
maxValue = _this$props2.maxValue,
_this$props2$valueLis = _this$props2.valueList,
valueList = _this$props2$valueLis === void 0 ? [] : _this$props2$valueLis;
var steps = _this.getNumberOfSteps();
var thisValue = value - minValue;
var range = maxValue - minValue;
if (valueList.length > 0) {
return valueList.indexOf(value);
} else {
return Math.round((steps - 1) * thisValue / range);
}
});
_defineProperty(_assertThisInitialized(_this), "getValueAtStepPosition", function (step) {
var _this$props3 = _this.props,
minValue = _this$props3.minValue,
maxValue = _this$props3.maxValue,
_this$props3$valueLis = _this$props3.valueList,
valueList = _this$props3$valueLis === void 0 ? [] : _this$props3$valueLis;
var steps = _this.getNumberOfSteps();
if (valueList.length > 0) {
return valueList.find(function (value, index) {
return index === step;
});
} else {
return minValue + step * ((maxValue - minValue) / (steps - 1));
}
});
_defineProperty(_assertThisInitialized(_this), "getCurrentValue", function () {
var currentStep = _this.state.currentStep;
return _this.getValueAtStepPosition(currentStep);
});
_defineProperty(_assertThisInitialized(_this), "updateCurrentStep", function (position) {
var trackWidth = _this.getElementWidth(_this.trackRef.current);
var trackLeft = _this.getElementLeft(_this.trackRef.current);
var thumbWidth = THUMB_WIDTH;
var newPositionLeft = position - trackLeft - thumbWidth / 2;
var isMax = newPositionLeft >= trackWidth - thumbWidth;
var isMin = newPositionLeft <= 0;
var currentPositionLeft = isMax ? trackWidth - thumbWidth : isMin ? 0 : newPositionLeft;
var currentPositionPercent = currentPositionLeft / (trackWidth - thumbWidth);
if (typeof position === "number") {
_this.setState({
currentStep: _this.getStepAtPercentagePosition(currentPositionPercent),
currentLeft: currentPositionLeft
});
}
});
_defineProperty(_assertThisInitialized(_this), "getLeftPositionFromCurrentStep", function () {
if (!_this.trackRef || !_this.thumbRef) {
return 0;
}
var _this$state2 = _this.state,
_this$state2$currentS = _this$state2.currentStep,
currentStep = _this$state2$currentS === void 0 ? 0 : _this$state2$currentS,
_this$state2$currentL = _this$state2.currentLeft,
currentLeft = _this$state2$currentL === void 0 ? 0 : _this$state2$currentL;
var steps = _this.getNumberOfSteps();
var trackWidth = _this.getElementWidth(_this.trackRef.current);
var leftPos = currentStep * (trackWidth - THUMB_WIDTH) / (steps - 1);
return currentLeft ? currentLeft : Math.round(leftPos);
});
_defineProperty(_assertThisInitialized(_this), "handleMouseDown", function (e) {
_this.updateCurrentStep(e.clientX);
_this.setState({
lastStep: _this.state.currentStep
});
});
_defineProperty(_assertThisInitialized(_this), "handleDragStart", function () {
_this.setState({
isDragging: true,
lastStep: _this.state.currentStep
});
document.addEventListener("mousemove", _this.handleDrag);
document.addEventListener("mouseup", _this.handleDragEnd);
});
_defineProperty(_assertThisInitialized(_this), "handleDrag", function (e) {
var onMoveStart = _this.props.onMoveStart;
var currentValue = _this.getCurrentValue();
e.preventDefault();
e.stopPropagation();
if (_this.state.isDragging) {
_this.updateCurrentStep(e.touches ? e.touches[0].clientX : e.clientX);
if (typeof onMoveStart === "function") {
onMoveStart(currentValue);
}
}
});
_defineProperty(_assertThisInitialized(_this), "handleDragEnd", function () {
var onMoveEnd = _this.props.onMoveEnd;
_this.setState({
isDragging: false
});
document.removeEventListener("mousemove", _this.handleDrag);
document.removeEventListener("mouseup", _this.handleDragEnd);
_this.thumbRef.current.blur();
_this.resetCurrentLeft();
_this.handleChange();
if (typeof onMoveEnd === "function") {
onMoveEnd();
}
});
_defineProperty(_assertThisInitialized(_this), "adjustCurrentStepBy", function (diff) {
var currentStep = _this.state.currentStep;
var steps = _this.getNumberOfSteps();
var nextStep = currentStep + diff;
_this.setState({
currentStep: nextStep <= steps - 1 && nextStep >= 0 ? nextStep : currentStep
});
});
_defineProperty(_assertThisInitialized(_this), "handleKeyDown", function (e) {
e.preventDefault();
e.stopPropagation();
var key = e.which;
if (key === KEY_UP || key === KEY_RIGHT) {
_this.adjustCurrentStepBy(1);
} else if (key === KEY_DOWN || key === KEY_LEFT) {
_this.adjustCurrentStepBy(-1);
}
});
_this.trackRef = React.createRef();
_this.thumbRef = React.createRef();
return _this;
}
_createClass(SliderComponent, [{
key: "componentDidMount",
value: function componentDidMount() {
var _this2 = this;
var initialValue = this.props.initialValue;
this.setState({
currentStep: this.getStepForValue(initialValue)
});
var resizeTimer;
this.resizeEventHandler = function () {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
_this2.forceUpdate();
}, 1);
};
window.addEventListener("resize", this.resizeEventHandler);
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
window.removeEventListener("resize", this.resizeEventHandler);
}
}, {
key: "resetCurrentLeft",
value: function resetCurrentLeft() {
this.setState({
currentLeft: 0
});
}
}, {
key: "handleMouseUp",
value: function handleMouseUp() {
this.resetCurrentLeft();
this.handleChange();
}
}, {
key: "handleKeyUp",
value: function handleKeyUp() {
this.setState({
lastStep: this.state.currentStep
});
this.handleChange();
}
}, {
key: "renderThumb",
value: function renderThumb() {
var _this3 = this;
var _this$props4 = this.props,
minValue = _this$props4.minValue,
maxValue = _this$props4.maxValue,
theme = _this$props4.theme,
disabled = _this$props4.disabled;
var value = this.getCurrentValue();
var left = this.getLeftPositionFromCurrentStep();
var styleProps = {
isDragging: this.state.isDragging,
left: left,
theme: theme,
disabled: disabled
};
return React.createElement(Click, {
innerRef: this.thumbRef,
extend: [thumbStyle(styleProps), getThemeStyle("sliderThumb", theme, styleProps)],
role: "slider",
"aria-valuemin": minValue,
"aria-valuemax": maxValue,
"aria-valuenow": value,
"aria-orientation": "horizontal",
disabled: disabled,
onMouseDown: function onMouseDown() {
return _this3.handleDragStart();
},
onMouseMove: function onMouseMove(e) {
return _this3.handleDrag(e);
},
onMouseUp: function onMouseUp() {
return _this3.handleDragEnd();
},
onContextMenu: function onContextMenu() {
return _this3.handleDragEnd();
},
onTouchStart: function onTouchStart() {
return _this3.handleDragStart();
},
onTouchMove: function onTouchMove(e) {
return _this3.handleDrag(e);
},
onTouchEnd: function onTouchEnd() {
return _this3.handleDragEnd();
},
onKeyDown: function onKeyDown(e) {
return _this3.handleKeyDown(e);
},
onKeyUp: function onKeyUp() {
return _this3.handleKeyUp();
}
}, React.createElement(Arrow, {
color: theme.tokens[disabled ? "inputDisabledControl" : "inputControl"],
direction: "left"
}), React.createElement(Arrow, {
color: theme.tokens[disabled ? "inputDisabledControl" : "inputControl"],
direction: "right"
}));
}
}, {
key: "render",
value: function render() {
var _this4 = this;
var theme = this.props.theme;
return React.createElement(Block, {
extend: [{
position: "relative",
height: 42
}, getThemeStyle("slider", theme)]
}, React.createElement(Block, {
extend: [{
position: "absolute",
top: 9,
left: 0,
right: 0,
width: "100%",
boxSizing: "border-box",
height: 21,
borderWidth: 1,
borderStyle: "solid",
borderColor: theme.tokens.inputBorder,
background: theme.tokens.inputBackground,
cursor: this.props.disabled ? "not-allwoed" : "pointer"
}, getThemeStyle("sliderTrack", theme)],
innerRef: this.trackRef,
onMouseDown: function onMouseDown(e) {
if (!_this4.props.disabled) {
_this4.handleMouseDown(e);
}
},
onMouseUp: function onMouseUp() {
if (!_this4.props.disabled) {
_this4.handleMouseUp();
}
}
}), typeof this.state.currentStep !== "undefined" && this.renderThumb());
}
}]);
return SliderComponent;
}(Component);
_defineProperty(SliderComponent, "propTypes", {
initialValue: PropTypes.number.isRequired,
minValue: PropTypes.number,
maxValue: PropTypes.number,
step: PropTypes.number,
valueList: PropTypes.array,
onMoveStart: PropTypes.func,
onMoveEnd: PropTypes.func,
onChange: PropTypes.func
});
SliderComponent.displayName = "Slider";
var Slider = withTheme(SliderComponent);
export { Slider };