diff --git a/components/vc-slider/src/Handle.jsx b/components/vc-slider/src/Handle.jsx
index 918ccc1e7..74fc1a8e4 100644
--- a/components/vc-slider/src/Handle.jsx
+++ b/components/vc-slider/src/Handle.jsx
@@ -1,74 +1,80 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import addEventListener from 'rc-util/lib/Dom/addEventListener';
-export default class Handle extends React.Component {
- state = {
- clickFocused: false,
- }
+import classNames from 'classnames'
+import PropTypes from '../../../_util/vue-types'
+import addEventListener from '../../../_util/Dom/addEventListener'
+import BaseMixin from '../../../_util/BaseMixin'
- componentDidMount() {
- // mouseup won't trigger if mouse moved out of handle,
- // so we listen on document here.
- this.onMouseUpListener = addEventListener(document, 'mouseup', this.handleMouseUp);
- }
-
- componentWillUnmount() {
- if (this.onMouseUpListener) {
- this.onMouseUpListener.remove();
+export default {
+ mixins: [BaseMixin],
+ props: {
+ prefixCls: PropTypes.string,
+ vertical: PropTypes.bool,
+ offset: PropTypes.number,
+ disabled: PropTypes.bool,
+ min: PropTypes.number,
+ max: PropTypes.number,
+ value: PropTypes.number,
+ tabIndex: PropTypes.number,
+ },
+ data () {
+ return {
+ clickFocused: false,
}
- }
-
- setClickFocus(focused) {
- this.setState({ clickFocused: focused });
- }
-
- handleMouseUp = () => {
- if (document.activeElement === this.handle) {
- this.setClickFocus(true);
- }
- }
-
- handleBlur = () => {
- this.setClickFocus(false);
- }
-
- handleKeyDown = () => {
- this.setClickFocus(false);
- }
-
- clickFocus() {
- this.setClickFocus(true);
- this.focus();
- }
-
- focus() {
- this.handle.focus();
- }
-
- blur() {
- this.handle.blur();
- }
-
- render() {
+ },
+ mounted () {
+ this.$nextTick(() => {
+ this.onMouseUpListener = addEventListener(document, 'mouseup', this.handleMouseUp)
+ })
+ },
+ beforeDestroy () {
+ this.$nextTick(() => {
+ if (this.onMouseUpListener) {
+ this.onMouseUpListener.remove()
+ }
+ })
+ },
+ methods: {
+ setClickFocus (focused) {
+ this.setState({ clickFocused: focused })
+ },
+ handleMouseUp () {
+ if (document.activeElement === this.$refs.handle) {
+ this.setClickFocus(true)
+ }
+ },
+ handleBlur () {
+ this.setClickFocus(false)
+ },
+ handleKeyDown () {
+ this.setClickFocus(false)
+ },
+ clickFocus () {
+ this.setClickFocus(true)
+ this.focus()
+ },
+ focus () {
+ this.$refs.handle.focus()
+ },
+ blur () {
+ this.$refs.handle.blur()
+ },
+ },
+ render () {
const {
- prefixCls, vertical, offset, style, disabled, min, max, value, tabIndex, ...restProps,
- } = this.props;
+ prefixCls, vertical, offset, disabled, min, max, value, tabIndex, ...restProps
+ } = this.$props
const className = classNames(
- this.props.className,
{
- [`${prefixCls}-handle-click-focused`]: this.state.clickFocused,
+ [`${prefixCls}-handle-click-focused`]: this.clickFocused,
}
- );
+ )
- const postionStyle = vertical ? { bottom: `${offset}%` } : { left: `${offset}%` };
+ const postionStyle = vertical ? { bottom: `${offset}%` } : { left: `${offset}%` }
const elStyle = {
- ...style,
...postionStyle,
- };
- let ariaProps = {};
+ }
+ let ariaProps = {}
if (value !== undefined) {
ariaProps = {
...ariaProps,
@@ -76,34 +82,21 @@ export default class Handle extends React.Component {
'aria-valuemax': max,
'aria-valuenow': value,
'aria-disabled': !!disabled,
- };
+ }
}
return (
(this.handle = node)}
- role="slider"
+ ref='handle'
+ role='slider'
tabIndex= {disabled ? null : (tabIndex || 0)}
{...ariaProps}
{...restProps}
- className={className}
+ class={className}
style={elStyle}
onBlur={this.handleBlur}
- onKeyDown={this.handleKeyDown}
+ onKeydown={this.handleKeyDown}
/>
- );
- }
+ )
+ },
}
-
-Handle.propTypes = {
- prefixCls: PropTypes.string,
- className: PropTypes.string,
- vertical: PropTypes.bool,
- offset: PropTypes.number,
- style: PropTypes.object,
- disabled: PropTypes.bool,
- min: PropTypes.number,
- max: PropTypes.number,
- value: PropTypes.number,
- tabIndex: PropTypes.number,
-};
diff --git a/components/vc-slider/src/Range.jsx b/components/vc-slider/src/Range.jsx
index 03876b052..7beeacf53 100644
--- a/components/vc-slider/src/Range.jsx
+++ b/components/vc-slider/src/Range.jsx
@@ -1,327 +1,308 @@
-/* eslint-disable react/prop-types */
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import shallowEqual from 'shallowequal';
-import Track from './common/Track';
-import createSlider from './common/createSlider';
-import * as utils from './utils';
+import classNames from 'classnames'
+import PropTypes from '../../../_util/vue-types'
+import BaseMixin from '../../../_util/BaseMixin'
+import { initDefaultProps, hasProp } from '../../../_util/props-util'
+import Track from './common/Track'
+import createSlider from './common/createSlider'
+import * as utils from './utils'
-class Range extends React.Component {
- static displayName = 'Range';
- static propTypes = {
- 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,
- tabIndex: PropTypes.arrayOf(PropTypes.number),
- };
-
- static defaultProps = {
+const rangeProps = {
+ 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,
+ tabIndex: PropTypes.arrayOf(PropTypes.number),
+}
+const Range = {
+ displayName: 'Range',
+ mixins: [BaseMixin],
+ props: initDefaultProps(rangeProps, {
count: 1,
allowCross: true,
pushable: false,
tabIndex: [],
- };
-
- constructor(props) {
- super(props);
-
- const { count, min, max } = props;
+ }),
+ data () {
+ const { count, min, max } = this
const initialValue = Array.apply(null, Array(count + 1))
- .map(() => min);
- const defaultValue = 'defaultValue' in props ?
- props.defaultValue : initialValue;
- const value = props.value !== undefined ?
- props.value : defaultValue;
- const bounds = value.map((v, i) => this.trimAlignValue(v, i));
- const recent = bounds[0] === max ? 0 : bounds.length - 1;
-
- this.state = {
+ .map(() => min)
+ const defaultValue = hasProp(this, 'defaultValue') ? this.defaultValue : initialValue
+ let { value } = this
+ if (value === undefined) {
+ value = defaultValue
+ }
+ const bounds = value.map((v, i) => this.trimAlignValue(v, i))
+ const recent = bounds[0] === max ? 0 : bounds.length - 1
+ return {
handle: null,
recent,
bounds,
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (!('value' in nextProps || 'min' in nextProps || 'max' in nextProps)) return;
- if (this.props.min === nextProps.min &&
- this.props.max === nextProps.max &&
- shallowEqual(this.props.value, nextProps.value)) {
- return;
}
+ },
+ watch: {
+ value: {
+ handler (val) {
+ const { min, max } = this
+ this.setChangeValue(val, min, max)
+ },
+ deep: true,
+ },
+ min (val) {
+ const { bounds, max } = this
+ this.setChangeValue(bounds, val, max)
+ },
+ max (val) {
+ const { bounds, min } = this
+ this.setChangeValue(bounds, min, val)
+ },
+ },
+ methods: {
+ setChangeValue (value, min, max) {
+ const { bounds } = this
+ const newValue = value || bounds
+ const minAmaxProps = {
+ min,
+ max,
+ }
+ const nextBounds = newValue.map((v, i) => this.trimAlignValue(v, i, minAmaxProps))
+ if (nextBounds.length === bounds.length && nextBounds.every((v, i) => v === bounds[i])) return
- const { bounds } = this.state;
- const value = nextProps.value || bounds;
- const nextBounds = value.map((v, i) => this.trimAlignValue(v, i, nextProps));
- if (nextBounds.length === bounds.length && nextBounds.every((v, i) => v === bounds[i])) return;
+ this.setState({ bounds: nextBounds })
- this.setState({ bounds: nextBounds });
+ if (bounds.some(v => utils.isValueOutOfRange(v, minAmaxProps))) {
+ const newValues = newValue.map((v) => {
+ return utils.ensureValueInRange(v, minAmaxProps)
+ })
+ this.$emit('change', newValues)
+ }
+ },
+ onChange (state) {
+ const isNotControlled = !hasProp(this, 'value')
+ if (isNotControlled) {
+ this.setState(state)
+ } else if (state.handle !== undefined) {
+ this.setState({ handle: state.handle })
+ }
- if (bounds.some(v => utils.isValueOutOfRange(v, nextProps))) {
- const newValues = value.map((v) => {
- return utils.ensureValueInRange(v, nextProps);
- });
- this.props.onChange(newValues);
- }
- }
+ const data = { ...this.$data, ...state }
+ const changedValue = data.bounds
+ this.$emit('change', changedValue)
+ },
+ onStart (position) {
+ const { bounds } = this
+ this.$emit('beforeChange', bounds)
- onChange(state) {
- const props = this.props;
- const isNotControlled = !('value' in props);
- if (isNotControlled) {
- this.setState(state);
- } else if (state.handle !== undefined) {
- this.setState({ handle: state.handle });
- }
+ const value = this.calcValueByPos(position)
- const data = { ...this.state, ...state };
- const changedValue = data.bounds;
- props.onChange(changedValue);
- }
+ const closestBound = this.getClosestBound(value)
+ this.prevMovedHandleIndex = this.getBoundNeedMoving(value, closestBound)
- onStart(position) {
- const props = this.props;
- const state = this.state;
- const bounds = this.getValue();
- props.onBeforeChange(bounds);
+ this.setState({
+ handle: this.prevMovedHandleIndex,
+ recent: this.prevMovedHandleIndex,
+ })
- const value = this.calcValueByPos(position);
- this.startValue = value;
- this.startPosition = position;
+ const prevValue = bounds[this.prevMovedHandleIndex]
+ if (value === prevValue) return
- const closestBound = this.getClosestBound(value);
- this.prevMovedHandleIndex = this.getBoundNeedMoving(value, closestBound);
+ const nextBounds = [...bounds]
+ nextBounds[this.prevMovedHandleIndex] = value
+ this.$emit('change', { bounds: nextBounds })
+ },
+ onEnd () {
+ this.removeDocumentEvents()
+ this.$emit('afterChange', this.bounds)
+ },
+ onMove (e, position) {
+ utils.pauseEvent(e)
+ const { bounds, handle } = this
+ const value = this.calcValueByPos(position)
+ const oldValue = bounds[handle]
+ if (value === oldValue) return
- this.setState({
- handle: this.prevMovedHandleIndex,
- recent: this.prevMovedHandleIndex,
- });
+ this.moveTo(value)
+ },
+ onKeyboard (e) {
+ const valueMutator = utils.getKeyboardValueMutator(e)
- const prevValue = bounds[this.prevMovedHandleIndex];
- if (value === prevValue) return;
+ if (valueMutator) {
+ utils.pauseEvent(e)
+ const { bounds, handle } = this
+ const oldValue = bounds[handle]
+ const mutatedValue = valueMutator(oldValue, this.$props)
+ const value = this.trimAlignValue(mutatedValue)
+ if (value === oldValue) return
+ const isFromKeyboardEvent = true
+ this.moveTo(value, isFromKeyboardEvent)
+ }
+ },
+ getClosestBound (value) {
+ const { bounds } = this
+ let closestBound = 0
+ for (let 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 = closestBound + 1
+ }
+ return closestBound
+ },
+ getBoundNeedMoving (value, closestBound) {
+ const { bounds, recent } = this
+ let boundNeedMoving = closestBound
+ const isAtTheSamePoint = (bounds[closestBound + 1] === bounds[closestBound])
- const nextBounds = [...state.bounds];
- nextBounds[this.prevMovedHandleIndex] = value;
- this.onChange({ bounds: nextBounds });
- }
+ if (isAtTheSamePoint && bounds[recent] === bounds[closestBound]) {
+ boundNeedMoving = recent
+ }
- onEnd = () => {
- this.removeDocumentEvents();
- this.props.onAfterChange(this.getValue());
- }
+ if (isAtTheSamePoint && (value !== bounds[closestBound + 1])) {
+ boundNeedMoving = value < bounds[closestBound + 1] ? closestBound : closestBound + 1
+ }
+ return boundNeedMoving
+ },
+ getLowerBound () {
+ return this.bounds[0]
+ },
+ getUpperBound () {
+ const { bounds } = this
+ return bounds[bounds.length - 1]
+ },
+ /**
+ * Returns an array of possible slider points, taking into account both
+ * `marks` and `step`. The result is cached.
+ */
+ getPoints () {
+ const { marks, step, min, max } = this
+ const cache = this._getPointsCache
+ if (!cache || cache.marks !== marks || cache.step !== step) {
+ const pointsObject = { ...marks }
+ if (step !== null) {
+ for (let point = min; point <= max; point += step) {
+ pointsObject[point] = point
+ }
+ }
+ const points = Object.keys(pointsObject).map(parseFloat)
+ points.sort((a, b) => a - b)
+ this._getPointsCache = { marks, step, points }
+ }
+ return this._getPointsCache.points
+ },
+ moveTo (value, isFromKeyboardEvent) {
+ const { bounds, handle } = this
+ const nextBounds = [...bounds]
+ nextBounds[handle] = value
+ let nextHandle = handle
+ if (this.pushable !== false) {
+ this.pushSurroundingHandles(nextBounds, nextHandle)
+ } else if (this.allowCross) {
+ nextBounds.sort((a, b) => a - b)
+ nextHandle = nextBounds.indexOf(value)
+ }
+ this.$emit('change', {
+ 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.setState({}, () => {
+ this.handlesRefs[nextHandle].focus()
+ })
+ }
+ },
+ pushSurroundingHandles (bounds, handle) {
+ const value = bounds[handle]
+ let { pushable: threshold } = this
+ threshold = Number(threshold)
- onMove(e, position) {
- utils.pauseEvent(e);
- const state = this.state;
+ let direction = 0
+ if (bounds[handle + 1] - value < threshold) {
+ direction = +1 // push to right
+ }
+ if (value - bounds[handle - 1] < threshold) {
+ direction = -1 // push to left
+ }
- const value = this.calcValueByPos(position);
- const oldValue = state.bounds[state.handle];
- if (value === oldValue) return;
+ if (direction === 0) { return }
- this.moveTo(value);
- }
-
- onKeyboard(e) {
- const valueMutator = utils.getKeyboardValueMutator(e);
-
- if (valueMutator) {
- utils.pauseEvent(e);
- const { state, props } = this;
- const { bounds, handle } = state;
- const oldValue = bounds[handle];
- const mutatedValue = valueMutator(oldValue, props);
- const value = this.trimAlignValue(mutatedValue);
- if (value === oldValue) return;
- const isFromKeyboardEvent = true;
- this.moveTo(value, isFromKeyboardEvent);
- }
- }
-
- getValue() {
- return this.state.bounds;
- }
-
- getClosestBound(value) {
- const { bounds } = this.state;
- let closestBound = 0;
- for (let 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 = closestBound + 1;
- }
- return closestBound;
- }
-
- getBoundNeedMoving(value, closestBound) {
- const { bounds, recent } = this.state;
- let boundNeedMoving = closestBound;
- const 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;
- }
-
- getLowerBound() {
- return this.state.bounds[0];
- }
-
- getUpperBound() {
- const { bounds } = this.state;
- return bounds[bounds.length - 1];
- }
-
- /**
- * Returns an array of possible slider points, taking into account both
- * `marks` and `step`. The result is cached.
- */
- getPoints() {
- const { marks, step, min, max } = this.props;
- const cache = this._getPointsCache;
- if (!cache || cache.marks !== marks || cache.step !== step) {
- const pointsObject = { ...marks };
- if (step !== null) {
- for (let point = min; point <= max; point += step) {
- pointsObject[point] = point;
+ const nextHandle = handle + direction
+ const 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)
+ }
+ },
+ pushHandle (bounds, handle, direction, amount) {
+ const originalValue = bounds[handle]
+ let 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
+ },
+ pushHandleOnePoint (bounds, handle, direction) {
+ const points = this.getPoints()
+ const pointIndex = points.indexOf(bounds[handle])
+ const nextPointIndex = pointIndex + direction
+ if (nextPointIndex >= points.length || nextPointIndex < 0) {
+ // reached the minimum or maximum available point, can't push anymore
+ return false
+ }
+ const nextHandle = handle + direction
+ const nextValue = points[nextPointIndex]
+ const { pushable: threshold } = this
+ const 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
+ },
+ trimAlignValue (v, handle, nextProps = {}) {
+ const mergedProps = { ...this, ...nextProps }
+ const valInRange = utils.ensureValueInRange(v, mergedProps)
+ const valNotConflict = this.ensureValueNotConflict(handle, valInRange, mergedProps)
+ return utils.ensureValuePrecision(valNotConflict, mergedProps)
+ },
+ ensureValueNotConflict (handle, val, { allowCross, pushable: thershold }) {
+ const state = this.$data || {}
+ const { bounds } = state
+ handle = handle === undefined ? state.handle : handle
+ thershold = Number(thershold)
+ /* eslint-disable eqeqeq */
+ if (!allowCross && handle != null && bounds !== undefined) {
+ if (handle > 0 && val <= (bounds[handle - 1] + thershold)) {
+ return bounds[handle - 1] + thershold
+ }
+ if (handle < bounds.length - 1 && val >= (bounds[handle + 1] - thershold)) {
+ return bounds[handle + 1] - thershold
}
}
- const points = Object.keys(pointsObject).map(parseFloat);
- points.sort((a, b) => a - b);
- this._getPointsCache = { marks, step, points };
- }
- return this._getPointsCache.points;
- }
-
- moveTo(value, isFromKeyboardEvent) {
- const { state, props } = this;
- const nextBounds = [...state.bounds];
- nextBounds[state.handle] = value;
- let nextHandle = state.handle;
- if (props.pushable !== false) {
- this.pushSurroundingHandles(nextBounds, nextHandle);
- } else if (props.allowCross) {
- nextBounds.sort((a, b) => a - b);
- nextHandle = nextBounds.indexOf(value);
- }
- this.onChange({
- 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.setState({}, () => {
- this.handlesRefs[nextHandle].focus();
- });
- }
- }
-
- pushSurroundingHandles(bounds, handle) {
- const value = bounds[handle];
- let { pushable: threshold } = this.props;
- threshold = Number(threshold);
-
- let 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; }
-
- const nextHandle = handle + direction;
- const 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);
- }
- }
-
- pushHandle(bounds, handle, direction, amount) {
- const originalValue = bounds[handle];
- let 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;
- }
-
- pushHandleOnePoint(bounds, handle, direction) {
- const points = this.getPoints();
- const pointIndex = points.indexOf(bounds[handle]);
- const nextPointIndex = pointIndex + direction;
- if (nextPointIndex >= points.length || nextPointIndex < 0) {
- // reached the minimum or maximum available point, can't push anymore
- return false;
- }
- const nextHandle = handle + direction;
- const nextValue = points[nextPointIndex];
- const { pushable: threshold } = this.props;
- const 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;
- }
-
- trimAlignValue(v, handle, nextProps = {}) {
- const mergedProps = { ...this.props, ...nextProps };
- const valInRange = utils.ensureValueInRange(v, mergedProps);
- const valNotConflict = this.ensureValueNotConflict(handle, valInRange, mergedProps);
- return utils.ensureValuePrecision(valNotConflict, mergedProps);
- }
-
- ensureValueNotConflict(handle, val, { allowCross, pushable: thershold }) {
- const state = this.state || {};
- const { bounds } = state;
- handle = handle === undefined ? state.handle : handle;
- thershold = Number(thershold);
- /* eslint-disable eqeqeq */
- if (!allowCross && handle != null && bounds !== undefined) {
- if (handle > 0 && val <= (bounds[handle - 1] + thershold)) {
- return bounds[handle - 1] + thershold;
- }
- if (handle < bounds.length - 1 && val >= (bounds[handle + 1] - thershold)) {
- return bounds[handle + 1] - thershold;
- }
- }
- /* eslint-enable eqeqeq */
- return val;
- }
-
- render() {
+ /* eslint-enable eqeqeq */
+ return val
+ },
+ },
+ render () {
const {
handle,
bounds,
- } = this.state;
- const {
prefixCls,
vertical,
included,
@@ -332,11 +313,11 @@ class Range extends React.Component {
trackStyle,
handleStyle,
tabIndex,
- } = this.props;
+ } = this
- const offsets = bounds.map(v => this.calcOffset(v));
+ const offsets = bounds.map(v => this.calcOffset(v))
- const handleClassName = `${prefixCls}-handle`;
+ const handleClassName = `${prefixCls}-handle`
const handles = bounds.map((v, i) => handleGenerator({
className: classNames({
[handleClassName]: true,
@@ -354,14 +335,14 @@ class Range extends React.Component {
disabled,
style: handleStyle[i],
ref: h => this.saveHandle(i, h),
- }));
+ }))
const tracks = bounds.slice(0, -1).map((_, index) => {
- const i = index + 1;
+ const i = index + 1
const trackClassName = classNames({
[`${prefixCls}-track`]: true,
[`${prefixCls}-track-${i}`]: true,
- });
+ })
return (
- );
- });
+ )
+ })
- return { tracks, handles };
- }
+ return { tracks, handles }
+ },
}
-export default createSlider(Range);
+export default createSlider(Range)
diff --git a/components/vc-slider/src/Slider.jsx b/components/vc-slider/src/Slider.jsx
index 41a1094ad..de836d369 100644
--- a/components/vc-slider/src/Slider.jsx
+++ b/components/vc-slider/src/Slider.jsx
@@ -1,142 +1,142 @@
-/* eslint-disable react/prop-types */
-import React from 'react'
-import PropTypes from 'prop-types'
-import warning from 'warning'
+import PropTypes from '../../../_util/vue-types'
+import warning from '../../../_util/warning'
+import BaseMixin from '../../../_util/BaseMixin'
+import { hasProp } from '../../../_util/props-util'
import Track from './common/Track'
import createSlider from './common/createSlider'
import * as utils from './utils'
-class Slider extends React.Component {
- static propTypes = {
+const Slider = {
+ mixins: [BaseMixin],
+ props: {
defaultValue: PropTypes.number,
value: PropTypes.number,
disabled: PropTypes.bool,
autoFocus: PropTypes.bool,
tabIndex: PropTypes.number,
- };
+ },
+ data () {
+ const defaultValue = this.defaultValue !== undefined
+ ? this.defaultValue : this.min
+ const value = this.value !== undefined
+ ? this.value : defaultValue
- constructor (props) {
- super(props)
-
- const defaultValue = props.defaultValue !== undefined
- ? props.defaultValue : props.min
- const value = props.value !== undefined
- ? props.value : defaultValue
-
- this.state = {
- value: this.trimAlignValue(value),
- dragging: false,
- }
if (process.env.NODE_ENV !== 'production') {
warning(
- !('minimumTrackStyle' in props),
+ !hasProp(this, 'minimumTrackStyle'),
'minimumTrackStyle will be deprecate, please use trackStyle instead.'
)
warning(
- !('maximumTrackStyle' in props),
+ !hasProp(this, 'maximumTrackStyle'),
'maximumTrackStyle will be deprecate, please use railStyle instead.'
)
}
- }
-
- componentDidMount () {
- const { autoFocus, disabled } = this.props
- if (autoFocus && !disabled) {
- this.focus()
+ return {
+ sValue: this.trimAlignValue(value),
+ dragging: false,
}
- }
+ },
+ mounted () {
+ this.$nextTick(() => {
+ const { autoFocus, disabled } = this
+ if (autoFocus && !disabled) {
+ this.focus()
+ }
+ })
+ },
+ watch: {
+ value: {
+ handler (val) {
+ const { min, max } = this
+ this.setChangeValue(val, min, max)
+ },
+ deep: true,
+ },
+ min (val) {
+ const { sValue, max } = this
+ this.setChangeValue(sValue, val, max)
+ },
+ max (val) {
+ const { sValue, min } = this
+ this.setChangeValue(sValue, min, val)
+ },
+ },
+ methods: {
+ setChangeValue (value, min, max) {
+ const minAmaxProps = {
+ min,
+ max,
+ }
+ const newValue = value !== undefined
+ ? value : this.sValue
+ const nextValue = this.trimAlignValue(newValue, minAmaxProps)
+ if (nextValue === this.sValue) return
- componentWillReceiveProps (nextProps) {
- if (!('value' in nextProps || 'min' in nextProps || 'max' in nextProps)) return
+ this.setState({ sValue: nextValue })
+ if (utils.isValueOutOfRange(newValue, minAmaxProps)) {
+ this.$emit('change', nextValue)
+ }
+ },
+ onChange (state) {
+ const isNotControlled = !hasProp(this, 'value')
+ if (isNotControlled) {
+ this.setState(state)
+ }
- const prevValue = this.state.value
- const value = nextProps.value !== undefined
- ? nextProps.value : prevValue
- const nextValue = this.trimAlignValue(value, nextProps)
- if (nextValue === prevValue) return
+ const changedValue = state.sValue
+ this.$emit('change', changedValue)
+ },
+ onStart (position) {
+ this.setState({ dragging: true })
+ const { sValue } = this
+ this.$emit('beforeChange', sValue)
- this.setState({ value: nextValue })
- if (utils.isValueOutOfRange(value, nextProps)) {
- this.props.onChange(nextValue)
- }
- }
+ const value = this.calcValueByPos(position)
- onChange (state) {
- const props = this.props
- const isNotControlled = !('value' in props)
- if (isNotControlled) {
- this.setState(state)
- }
+ if (value === sValue) return
- const changedValue = state.value
- props.onChange(changedValue)
- }
+ this.prevMovedHandleIndex = 0
- onStart (position) {
- this.setState({ dragging: true })
- const props = this.props
- const prevValue = this.getValue()
- props.onBeforeChange(prevValue)
-
- const value = this.calcValueByPos(position)
- this.startValue = value
- this.startPosition = position
-
- if (value === prevValue) return
-
- this.prevMovedHandleIndex = 0
-
- this.onChange({ value })
- }
-
- onEnd = () => {
- this.setState({ dragging: false })
- this.removeDocumentEvents()
- this.props.onAfterChange(this.getValue())
- }
-
- onMove (e, position) {
- utils.pauseEvent(e)
- const { value: oldValue } = this.state
- const value = this.calcValueByPos(position)
- if (value === oldValue) return
-
- this.onChange({ value })
- }
-
- onKeyboard (e) {
- const valueMutator = utils.getKeyboardValueMutator(e)
-
- if (valueMutator) {
+ this.onChange({ sValue: value })
+ },
+ onEnd () {
+ this.setState({ dragging: false })
+ this.removeDocumentEvents()
+ this.$emit('afterChange', this.sValue)
+ },
+ onMove (e, position) {
utils.pauseEvent(e)
- const state = this.state
- const oldValue = state.value
- const mutatedValue = valueMutator(oldValue, this.props)
- const value = this.trimAlignValue(mutatedValue)
- if (value === oldValue) return
+ const { sValue } = this
+ const value = this.calcValueByPos(position)
+ if (value === sValue) return
- this.onChange({ value })
- }
- }
+ this.onChange({ sValue: value })
+ },
+ onKeyboard (e) {
+ const valueMutator = utils.getKeyboardValueMutator(e)
- getValue () {
- return this.state.value
- }
-
- getLowerBound () {
- return this.props.min
- }
-
- getUpperBound () {
- return this.state.value
- }
-
- trimAlignValue (v, nextProps = {}) {
- const mergedProps = { ...this.props, ...nextProps }
- const val = utils.ensureValueInRange(v, mergedProps)
- return utils.ensureValuePrecision(val, mergedProps)
- }
+ if (valueMutator) {
+ utils.pauseEvent(e)
+ const { sValue } = this
+ const mutatedValue = valueMutator(sValue, this.$props)
+ const value = this.trimAlignValue(mutatedValue)
+ if (value === sValue) return
+ this.onChange({ sValue: value })
+ }
+ },
+ getLowerBound () {
+ return this.min
+ },
+ getUpperBound () {
+ return this.sValue
+ },
+ trimAlignValue (v, nextProps = {}) {
+ const mergedProps = { ...this.$props, ...nextProps }
+ const val = utils.ensureValueInRange(v, mergedProps)
+ return utils.ensureValuePrecision(val, mergedProps)
+ },
+ },
render () {
const {
prefixCls,
@@ -150,7 +150,7 @@ class Slider extends React.Component {
min,
max,
handle: handleGenerator,
- } = this.props
+ } = this
const { value, dragging } = this.state
const offset = this.calcOffset(value)
const handle = handleGenerator({
@@ -183,9 +183,8 @@ class Slider extends React.Component {
}}
/>
)
-
return { tracks: track, handles: handle }
- }
+ },
}
export default createSlider(Slider)
diff --git a/components/vc-slider/src/common/Marks.jsx b/components/vc-slider/src/common/Marks.jsx
index f869ca143..0adbcafdd 100644
--- a/components/vc-slider/src/common/Marks.jsx
+++ b/components/vc-slider/src/common/Marks.jsx
@@ -1,66 +1,71 @@
-import React from 'react'
import classNames from 'classnames'
-const Marks = ({
- className,
- vertical,
- marks,
- included,
- upperBound,
- lowerBound,
- max, min,
- onClickLabel,
-}) => {
- const marksKeys = Object.keys(marks)
- const marksCount = marksKeys.length
- const unit = marksCount > 1 ? 100 / (marksCount - 1) : 100
- const markWidth = unit * 0.9
+const Marks = {
+ functional: true,
+ render (createElement, context) {
+ const {
+ className,
+ vertical,
+ marks,
+ included,
+ upperBound,
+ lowerBound,
+ max, min,
+ } = context.props
+ const { clickLabel } = context.listeners
+ const marksKeys = Object.keys(marks)
+ const marksCount = marksKeys.length
+ const unit = marksCount > 1 ? 100 / (marksCount - 1) : 100
+ const markWidth = unit * 0.9
- const range = max - min
- const elements = marksKeys.map(parseFloat).sort((a, b) => a - b).map(point => {
- const markPoint = marks[point]
- const markPointIsObject = typeof markPoint === 'object' &&
- !React.isValidElement(markPoint)
- const markLabel = markPointIsObject ? markPoint.label : markPoint
- if (!markLabel && markLabel !== 0) {
- return null
- }
+ const range = max - min
+ const elements = marksKeys.map(parseFloat).sort((a, b) => a - b).map(point => {
+ const markPoint = marks[point]
+ // todo
+ // const markPointIsObject = typeof markPoint === 'object' &&
+ // !React.isValidElement(markPoint)
+ const markPointIsObject = typeof markPoint === 'object'
+ const markLabel = markPointIsObject ? markPoint.label : markPoint
+ if (!markLabel && markLabel !== 0) {
+ return null
+ }
- const isActive = (!included && point === upperBound) ||
- (included && point <= upperBound && point >= lowerBound)
- const markClassName = classNames({
- [`${className}-text`]: true,
- [`${className}-text-active`]: isActive,
+ const isActive = (!included && point === upperBound) ||
+ (included && point <= upperBound && point >= lowerBound)
+ const markClassName = classNames({
+ [`${className}-text`]: true,
+ [`${className}-text-active`]: isActive,
+ })
+
+ const bottomStyle = {
+ marginBottom: '-50%',
+ bottom: `${(point - min) / range * 100}%`,
+ }
+
+ const leftStyle = {
+ width: `${markWidth}%`,
+ marginLeft: `${-markWidth / 2}%`,
+ left: `${(point - min) / range * 100}%`,
+ }
+
+ const style = vertical ? bottomStyle : leftStyle
+ const markStyle = markPointIsObject
+ ? { ...style, ...markPoint.style } : style
+ return (
+
clickLabel(e, point)}
+ onTouchStart={(e) => clickLabel(e, point)}
+ >
+ {markLabel}
+
+ )
})
- const bottomStyle = {
- marginBottom: '-50%',
- bottom: `${(point - min) / range * 100}%`,
- }
-
- const leftStyle = {
- width: `${markWidth}%`,
- marginLeft: `${-markWidth / 2}%`,
- left: `${(point - min) / range * 100}%`,
- }
-
- const style = vertical ? bottomStyle : leftStyle
- const markStyle = markPointIsObject
- ? { ...style, ...markPoint.style } : style
- return (
-
onClickLabel(e, point)}
- onTouchStart={(e) => onClickLabel(e, point)}
- >
- {markLabel}
-
- )
- })
-
- return
{elements}
-};
+ return
{elements}
+ },
+}
export default Marks
diff --git a/components/vc-slider/src/common/Steps.jsx b/components/vc-slider/src/common/Steps.jsx
index 2859a9582..f9a734b4c 100644
--- a/components/vc-slider/src/common/Steps.jsx
+++ b/components/vc-slider/src/common/Steps.jsx
@@ -1,6 +1,5 @@
-import React from 'react'
import classNames from 'classnames'
-import warning from 'warning'
+import warning from '../../../_util/warning'
const calcPoints = (vertical, marks, dots, step, min, max) => {
warning(
@@ -17,28 +16,32 @@ const calcPoints = (vertical, marks, dots, step, min, max) => {
return points
}
-const Steps = ({ prefixCls, vertical, marks, dots, step, included,
- lowerBound, upperBound, max, min, dotStyle, activeDotStyle }) => {
- const range = max - min
- const elements = calcPoints(vertical, marks, dots, step, min, max).map((point) => {
- const offset = `${Math.abs(point - min) / range * 100}%`
+const Steps = {
+ functional: true,
+ render (createElement, context) {
+ const { prefixCls, vertical, marks, dots, step, included,
+ lowerBound, upperBound, max, min, dotStyle, activeDotStyle } = context.data
+ const range = max - min
+ const elements = calcPoints(vertical, marks, dots, step, min, max).map((point) => {
+ const offset = `${Math.abs(point - min) / range * 100}%`
- const isActived = (!included && point === upperBound) ||
- (included && point <= upperBound && point >= lowerBound)
- let style = vertical ? { bottom: offset, ...dotStyle } : { left: offset, ...dotStyle }
- if (isActived) {
- style = { ...style, ...activeDotStyle }
- }
+ const isActived = (!included && point === upperBound) ||
+ (included && point <= upperBound && point >= lowerBound)
+ let style = vertical ? { bottom: offset, ...dotStyle } : { left: offset, ...dotStyle }
+ if (isActived) {
+ style = { ...style, ...activeDotStyle }
+ }
- const pointClassName = classNames({
- [`${prefixCls}-dot`]: true,
- [`${prefixCls}-dot-active`]: isActived,
+ const pointClassName = classNames({
+ [`${prefixCls}-dot`]: true,
+ [`${prefixCls}-dot-active`]: isActived,
+ })
+
+ return
})
- return
- })
-
- return
{elements}
+ return
{elements}
+ },
}
export default Steps
diff --git a/components/vc-slider/src/common/createSlider.jsx b/components/vc-slider/src/common/createSlider.jsx
index 9ef8ddcbe..1fdbd0256 100644
--- a/components/vc-slider/src/common/createSlider.jsx
+++ b/components/vc-slider/src/common/createSlider.jsx
@@ -1,8 +1,8 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import addEventListener from 'rc-util/lib/Dom/addEventListener'
import classNames from 'classnames'
-import warning from 'warning'
+import PropTypes from '../../../_util/vue-types'
+import addEventListener from '../../../_util/Dom/addEventListener'
+import warning from '../../../_util/warning'
+import { initDefaultProps } from '../../../_util/props-util'
import Steps from './Steps'
import Marks from './Marks'
import Handle from '../Handle'
@@ -11,42 +11,32 @@ import * as utils from '../utils'
function noop () {}
export default function createSlider (Component) {
- return class ComponentEnhancer extends Component {
- static displayName = `ComponentEnhancer(${Component.displayName})`;
- static propTypes = {
- ...Component.propTypes,
- min: PropTypes.number,
- max: PropTypes.number,
- step: PropTypes.number,
- marks: PropTypes.object,
- included: PropTypes.bool,
- className: PropTypes.string,
- prefixCls: PropTypes.string,
- disabled: PropTypes.bool,
- children: PropTypes.any,
- onBeforeChange: PropTypes.func,
- onChange: PropTypes.func,
- onAfterChange: PropTypes.func,
- handle: PropTypes.func,
- dots: PropTypes.bool,
- vertical: PropTypes.bool,
- style: PropTypes.object,
- minimumTrackStyle: PropTypes.object, // just for compatibility, will be deperecate
- maximumTrackStyle: PropTypes.object, // just for compatibility, will be deperecate
- handleStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]),
- trackStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]),
- railStyle: PropTypes.object,
- dotStyle: PropTypes.object,
- activeDotStyle: PropTypes.object,
- autoFocus: PropTypes.bool,
- onFocus: PropTypes.func,
- onBlur: PropTypes.func,
- };
-
- static defaultProps = {
+ // const displayName = `ComponentEnhancer(${Component.displayName})`
+ const propTypes = {
+ ...Component.propTypes,
+ min: PropTypes.number,
+ max: PropTypes.number,
+ step: PropTypes.number,
+ marks: PropTypes.object,
+ included: PropTypes.bool,
+ prefixCls: PropTypes.string,
+ disabled: PropTypes.bool,
+ handle: PropTypes.func,
+ dots: PropTypes.bool,
+ vertical: PropTypes.bool,
+ minimumTrackStyle: PropTypes.object, // just for compatibility, will be deperecate
+ maximumTrackStyle: PropTypes.object, // just for compatibility, will be deperecate
+ handleStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]),
+ trackStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]),
+ railStyle: PropTypes.object,
+ dotStyle: PropTypes.object,
+ activeDotStyle: PropTypes.object,
+ autoFocus: PropTypes.bool,
+ }
+ return {
+ props: initDefaultProps(propTypes, {
...Component.defaultProps,
prefixCls: 'rc-slider',
- className: '',
min: 0,
max: 100,
step: 1,
@@ -55,9 +45,6 @@ export default function createSlider (Component) {
delete restProps.dragging
return
},
- onBeforeChange: noop,
- onChange: noop,
- onAfterChange: noop,
included: true,
disabled: false,
dots: false,
@@ -67,13 +54,10 @@ export default function createSlider (Component) {
railStyle: {},
dotStyle: {},
activeDotStyle: {},
- };
-
- constructor (props) {
- super(props)
-
+ }),
+ data () {
if (process.env.NODE_ENV !== 'production') {
- const { step, max, min } = props
+ const { step, max, min } = this
warning(
step && Math.floor(step) === step ? (max - min) % step === 0 : true,
'Slider[max] - Slider[min] (%s) should be a multiple of Slider[step] (%s)',
@@ -82,190 +66,163 @@ export default function createSlider (Component) {
)
}
this.handlesRefs = {}
- }
-
- componentWillUnmount () {
- if (super.componentWillUnmount) super.componentWillUnmount()
- this.removeDocumentEvents()
- }
-
- componentDidMount () {
- // Snapshot testing cannot handle refs, so be sure to null-check this.
- this.document = this.sliderRef && this.sliderRef.ownerDocument
- }
-
- onMouseDown = (e) => {
- if (e.button !== 0) { return }
-
- const isVertical = this.props.vertical
- let position = utils.getMousePosition(isVertical, e)
- if (!utils.isEventFromHandle(e, this.handlesRefs)) {
- this.dragOffset = 0
- } else {
- const handlePosition = utils.getHandleCenterPosition(isVertical, e.target)
- this.dragOffset = position - handlePosition
- position = handlePosition
- }
- this.removeDocumentEvents()
- this.onStart(position)
- this.addDocumentMouseEvents()
- }
-
- onTouchStart = (e) => {
- if (utils.isNotTouchEvent(e)) return
-
- const isVertical = this.props.vertical
- let position = utils.getTouchPosition(isVertical, e)
- if (!utils.isEventFromHandle(e, this.handlesRefs)) {
- this.dragOffset = 0
- } else {
- const handlePosition = utils.getHandleCenterPosition(isVertical, e.target)
- this.dragOffset = position - handlePosition
- position = handlePosition
- }
- this.onStart(position)
- this.addDocumentTouchEvents()
- utils.pauseEvent(e)
- }
-
- onFocus = (e) => {
- const { onFocus, vertical } = this.props
- if (utils.isEventFromHandle(e, this.handlesRefs)) {
- const handlePosition = utils.getHandleCenterPosition(vertical, e.target)
- this.dragOffset = 0
- this.onStart(handlePosition)
- utils.pauseEvent(e)
- if (onFocus) {
- onFocus(e)
+ return {}
+ },
+ beforeDestroy () {
+ this.$nextTick(() => {
+ // if (super.componentWillUnmount) super.componentWillUnmount()
+ this.removeDocumentEvents()
+ })
+ },
+ mounted () {
+ this.$nextTick(() => {
+ // Snapshot testing cannot handle refs, so be sure to null-check this.
+ this.document = this.$refs.sliderRef && this.$refs.sliderRef.ownerDocument
+ })
+ },
+ methods: {
+ onMouseDown (e) {
+ if (e.button !== 0) { return }
+ const isVertical = this.vertical
+ let position = utils.getMousePosition(isVertical, e)
+ if (!utils.isEventFromHandle(e, this.handlesRefs)) {
+ this.dragOffset = 0
+ } else {
+ const handlePosition = utils.getHandleCenterPosition(isVertical, e.target)
+ this.dragOffset = position - handlePosition
+ position = handlePosition
}
- }
- }
+ this.removeDocumentEvents()
+ this.onStart(position)
+ this.addDocumentMouseEvents()
+ },
+ onTouchStart (e) {
+ if (utils.isNotTouchEvent(e)) return
- onBlur = (e) => {
- const { onBlur } = this.props
- this.onEnd(e)
- if (onBlur) {
- onBlur(e)
- }
- };
+ const isVertical = this.vertical
+ let position = utils.getTouchPosition(isVertical, e)
+ if (!utils.isEventFromHandle(e, this.handlesRefs)) {
+ this.dragOffset = 0
+ } else {
+ const handlePosition = utils.getHandleCenterPosition(isVertical, e.target)
+ this.dragOffset = position - handlePosition
+ position = handlePosition
+ }
+ this.onStart(position)
+ this.addDocumentTouchEvents()
+ utils.pauseEvent(e)
+ },
+ onFocus (e) {
+ const { vertical } = this
+ if (utils.isEventFromHandle(e, this.handlesRefs)) {
+ const handlePosition = utils.getHandleCenterPosition(vertical, e.target)
+ this.dragOffset = 0
+ this.onStart(handlePosition)
+ utils.pauseEvent(e)
+ this.$emit('focus', e)
+ }
+ },
+ onBlur (e) {
+ this.onEnd(e)
+ this.$emit('blur', e)
+ },
+ addDocumentTouchEvents () {
+ // just work for Chrome iOS Safari and Android Browser
+ this.onTouchMoveListener = addEventListener(this.document, 'touchmove', this.onTouchMove)
+ this.onTouchUpListener = addEventListener(this.document, 'touchend', this.onEnd)
+ },
+ addDocumentMouseEvents () {
+ this.onMouseMoveListener = addEventListener(this.document, 'mousemove', this.onMouseMove)
+ this.onMouseUpListener = addEventListener(this.document, 'mouseup', this.onEnd)
+ },
+ removeDocumentEvents () {
+ /* eslint-disable no-unused-expressions */
+ this.onTouchMoveListener && this.onTouchMoveListener.remove()
+ this.onTouchUpListener && this.onTouchUpListener.remove()
- addDocumentTouchEvents () {
- // just work for Chrome iOS Safari and Android Browser
- this.onTouchMoveListener = addEventListener(this.document, 'touchmove', this.onTouchMove)
- this.onTouchUpListener = addEventListener(this.document, 'touchend', this.onEnd)
- }
+ this.onMouseMoveListener && this.onMouseMoveListener.remove()
+ this.onMouseUpListener && this.onMouseUpListener.remove()
+ /* eslint-enable no-unused-expressions */
+ },
+ onMouseUp () {
+ if (this.handlesRefs[this.prevMovedHandleIndex]) {
+ this.handlesRefs[this.prevMovedHandleIndex].clickFocus()
+ }
+ },
+ onMouseMove (e) {
+ if (!this.$refs.sliderRef) {
+ this.onEnd()
+ return
+ }
+ const position = utils.getMousePosition(this.vertical, e)
+ this.onMove(e, position - this.dragOffset)
+ },
+ onTouchMove (e) {
+ if (utils.isNotTouchEvent(e) || !this.$refs.sliderRef) {
+ this.onEnd()
+ return
+ }
- addDocumentMouseEvents () {
- this.onMouseMoveListener = addEventListener(this.document, 'mousemove', this.onMouseMove)
- this.onMouseUpListener = addEventListener(this.document, 'mouseup', this.onEnd)
- }
+ const position = utils.getTouchPosition(this.vertical, e)
+ this.onMove(e, position - this.dragOffset)
+ },
+ onKeyDown (e) {
+ if (this.$refs.sliderRef && utils.isEventFromHandle(e, this.handlesRefs)) {
+ this.onKeyboard(e)
+ }
+ },
+ focus () {
+ if (!this.disabled) {
+ this.handlesRefs[0].focus()
+ }
+ },
+ blur () {
+ if (!this.disabled) {
+ this.handlesRefs[0].blur()
+ }
+ },
+ getSliderStart () {
+ const slider = this.$refs.sliderRef
+ const rect = slider.getBoundingClientRect()
- removeDocumentEvents () {
- /* eslint-disable no-unused-expressions */
- this.onTouchMoveListener && this.onTouchMoveListener.remove()
- this.onTouchUpListener && this.onTouchUpListener.remove()
-
- this.onMouseMoveListener && this.onMouseMoveListener.remove()
- this.onMouseUpListener && this.onMouseUpListener.remove()
- /* eslint-enable no-unused-expressions */
- }
-
- onMouseUp = () => {
- if (this.handlesRefs[this.prevMovedHandleIndex]) {
- this.handlesRefs[this.prevMovedHandleIndex].clickFocus()
- }
- }
-
- onMouseMove = (e) => {
- if (!this.sliderRef) {
- this.onEnd()
- return;
- }
- const position = utils.getMousePosition(this.props.vertical, e)
- this.onMove(e, position - this.dragOffset)
- }
-
- onTouchMove = (e) => {
- if (utils.isNotTouchEvent(e) || !this.sliderRef) {
- this.onEnd()
- return;
- }
-
- const position = utils.getTouchPosition(this.props.vertical, e)
- this.onMove(e, position - this.dragOffset)
- }
-
- onKeyDown = (e) => {
- if (this.sliderRef && utils.isEventFromHandle(e, this.handlesRefs)) {
- this.onKeyboard(e)
- }
- }
-
- focus () {
- if (!this.props.disabled) {
- this.handlesRefs[0].focus()
- }
- }
-
- blur () {
- if (!this.props.disabled) {
- this.handlesRefs[0].blur()
- }
- }
-
- getSliderStart () {
- const slider = this.sliderRef
- const rect = slider.getBoundingClientRect()
-
- return this.props.vertical ? rect.top : rect.left
- }
-
- getSliderLength () {
- const slider = this.sliderRef
- if (!slider) {
- return 0
- }
-
- const coords = slider.getBoundingClientRect()
- return this.props.vertical ? coords.height : coords.width
- }
-
- calcValue (offset) {
- const { vertical, min, max } = this.props
- const ratio = Math.abs(Math.max(offset, 0) / this.getSliderLength())
- const value = vertical ? (1 - ratio) * (max - min) + min : ratio * (max - min) + min
- return value
- }
-
- calcValueByPos (position) {
- const pixelOffset = position - this.getSliderStart()
- const nextValue = this.trimAlignValue(this.calcValue(pixelOffset))
- return nextValue
- }
-
- calcOffset (value) {
- const { min, max } = this.props
- const ratio = (value - min) / (max - min)
- return ratio * 100
- }
-
- saveSlider = (slider) => {
- this.sliderRef = slider
- }
-
- saveHandle (index, handle) {
- this.handlesRefs[index] = handle
- }
-
- onClickMarkLabel = (e, value) => {
- e.stopPropagation()
- this.onChange({ value })
- }
+ return this.vertical ? rect.top : rect.left
+ },
+ getSliderLength () {
+ const slider = this.$refs.sliderRef
+ if (!slider) {
+ return 0
+ }
+ const coords = slider.getBoundingClientRect()
+ return this.vertical ? coords.height : coords.width
+ },
+ calcValue (offset) {
+ const { vertical, min, max } = this
+ const ratio = Math.abs(Math.max(offset, 0) / this.getSliderLength())
+ const value = vertical ? (1 - ratio) * (max - min) + min : ratio * (max - min) + min
+ return value
+ },
+ calcValueByPos (position) {
+ const pixelOffset = position - this.getSliderStart()
+ const nextValue = this.trimAlignValue(this.calcValue(pixelOffset))
+ return nextValue
+ },
+ calcOffset (value) {
+ const { min, max } = this.props
+ const ratio = (value - min) / (max - min)
+ return ratio * 100
+ },
+ saveHandle (index, handle) {
+ this.handlesRefs[index] = handle
+ },
+ onClickMarkLabel (e, value) {
+ e.stopPropagation()
+ this.$emit('change', { value })
+ },
+ },
render () {
const {
prefixCls,
- className,
marks,
dots,
step,
@@ -274,35 +231,46 @@ export default function createSlider (Component) {
vertical,
min,
max,
- children,
maximumTrackStyle,
- style,
railStyle,
dotStyle,
activeDotStyle,
- } = this.props
+ } = this
const { tracks, handles } = super.render()
const sliderClassName = classNames(prefixCls, {
[`${prefixCls}-with-marks`]: Object.keys(marks).length,
[`${prefixCls}-disabled`]: disabled,
[`${prefixCls}-vertical`]: vertical,
- [className]: className,
})
+ const markProps = {
+ props: {
+ vertical,
+ marks,
+ included,
+ lowerBound: this.getLowerBound(),
+ upperBound: this.getUpperBound(),
+ max,
+ min,
+ className: `${prefixCls}-mark`,
+ },
+ on: {
+ clickLabel: disabled ? noop : this.onClickMarkLabel,
+ },
+ }
return (
{handles}
- {children}
+ {this.$slots.default}
)
- }
+ },
}
}
diff --git a/components/vc-slider/src/createSliderWithTooltip.jsx b/components/vc-slider/src/createSliderWithTooltip.jsx
index 002357a48..23441d6be 100644
--- a/components/vc-slider/src/createSliderWithTooltip.jsx
+++ b/components/vc-slider/src/createSliderWithTooltip.jsx
@@ -1,80 +1,91 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import Tooltip from 'rc-tooltip';
-import Handle from './Handle';
+import PropTypes from '../../../_util/vue-types'
+import BaseMixin from '../../../_util/BaseMixin'
+import Tooltip from '../../vc-tooltip'
+import Handle from './Handle'
-export default function createSliderWithTooltip(Component) {
- return class ComponentWrapper extends React.Component {
- static propTypes = {
- tipFormatter: PropTypes.func,
- handleStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]),
- tipProps: PropTypes.object,
- };
- static defaultProps = {
- tipFormatter(value) { return value; },
- handleStyle: [{}],
- tipProps: {},
- };
- constructor(props) {
- super(props);
- this.state = { visibles: {} };
- }
- handleTooltipVisibleChange = (index, visible) => {
- this.setState((prevState) => {
- return {
- visibles: {
- ...prevState.visibles,
- [index]: visible,
- },
- };
- });
- }
- handleWithTooltip = ({ value, dragging, index, disabled, ...restProps }) => {
- const {
- tipFormatter,
- tipProps,
- handleStyle,
- } = this.props;
-
- const {
- prefixCls = 'rc-slider-tooltip',
- overlay = tipFormatter(value),
- placement = 'top',
- visible = visible || false,
- ...restTooltipProps,
- } = tipProps;
-
- let handleStyleWithIndex;
- if (Array.isArray(handleStyle)) {
- handleStyleWithIndex = handleStyle[index] || handleStyle[0];
- } else {
- handleStyleWithIndex = handleStyle;
+export default function createSliderWithTooltip (Component) {
+ return {
+ mixins: [BaseMixin],
+ props: {
+ tipFormatter: PropTypes.func.def((value) => { return value }),
+ handleStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]).def([{}]),
+ tipProps: PropTypes.object.def({}),
+ },
+ data () {
+ return {
+ visibles: {},
}
+ },
+ methods: {
+ handleTooltipVisibleChange (index, visible) {
+ this.setState((prevState) => {
+ return {
+ visibles: {
+ ...prevState.visibles,
+ [index]: visible,
+ },
+ }
+ })
+ },
+ handleWithTooltip ({ value, dragging, index, disabled, ...restProps }) {
+ const {
+ tipFormatter,
+ tipProps,
+ handleStyle,
+ } = this.$props
- return (
-
+ const {
+ prefixCls = 'rc-slider-tooltip',
+ overlay = tipFormatter(value),
+ placement = 'top',
+ visible = visible || false,
+ ...restTooltipProps } = tipProps
- this.handleTooltipVisibleChange(index, true)}
- onMouseLeave={() => this.handleTooltipVisibleChange(index, false)}
- />
-
- );
- }
- render() {
- return
;
- }
- };
+ let handleStyleWithIndex
+ if (Array.isArray(handleStyle)) {
+ handleStyleWithIndex = handleStyle[index] || handleStyle[0]
+ } else {
+ handleStyleWithIndex = handleStyle
+ }
+
+ const tooltipProps = {
+ props: {
+ prefixCls,
+ overlay,
+ placement,
+ visible: (!disabled && (this.visibles[index] || dragging)) || visible,
+ ...restTooltipProps,
+ },
+ key: index,
+ }
+ const handleProps = {
+ props: {
+ value,
+ ...restProps,
+ },
+ on: {
+ mouseenter: () => this.handleTooltipVisibleChange(index, true),
+ mouseleave: () => this.handleTooltipVisibleChange(index, false),
+ },
+ style: {
+ ...handleStyleWithIndex,
+ },
+ }
+
+ return (
+
+
+
+
+ )
+ },
+ },
+ render () {
+ return
+ },
+ }
}
diff --git a/components/vc-slider/src/utils.js b/components/vc-slider/src/utils.js
index 1b2f4a036..170f2ccf1 100644
--- a/components/vc-slider/src/utils.js
+++ b/components/vc-slider/src/utils.js
@@ -1,9 +1,8 @@
-import { findDOMNode } from 'react-dom'
import keyCode from '../../_util/KeyCode'
export function isEventFromHandle (e, handles) {
return Object.keys(handles)
- .some(key => e.target === findDOMNode(handles[key]))
+ .some(key => e.target === handles[key])
}
export function isValueOutOfRange (value, { min, max }) {