571 lines
18 KiB
JavaScript
571 lines
18 KiB
JavaScript
'use strict';
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
|
||
var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
|
||
|
||
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
|
||
|
||
var _extends2 = require('babel-runtime/helpers/extends');
|
||
|
||
var _extends3 = _interopRequireDefault(_extends2);
|
||
|
||
var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
|
||
|
||
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
|
||
|
||
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
|
||
|
||
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
||
|
||
var _createClass2 = require('babel-runtime/helpers/createClass');
|
||
|
||
var _createClass3 = _interopRequireDefault(_createClass2);
|
||
|
||
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
|
||
|
||
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
|
||
|
||
var _inherits2 = require('babel-runtime/helpers/inherits');
|
||
|
||
var _inherits3 = _interopRequireDefault(_inherits2);
|
||
|
||
var _react = require('react');
|
||
|
||
var _react2 = _interopRequireDefault(_react);
|
||
|
||
var _classnames = require('classnames');
|
||
|
||
var _classnames2 = _interopRequireDefault(_classnames);
|
||
|
||
var _shallowequal = require('shallowequal');
|
||
|
||
var _shallowequal2 = _interopRequireDefault(_shallowequal);
|
||
|
||
var _Track = require('./common/Track');
|
||
|
||
var _Track2 = _interopRequireDefault(_Track);
|
||
|
||
var _createSlider = require('./common/createSlider');
|
||
|
||
var _createSlider2 = _interopRequireDefault(_createSlider);
|
||
|
||
var _utils = require('./utils');
|
||
|
||
var utils = _interopRequireWildcard(_utils);
|
||
|
||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
|
||
|
||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
|
||
|
||
var _trimAlignValue = function _trimAlignValue(_ref) {
|
||
var value = _ref.value,
|
||
handle = _ref.handle,
|
||
bounds = _ref.bounds,
|
||
props = _ref.props;
|
||
var allowCross = props.allowCross,
|
||
pushable = props.pushable;
|
||
|
||
var thershold = Number(pushable);
|
||
var valInRange = utils.ensureValueInRange(value, props);
|
||
var valNotConflict = valInRange;
|
||
if (!allowCross && handle != null && bounds !== undefined) {
|
||
if (handle > 0 && valInRange <= bounds[handle - 1] + thershold) {
|
||
valNotConflict = bounds[handle - 1] + thershold;
|
||
}
|
||
if (handle < bounds.length - 1 && valInRange >= bounds[handle + 1] - thershold) {
|
||
valNotConflict = bounds[handle + 1] - thershold;
|
||
}
|
||
}
|
||
return utils.ensureValuePrecision(valNotConflict, props);
|
||
};
|
||
|
||
var Range = function (_React$Component) {
|
||
(0, _inherits3['default'])(Range, _React$Component);
|
||
|
||
function Range(props) {
|
||
(0, _classCallCheck3['default'])(this, Range);
|
||
|
||
var _this = (0, _possibleConstructorReturn3['default'])(this, (Range.__proto__ || Object.getPrototypeOf(Range)).call(this, props));
|
||
|
||
_this.onEnd = function (force) {
|
||
var handle = _this.state.handle;
|
||
|
||
_this.removeDocumentEvents();
|
||
|
||
if (handle !== null || force) {
|
||
_this.props.onAfterChange(_this.getValue());
|
||
}
|
||
|
||
_this.setState({
|
||
handle: null
|
||
});
|
||
};
|
||
|
||
var count = props.count,
|
||
min = props.min,
|
||
max = props.max;
|
||
|
||
var initialValue = Array.apply(undefined, (0, _toConsumableArray3['default'])(Array(count + 1))).map(function () {
|
||
return min;
|
||
});
|
||
var defaultValue = 'defaultValue' in props ? props.defaultValue : initialValue;
|
||
var value = props.value !== undefined ? props.value : defaultValue;
|
||
var bounds = value.map(function (v, i) {
|
||
return _trimAlignValue({
|
||
value: v,
|
||
handle: i,
|
||
props: props
|
||
});
|
||
});
|
||
var recent = bounds[0] === max ? 0 : bounds.length - 1;
|
||
|
||
_this.state = {
|
||
handle: null,
|
||
recent: recent,
|
||
bounds: bounds
|
||
};
|
||
return _this;
|
||
}
|
||
|
||
(0, _createClass3['default'])(Range, [{
|
||
key: 'componentDidUpdate',
|
||
value: function componentDidUpdate(prevProps, prevState) {
|
||
var _this2 = this;
|
||
|
||
if (!('value' in this.props || 'min' in this.props || 'max' in this.props)) {
|
||
return;
|
||
}
|
||
if (this.props.min === prevProps.min && this.props.max === prevProps.max && (0, _shallowequal2['default'])(this.props.value, prevProps.value)) {
|
||
return;
|
||
}
|
||
var _props = this.props,
|
||
onChange = _props.onChange,
|
||
value = _props.value;
|
||
|
||
var currentValue = value || prevState.bounds;
|
||
if (currentValue.some(function (v) {
|
||
return utils.isValueOutOfRange(v, _this2.props);
|
||
})) {
|
||
var newValues = currentValue.map(function (v) {
|
||
return utils.ensureValueInRange(v, _this2.props);
|
||
});
|
||
onChange(newValues);
|
||
}
|
||
}
|
||
}, {
|
||
key: 'onChange',
|
||
value: function onChange(state) {
|
||
var props = this.props;
|
||
var isNotControlled = !('value' in props);
|
||
if (isNotControlled) {
|
||
this.setState(state);
|
||
} else {
|
||
var controlledState = {};
|
||
|
||
['handle', 'recent'].forEach(function (item) {
|
||
if (state[item] !== undefined) {
|
||
controlledState[item] = state[item];
|
||
}
|
||
});
|
||
|
||
if (Object.keys(controlledState).length) {
|
||
this.setState(controlledState);
|
||
}
|
||
}
|
||
|
||
var data = (0, _extends3['default'])({}, this.state, state);
|
||
var changedValue = data.bounds;
|
||
props.onChange(changedValue);
|
||
}
|
||
}, {
|
||
key: 'onStart',
|
||
value: function onStart(position) {
|
||
var props = this.props;
|
||
var state = this.state;
|
||
var bounds = this.getValue();
|
||
props.onBeforeChange(bounds);
|
||
|
||
var value = this.calcValueByPos(position);
|
||
this.startValue = value;
|
||
this.startPosition = position;
|
||
|
||
var closestBound = this.getClosestBound(value);
|
||
this.prevMovedHandleIndex = this.getBoundNeedMoving(value, closestBound);
|
||
|
||
this.setState({
|
||
handle: this.prevMovedHandleIndex,
|
||
recent: this.prevMovedHandleIndex
|
||
});
|
||
|
||
var prevValue = bounds[this.prevMovedHandleIndex];
|
||
if (value === prevValue) return;
|
||
|
||
var nextBounds = [].concat((0, _toConsumableArray3['default'])(state.bounds));
|
||
nextBounds[this.prevMovedHandleIndex] = value;
|
||
this.onChange({ bounds: nextBounds });
|
||
}
|
||
}, {
|
||
key: 'onMove',
|
||
value: function onMove(e, position) {
|
||
utils.pauseEvent(e);
|
||
var state = this.state;
|
||
|
||
var value = this.calcValueByPos(position);
|
||
var oldValue = state.bounds[state.handle];
|
||
if (value === oldValue) return;
|
||
|
||
this.moveTo(value);
|
||
}
|
||
}, {
|
||
key: 'onKeyboard',
|
||
value: function onKeyboard(e) {
|
||
var _props2 = this.props,
|
||
reverse = _props2.reverse,
|
||
vertical = _props2.vertical;
|
||
|
||
var valueMutator = utils.getKeyboardValueMutator(e, vertical, reverse);
|
||
|
||
if (valueMutator) {
|
||
utils.pauseEvent(e);
|
||
var state = this.state,
|
||
props = this.props;
|
||
var bounds = state.bounds,
|
||
handle = state.handle;
|
||
|
||
var oldValue = bounds[handle === null ? state.recent : handle];
|
||
var mutatedValue = valueMutator(oldValue, props);
|
||
var value = _trimAlignValue({
|
||
value: mutatedValue,
|
||
handle: handle,
|
||
bounds: state.bounds,
|
||
props: props
|
||
});
|
||
if (value === oldValue) return;
|
||
var isFromKeyboardEvent = true;
|
||
this.moveTo(value, isFromKeyboardEvent);
|
||
}
|
||
}
|
||
}, {
|
||
key: 'getValue',
|
||
value: function getValue() {
|
||
return this.state.bounds;
|
||
}
|
||
}, {
|
||
key: 'getClosestBound',
|
||
value: function getClosestBound(value) {
|
||
var bounds = this.state.bounds;
|
||
|
||
var closestBound = 0;
|
||
for (var i = 1; i < bounds.length - 1; ++i) {
|
||
if (value >= bounds[i]) {
|
||
closestBound = i;
|
||
}
|
||
}
|
||
if (Math.abs(bounds[closestBound + 1] - value) < Math.abs(bounds[closestBound] - value)) {
|
||
closestBound += 1;
|
||
}
|
||
return closestBound;
|
||
}
|
||
}, {
|
||
key: 'getBoundNeedMoving',
|
||
value: function getBoundNeedMoving(value, closestBound) {
|
||
var _state = this.state,
|
||
bounds = _state.bounds,
|
||
recent = _state.recent;
|
||
|
||
var boundNeedMoving = closestBound;
|
||
var isAtTheSamePoint = bounds[closestBound + 1] === bounds[closestBound];
|
||
|
||
if (isAtTheSamePoint && bounds[recent] === bounds[closestBound]) {
|
||
boundNeedMoving = recent;
|
||
}
|
||
|
||
if (isAtTheSamePoint && value !== bounds[closestBound + 1]) {
|
||
boundNeedMoving = value < bounds[closestBound + 1] ? closestBound : closestBound + 1;
|
||
}
|
||
return boundNeedMoving;
|
||
}
|
||
}, {
|
||
key: 'getLowerBound',
|
||
value: function getLowerBound() {
|
||
return this.state.bounds[0];
|
||
}
|
||
}, {
|
||
key: 'getUpperBound',
|
||
value: function getUpperBound() {
|
||
var bounds = this.state.bounds;
|
||
|
||
return bounds[bounds.length - 1];
|
||
}
|
||
|
||
/**
|
||
* Returns an array of possible slider points, taking into account both
|
||
* `marks` and `step`. The result is cached.
|
||
*/
|
||
|
||
}, {
|
||
key: 'getPoints',
|
||
value: function getPoints() {
|
||
var _props3 = this.props,
|
||
marks = _props3.marks,
|
||
step = _props3.step,
|
||
min = _props3.min,
|
||
max = _props3.max;
|
||
|
||
var cache = this._getPointsCache;
|
||
if (!cache || cache.marks !== marks || cache.step !== step) {
|
||
var pointsObject = (0, _extends3['default'])({}, marks);
|
||
if (step !== null) {
|
||
for (var point = min; point <= max; point += step) {
|
||
pointsObject[point] = point;
|
||
}
|
||
}
|
||
var points = Object.keys(pointsObject).map(parseFloat);
|
||
points.sort(function (a, b) {
|
||
return a - b;
|
||
});
|
||
this._getPointsCache = { marks: marks, step: step, points: points };
|
||
}
|
||
return this._getPointsCache.points;
|
||
}
|
||
}, {
|
||
key: 'moveTo',
|
||
value: function moveTo(value, isFromKeyboardEvent) {
|
||
var _this3 = this;
|
||
|
||
var state = this.state,
|
||
props = this.props;
|
||
|
||
var nextBounds = [].concat((0, _toConsumableArray3['default'])(state.bounds));
|
||
var handle = state.handle === null ? state.recent : state.handle;
|
||
nextBounds[handle] = value;
|
||
var nextHandle = handle;
|
||
if (props.pushable !== false) {
|
||
this.pushSurroundingHandles(nextBounds, nextHandle);
|
||
} else if (props.allowCross) {
|
||
nextBounds.sort(function (a, b) {
|
||
return a - b;
|
||
});
|
||
nextHandle = nextBounds.indexOf(value);
|
||
}
|
||
this.onChange({
|
||
recent: nextHandle,
|
||
handle: nextHandle,
|
||
bounds: nextBounds
|
||
});
|
||
if (isFromKeyboardEvent) {
|
||
// known problem: because setState is async,
|
||
// so trigger focus will invoke handler's onEnd and another handler's onStart too early,
|
||
// cause onBeforeChange and onAfterChange receive wrong value.
|
||
// here use setState callback to hack,but not elegant
|
||
this.props.onAfterChange(nextBounds);
|
||
this.setState({}, function () {
|
||
_this3.handlesRefs[nextHandle].focus();
|
||
});
|
||
this.onEnd();
|
||
}
|
||
}
|
||
}, {
|
||
key: 'pushSurroundingHandles',
|
||
value: function pushSurroundingHandles(bounds, handle) {
|
||
var value = bounds[handle];
|
||
var threshold = this.props.pushable;
|
||
|
||
threshold = Number(threshold);
|
||
|
||
var direction = 0;
|
||
if (bounds[handle + 1] - value < threshold) {
|
||
direction = +1; // push to right
|
||
}
|
||
if (value - bounds[handle - 1] < threshold) {
|
||
direction = -1; // push to left
|
||
}
|
||
|
||
if (direction === 0) {
|
||
return;
|
||
}
|
||
|
||
var nextHandle = handle + direction;
|
||
var diffToNext = direction * (bounds[nextHandle] - value);
|
||
if (!this.pushHandle(bounds, nextHandle, direction, threshold - diffToNext)) {
|
||
// revert to original value if pushing is impossible
|
||
bounds[handle] = bounds[nextHandle] - direction * threshold;
|
||
}
|
||
}
|
||
}, {
|
||
key: 'pushHandle',
|
||
value: function pushHandle(bounds, handle, direction, amount) {
|
||
var originalValue = bounds[handle];
|
||
var currentValue = bounds[handle];
|
||
while (direction * (currentValue - originalValue) < amount) {
|
||
if (!this.pushHandleOnePoint(bounds, handle, direction)) {
|
||
// can't push handle enough to create the needed `amount` gap, so we
|
||
// revert its position to the original value
|
||
bounds[handle] = originalValue;
|
||
return false;
|
||
}
|
||
currentValue = bounds[handle];
|
||
}
|
||
// the handle was pushed enough to create the needed `amount` gap
|
||
return true;
|
||
}
|
||
}, {
|
||
key: 'pushHandleOnePoint',
|
||
value: function pushHandleOnePoint(bounds, handle, direction) {
|
||
var points = this.getPoints();
|
||
var pointIndex = points.indexOf(bounds[handle]);
|
||
var nextPointIndex = pointIndex + direction;
|
||
if (nextPointIndex >= points.length || nextPointIndex < 0) {
|
||
// reached the minimum or maximum available point, can't push anymore
|
||
return false;
|
||
}
|
||
var nextHandle = handle + direction;
|
||
var nextValue = points[nextPointIndex];
|
||
var threshold = this.props.pushable;
|
||
|
||
var diffToNext = direction * (bounds[nextHandle] - nextValue);
|
||
if (!this.pushHandle(bounds, nextHandle, direction, threshold - diffToNext)) {
|
||
// couldn't push next handle, so we won't push this one either
|
||
return false;
|
||
}
|
||
// push the handle
|
||
bounds[handle] = nextValue;
|
||
return true;
|
||
}
|
||
}, {
|
||
key: 'trimAlignValue',
|
||
value: function trimAlignValue(value) {
|
||
var _state2 = this.state,
|
||
handle = _state2.handle,
|
||
bounds = _state2.bounds;
|
||
|
||
return _trimAlignValue({
|
||
value: value,
|
||
handle: handle,
|
||
bounds: bounds,
|
||
props: this.props
|
||
});
|
||
}
|
||
}, {
|
||
key: 'render',
|
||
value: function render() {
|
||
var _this4 = this;
|
||
|
||
var _state3 = this.state,
|
||
handle = _state3.handle,
|
||
bounds = _state3.bounds;
|
||
var _props4 = this.props,
|
||
prefixCls = _props4.prefixCls,
|
||
vertical = _props4.vertical,
|
||
included = _props4.included,
|
||
disabled = _props4.disabled,
|
||
min = _props4.min,
|
||
max = _props4.max,
|
||
reverse = _props4.reverse,
|
||
handleGenerator = _props4.handle,
|
||
trackStyle = _props4.trackStyle,
|
||
handleStyle = _props4.handleStyle,
|
||
tabIndex = _props4.tabIndex,
|
||
ariaLabelGroupForHandles = _props4.ariaLabelGroupForHandles,
|
||
ariaLabelledByGroupForHandles = _props4.ariaLabelledByGroupForHandles,
|
||
ariaValueTextFormatterGroupForHandles = _props4.ariaValueTextFormatterGroupForHandles;
|
||
|
||
|
||
var offsets = bounds.map(function (v) {
|
||
return _this4.calcOffset(v);
|
||
});
|
||
|
||
var handleClassName = prefixCls + '-handle';
|
||
var handles = bounds.map(function (v, i) {
|
||
var _classNames;
|
||
|
||
var _tabIndex = tabIndex[i] || 0;
|
||
if (disabled || tabIndex[i] === null) {
|
||
_tabIndex = null;
|
||
}
|
||
var dragging = handle === i;
|
||
return handleGenerator({
|
||
className: (0, _classnames2['default'])((_classNames = {}, (0, _defineProperty3['default'])(_classNames, handleClassName, true), (0, _defineProperty3['default'])(_classNames, handleClassName + '-' + (i + 1), true), (0, _defineProperty3['default'])(_classNames, handleClassName + '-dragging', dragging), _classNames)),
|
||
prefixCls: prefixCls,
|
||
vertical: vertical,
|
||
dragging: dragging,
|
||
offset: offsets[i],
|
||
value: v,
|
||
index: i,
|
||
tabIndex: _tabIndex,
|
||
min: min,
|
||
max: max,
|
||
reverse: reverse,
|
||
disabled: disabled,
|
||
style: handleStyle[i],
|
||
ref: function ref(h) {
|
||
return _this4.saveHandle(i, h);
|
||
},
|
||
ariaLabel: ariaLabelGroupForHandles[i],
|
||
ariaLabelledBy: ariaLabelledByGroupForHandles[i],
|
||
ariaValueTextFormatter: ariaValueTextFormatterGroupForHandles[i]
|
||
});
|
||
});
|
||
|
||
var tracks = bounds.slice(0, -1).map(function (_, index) {
|
||
var _classNames2;
|
||
|
||
var i = index + 1;
|
||
var trackClassName = (0, _classnames2['default'])((_classNames2 = {}, (0, _defineProperty3['default'])(_classNames2, prefixCls + '-track', true), (0, _defineProperty3['default'])(_classNames2, prefixCls + '-track-' + i, true), _classNames2));
|
||
return _react2['default'].createElement(_Track2['default'], {
|
||
className: trackClassName,
|
||
vertical: vertical,
|
||
reverse: reverse,
|
||
included: included,
|
||
offset: offsets[i - 1],
|
||
length: offsets[i] - offsets[i - 1],
|
||
style: trackStyle[index],
|
||
key: i
|
||
});
|
||
});
|
||
|
||
return { tracks: tracks, handles: handles };
|
||
}
|
||
}], [{
|
||
key: 'getDerivedStateFromProps',
|
||
value: function getDerivedStateFromProps(props, state) {
|
||
if ('value' in props || 'min' in props || 'max' in props) {
|
||
var value = props.value || state.bounds;
|
||
var nextBounds = value.map(function (v, i) {
|
||
return _trimAlignValue({
|
||
value: v,
|
||
handle: i,
|
||
bounds: state.bounds,
|
||
props: props
|
||
});
|
||
});
|
||
if (nextBounds.length === state.bounds.length && nextBounds.every(function (v, i) {
|
||
return v === state.bounds[i];
|
||
})) {
|
||
return null;
|
||
}
|
||
return (0, _extends3['default'])({}, state, {
|
||
bounds: nextBounds
|
||
});
|
||
}
|
||
return null;
|
||
}
|
||
}]);
|
||
return Range;
|
||
}(_react2['default'].Component);
|
||
|
||
Range.displayName = 'Range';
|
||
Range.defaultProps = {
|
||
count: 1,
|
||
allowCross: true,
|
||
pushable: false,
|
||
tabIndex: [],
|
||
ariaLabelGroupForHandles: [],
|
||
ariaLabelledByGroupForHandles: [],
|
||
ariaValueTextFormatterGroupForHandles: []
|
||
};
|
||
exports['default'] = (0, _createSlider2['default'])(Range);
|
||
module.exports = exports['default']; |