fk-react-ui-components
Version:
Step 1 : Create a file in [ Seeds / Plants / Trees ] <br> Step 2 : It should export an Object with component name and story Component [Refer other components] <br> Step 3 : Story Component should return a react component <br> Step 3 : Created file should
582 lines (486 loc) • 22.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
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; }; }();
var _templateObject = _taggedTemplateLiteral(['\n width: 50px;\n outline: none;\n'], ['\n width: 50px;\n outline: none;\n']);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _styledComponents = require('styled-components');
var _styledComponents2 = _interopRequireDefault(_styledComponents);
var _propTypes = require('./propTypes');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _styles = require('./styles');
var _Inputs = require('../FormElements/Inputs');
var _Inputs2 = _interopRequireDefault(_Inputs);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
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; }
function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
var Input = (0, _styledComponents2.default)(_Inputs2.default)(_templateObject);
var Slider = function (_React$PureComponent) {
_inherits(Slider, _React$PureComponent);
function Slider(props) {
_classCallCheck(this, Slider);
var _this = _possibleConstructorReturn(this, (Slider.__proto__ || Object.getPrototypeOf(Slider)).call(this, props));
_initialiseProps.call(_this);
_this.handleRefs = [];
var value = props.value;
if (typeof value === 'undefined' || value.length === 0) {
value = typeof props.defaultValue !== 'undefined' ? props.defaultValue : props.range ? [props.min, props.max] : props.min;
}
_this.state = {
value: value,
draggingHandleIndex: null,
isComponentMounted: false
};
_this.handleFirstInputValueChange = _this.handleInputValueChange.bind(_this, 0);
_this.handleSecondInputValueChange = _this.handleInputValueChange.bind(_this, 1);
return _this;
}
/**
* Set isComponentMounted in state as the marks can only be
* rendered after rendering the main scale.
*/
_createClass(Slider, [{
key: 'componentDidMount',
value: function componentDidMount() {
this.setState({ isComponentMounted: true });
}
/**
* Updates the selected value in the local state of this component
* @param {object} nextProps
*/
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var _this2 = this;
var value = nextProps.value;
if (typeof value === 'undefined' || value.length === 0) {
value = typeof nextProps.defaultValue !== 'undefined' ? nextProps.defaultValue : nextProps.range ? [nextProps.min, nextProps.max] : nextProps.min;
} else if (nextProps.value !== this.state.value) {
value = nextProps.value;
}
if (nextProps.range) {
[0, 1].map(function (index) {
if (_this2.state.value[index] < nextProps.min) {
var _value = [].concat(_toConsumableArray(_this2.state.value));
_value[index] = nextProps.min;
}
if (_this2.state.value[index] > nextProps.max) {
var _value2 = [].concat(_toConsumableArray(_this2.state.value));
_value2[index] = nextProps.max;
}
});
} else {
if (this.state.value < nextProps.min) {
value = nextProps.min;
}
if (this.state.value > nextProps.max) {
value = nextProps.max;
}
}
if (value !== this.state.value) {
this.setState({ value: value });
}
}
/**
* Sets the reference for the slider wrapper.
* @param {object} ref
*/
/**
* Sets the reference for the handle(s).
* @param {number} index
* @param {object} ref
*/
/**
* Called on pressing the mouse button.
* Adds global mousemove and mouseup event listeners to listen the drag event.
* In case of single value selection it updates the value in the local state
* which moves the handle to that postion. In case of range selection this cannot
* be done as there are two handles.
* @param {object} event
*/
/**
* Called on releasing the mouse button.
* Removes global mousemove and mouseup event listeners
* @param {object} event
*/
/**
* Called while dragging the mouse.
* Updates the value in the local state of the component.
*/
/**
* Adds global event listeners.
*/
/**
* Removes global event listeners.
*/
/**
* Returns the distance in pixels from the left edge of the slider to a point
* on the slider corresponding to a particular value.
* @param {number} value
* @return {number}
*/
/**
* Helper function to get the nearest marker(step) corresponding to given value
* @param {number} value
* @return {number}
*/
/**
* Returns the corresponding value on the slider of any point on the document where the
* user has clicked / dragged mouse.
* @param {number} clientX The x coordinate of the point
* @return {number}
*/
/**
* Helper function to get the marker data in the required format.
*/
/**
* Renders the scale with the steps / marks
*/
}, {
key: 'render',
value: function render() {
var _this3 = this;
return _react2.default.createElement(
'div',
null,
_react2.default.createElement(
_styles.SliderWrapper,
{
styles: this.props.styles.slider || {},
innerRef: this.setSliderRef,
onMouseDown: this.handleMouseDown
},
this.renderScale(),
this.props.range ? this.state.value.map(function (value, index) {
return _react2.default.createElement(_styles.Handle, {
key: index,
posX: _this3.getPositionX(value),
styles: _this3.props.styles.handle || {},
innerRef: function innerRef(ref) {
return _this3.setHandleRef(index, ref);
},
active: _this3.state.draggingHandleIndex === index
});
}) : _react2.default.createElement(_styles.Handle, {
posX: this.getPositionX(this.state.value),
styles: this.props.styles.handle || {},
innerRef: function innerRef(ref) {
return _this3.setHandleRef(0, ref);
},
active: this.state.draggingHandleIndex === 0
})
),
this.props.showTextField ? this.renderInput() : null
);
}
}]);
return Slider;
}(_react2.default.PureComponent);
var _initialiseProps = function _initialiseProps() {
var _this4 = this;
this.setSliderRef = function (ref) {
if (ref) {
_this4.sliderRef = ref;
}
};
this.setHandleRef = function (index, ref) {
if (ref) {
_this4.handleRefs[index] = ref;
}
};
this.handleInputValueChange = function (index, event) {
var nextValue = void 0;
var value = event.target.value;
var minValue = _this4.props.min;
var maxValue = _this4.props.max;
if (_this4.props.range) {
if (index === 0) {
maxValue = _this4.state.value[1];
} else {
minValue = _this4.state.value[0];
}
}
value = value < minValue ? minValue : value;
value = value > maxValue ? maxValue : value;
if (_this4.props.range) {
nextValue = [].concat(_toConsumableArray(_this4.state.value));
nextValue[index] = value;
} else {
value = value;
nextValue = value;
}
_this4.setState({ value: nextValue });
};
this.handleMouseDown = function (event) {
if (_this4.props.disabled) {
return;
}
if (!_this4.props.range) {
var value = _this4.getValue(event.clientX);
_this4.setState({ value: value, draggingHandleIndex: 0 });
_this4.props.onChange(value);
_this4.addGlobalEventListeners();
} else if (_this4.handleRefs.indexOf(event.target) > -1) {
_this4.setState({
draggingHandleIndex: _this4.handleRefs.indexOf(event.target)
});
_this4.addGlobalEventListeners();
} else {
var Xmin = _this4.sliderRef.getBoundingClientRect().left;
var clientPosX = event.clientX - Xmin;
var handleDistances = _this4.state.value.map(function (val) {
return Math.abs(_this4.getPositionX(val) - clientPosX);
});
var handleToMove = handleDistances.indexOf(Math.min.apply(Math, _toConsumableArray(handleDistances)));
var nextValueArray = [].concat(_toConsumableArray(_this4.state.value));
nextValueArray[handleToMove] = Math.round(_this4.getValue(event.clientX));
_this4.setState({ value: nextValueArray });
_this4.props.onChange(nextValueArray);
}
};
this.handleGlobalMouseUp = function (event) {
_this4.setState({ draggingHandleIndex: null });
_this4.removeGlobalEventListeners();
};
this.handleGlobalMouseMove = function (event) {
if (!_this4.props.range) {
var value = _this4.getValue(event.clientX);
_this4.setState({ value: value });
_this4.props.onChange(value);
} else if (_this4.state.draggingHandleIndex !== null) {
var min = _this4.props.min;
var max = _this4.props.max;
if (_this4.state.draggingHandleIndex === 0) {
max = _this4.state.value[1];
} else if (_this4.state.draggingHandleIndex === 1) {
min = _this4.state.value[0];
}
var _value3 = Math.round(_this4.getValue(event.clientX, min, max));
var nextValueArray = [].concat(_toConsumableArray(_this4.state.value));
nextValueArray[_this4.state.draggingHandleIndex] = _value3;
_this4.setState({ value: nextValueArray });
_this4.props.onChange(nextValueArray);
}
};
this.addGlobalEventListeners = function () {
document.body.addEventListener('mousemove', _this4.handleGlobalMouseMove);
document.body.addEventListener('mouseup', _this4.handleGlobalMouseUp);
};
this.removeGlobalEventListeners = function () {
document.body.removeEventListener('mousemove', _this4.handleGlobalMouseMove);
document.body.removeEventListener('mouseup', _this4.handleGlobalMouseUp);
};
this.getPositionX = function (value) {
if (_this4.sliderRef && _this4.props.max > _this4.props.min) {
var _sliderRef$getBoundin = _this4.sliderRef.getBoundingClientRect(),
Xmin = _sliderRef$getBoundin.left,
Xmax = _sliderRef$getBoundin.right;
/** In case of non linear scale simply get posX from the marker data */
if (_this4.props.nonLinear) {
var posX = void 0;
_this4.getMarkerData().map(function (data) {
if (data.value === value) {
posX = data.posX;
}
});
return posX;
/** In case of linear scale posX can be calculated via interpolation */
}
return parseInt((Xmax - Xmin) / (_this4.props.max - _this4.props.min) * (value - _this4.props.min));
}
return 0;
};
this.getNearestMarkerValue = function (value) {
var nearestValue = void 0;
var minDistance = 0;
_this4.getMarkerData().map(function (data) {
var step = data.value;
var distance = Math.abs(value - step);
if (typeof nearestValue === 'undefined' || distance < minDistance) {
nearestValue = step;
minDistance = distance;
}
});
return nearestValue;
};
this.getValue = function (clientX) {
var min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _this4.props.min;
var max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _this4.props.max;
if (_this4.sliderRef) {
var _sliderRef$getBoundin2 = _this4.sliderRef.getBoundingClientRect(),
Xmin = _sliderRef$getBoundin2.left,
Xmax = _sliderRef$getBoundin2.right;
var posX = clientX - Xmin;
var value = void 0;
if (_this4.props.nonLinear) {
/** In case of non linear scale value should be obtained from marker data */
var nearestValue = void 0,
minDistance = 0;
_this4.getMarkerData().map(function (data) {
var distance = Math.abs(data.posX - posX);
if (typeof nearestValue === 'undefined' || distance < minDistance) {
nearestValue = data.value;
minDistance = distance;
}
});
value = nearestValue;
/** In case of linear scale value can be calculated using interpolation */
} else {
value = _this4.props.min + (_this4.props.max - _this4.props.min) / (Xmax - Xmin) * posX;
}
/** Sanitize the value */
value = value > max ? max : value;
value = value < min ? min : value;
if (typeof _this4.props.steps !== 'undefined' && _this4.props.selectStepsOnly && !_this4.props.nonLinear) {
value = _this4.getNearestMarkerValue(value);
}
return value;
}
return _this4.props.min;
};
this.getMarkerData = function () {
var marks = [];
/** If steps are provided in props the use it to compute marker data */
if (_this4.props.steps) {
if (_this4.props.nonLinear) {
if (!_this4.sliderRef) {
return;
}
var stepKeys = Object.keys(_this4.props.steps).sort(function (a, b) {
return parseInt(a) - parseInt(b);
});
if (parseInt(stepKeys[0]) !== _this4.props.min) {
stepKeys = stepKeys.unshift(_this4.props.min);
}
if (parseInt(stepKeys[stepKeys.length - 1]) !== _this4.props.max) {
stepKeys.push(_this4.props.max);
}
var spaceBetweenKeys = (_this4.props.max - _this4.props.min) / (stepKeys.length - 1);
var _sliderRef$getBoundin3 = _this4.sliderRef.getBoundingClientRect(),
Xmin = _sliderRef$getBoundin3.left,
Xmax = _sliderRef$getBoundin3.right;
stepKeys.map(function (step, index) {
var posX = parseInt((Xmax - Xmin) / (_this4.props.max - _this4.props.min) * (spaceBetweenKeys * index - _this4.props.min));
marks.push({
index: marks.length,
value: parseInt(step),
posX: posX,
tooltip: _this4.props.getTooltip(_this4.props.steps[step])
});
});
} else {
Object.keys(_this4.props.steps).sort().map(function (step) {
marks.push({
index: marks.length,
value: parseInt(step),
posX: _this4.getPositionX(parseInt(step)),
tooltip: _this4.props.getTooltip(_this4.props.steps[step])
});
});
}
/** If steps is not provided than place marks at equal distance on the linear scale */
} else {
var step = Math.ceil((_this4.props.max - _this4.props.min) / 10) || 1;
var val = _this4.props.min;
while (val <= _this4.props.max) {
marks.push({
index: marks.length,
value: parseInt(step),
posX: _this4.getPositionX(val),
tooltip: _this4.props.getTooltip(val)
});
val += step;
}
}
return marks;
};
this.renderScale = function () {
var markerData = _this4.getMarkerData();
var value = _this4.state.value;
return _react2.default.createElement(
_styles.Scale,
{ styles: _this4.props.styles.scale || {} },
_this4.state.isComponentMounted ? markerData.map(function (mark) {
return _this4.props.showMarkerWithoutTooltip || mark.tooltip ? [_react2.default.createElement(_styles.Mark, {
styles: _this4.props.styles.mark || {},
posX: mark.posX
}), _react2.default.createElement(
_styles.Tooltip,
{
styles: _this4.props.styles.tooltip || {},
posX: mark.posX
},
mark.tooltip
)] : null;
}) : null,
_this4.props.range ? _react2.default.createElement(_styles.Line, {
styles: _this4.props.styles.line || {},
style: {
left: _this4.getPositionX(value[0]),
width: _this4.getPositionX(value[1]) - _this4.getPositionX(value[0])
}
}) : _react2.default.createElement(_styles.Line, {
styles: _this4.props.styles.line || {},
style: {
left: 0,
width: _this4.getPositionX(value)
}
})
);
};
this.renderInput = function () {
var value = _this4.state.value;
if (_this4.props.range) {
value = value.map(function (v) {
return parseInt(v * 100) / 100;
});
} else {
value = parseInt(value * 100) / 100;
}
return _react2.default.createElement(
_styles.InputWrapper,
null,
_this4.props.range ? [_react2.default.createElement(Input, {
value: value[0],
onChange: _this4.handleFirstInputValueChange,
type: 'number',
disabled: _this4.props.disabled
}), _react2.default.createElement(
_styles.Separator,
null,
'-'
), _react2.default.createElement(Input, {
value: value[1],
onChange: _this4.handleSecondInputValueChange,
type: 'number',
disabled: _this4.props.disabled
})] : _react2.default.createElement(Input, {
value: value,
onChange: _this4.handleFirstInputValueChange,
type: 'number',
disabled: _this4.props.disabled
})
);
};
};
Slider.propTypes = _propTypes2.default;
Slider.defaultProps = {
disabled: false,
selectStepsOnly: false,
showMarkerWithoutTooltip: true,
onChange: function onChange(val) {},
styles: {},
range: false,
min: 0,
max: 100,
getTooltip: function getTooltip(val) {
return val;
},
showTextField: false
};
exports.default = Slider;