|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533 |
- import _defineProperty from 'babel-runtime/helpers/defineProperty';
- import _extends from 'babel-runtime/helpers/extends';
- import _toConsumableArray from 'babel-runtime/helpers/toConsumableArray';
- import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
- import _createClass from 'babel-runtime/helpers/createClass';
- import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
- import _inherits from 'babel-runtime/helpers/inherits';
- /* eslint-disable react/prop-types */
- import React from 'react';
- import PropTypes from 'prop-types';
- import classNames from 'classnames';
- import { polyfill } from 'react-lifecycles-compat';
- import shallowEqual from 'shallowequal';
- import Track from './common/Track';
- import createSlider from './common/createSlider';
- import * as utils from './utils';
-
- 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) {
- _inherits(Range, _React$Component);
-
- function Range(props) {
- _classCallCheck(this, Range);
-
- var _this = _possibleConstructorReturn(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, _toConsumableArray(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;
- }
-
- _createClass(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 && shallowEqual(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 = _extends({}, 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(_toConsumableArray(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 = _extends({}, 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(_toConsumableArray(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;
-
-
- 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;
- }
- return handleGenerator({
- className: classNames((_classNames = {}, _defineProperty(_classNames, handleClassName, true), _defineProperty(_classNames, handleClassName + '-' + (i + 1), true), _classNames)),
- prefixCls: prefixCls,
- vertical: vertical,
- offset: offsets[i],
- value: v,
- dragging: handle === i,
- index: i,
- tabIndex: _tabIndex,
- min: min,
- max: max,
- reverse: reverse,
- disabled: disabled,
- style: handleStyle[i],
- ref: function ref(h) {
- return _this4.saveHandle(i, h);
- }
- });
- });
-
- var tracks = bounds.slice(0, -1).map(function (_, index) {
- var _classNames2;
-
- var i = index + 1;
- var trackClassName = classNames((_classNames2 = {}, _defineProperty(_classNames2, prefixCls + '-track', true), _defineProperty(_classNames2, prefixCls + '-track-' + i, true), _classNames2));
- return React.createElement(Track, {
- 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 _extends({}, state, {
- bounds: nextBounds
- });
- }
- return null;
- }
- }]);
-
- return Range;
- }(React.Component);
-
- Range.displayName = 'Range';
- Range.propTypes = {
- autoFocus: PropTypes.bool,
- defaultValue: PropTypes.arrayOf(PropTypes.number),
- value: PropTypes.arrayOf(PropTypes.number),
- count: PropTypes.number,
- pushable: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
- allowCross: PropTypes.bool,
- disabled: PropTypes.bool,
- reverse: PropTypes.bool,
- tabIndex: PropTypes.arrayOf(PropTypes.number),
- min: PropTypes.number,
- max: PropTypes.number
- };
- Range.defaultProps = {
- count: 1,
- allowCross: true,
- pushable: false,
- tabIndex: []
- };
-
-
- polyfill(Range);
-
- export default createSlider(Range);
|