feat: update vc-slider to 8.6.3

pull/309/head
wangxueliang 2018-11-28 18:28:58 +08:00
parent 6e5e8a972e
commit e825830079
8 changed files with 178 additions and 79 deletions

View File

@ -1,3 +1,3 @@
// base rc-slider 8.6.1 // base rc-slider 8.6.3
import Slider from './src/' import Slider from './src/'
export default Slider export default Slider

View File

@ -1,6 +1,8 @@
import classNames from 'classnames'
import PropTypes from '../../_util/vue-types' import PropTypes from '../../_util/vue-types'
import BaseMixin from '../../_util/BaseMixin' import BaseMixin from '../../_util/BaseMixin'
import { getOptionProps } from '../../_util/props-util' import { getOptionProps } from '../../_util/props-util'
import addEventListener from '../../_util/Dom/addEventListener'
export default { export default {
name: 'Handle', name: 'Handle',
@ -18,7 +20,42 @@ export default {
// handleFocus: PropTypes.func.def(noop), // handleFocus: PropTypes.func.def(noop),
// handleBlur: PropTypes.func.def(noop), // handleBlur: PropTypes.func.def(noop),
}, },
data () {
return {
clickFocused: false,
}
},
mounted () {
this.$nextTick(() => {
// mouseup won't trigger if mouse moved out of handle
// so we listen on document here.
this.onMouseUpListener = addEventListener(document, 'mouseup', this.handleMouseUp)
})
},
beforeDestroy () {
if (this.onMouseUpListener) {
this.onMouseUpListener.remove()
}
},
methods: { 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 () { focus () {
this.$refs.handle.focus() this.$refs.handle.focus()
}, },
@ -28,23 +65,27 @@ export default {
}, },
render () { render () {
const { const {
className, vertical, offset, disabled, min, max, value, tabIndex, prefixCls, vertical, offset, disabled, min, max, value, tabIndex,
} = getOptionProps(this) } = getOptionProps(this)
const className = classNames(
this.$props.className,
{
[`${prefixCls}-handle-click-focused`]: this.clickFocused,
}
)
const postionStyle = vertical ? { bottom: `${offset}%` } : { left: `${offset}%` } const postionStyle = vertical ? { bottom: `${offset}%` } : { left: `${offset}%` }
const elStyle = { const elStyle = {
...postionStyle, ...postionStyle,
} }
let ariaProps = {} const ariaProps = {
if (value !== undefined) { 'aria-valuemin': min,
ariaProps = { 'aria-valuemax': max,
...ariaProps, 'aria-valuenow': value,
'aria-valuemin': min, 'aria-disabled': !!disabled,
'aria-valuemax': max,
'aria-valuenow': value,
'aria-disabled': !!disabled,
}
} }
const handleProps = { const handleProps = {
attrs: { attrs: {
role: 'slider', role: 'slider',

View File

@ -1,5 +1,4 @@
import classNames from 'classnames' import classNames from 'classnames'
import warning from 'warning'
import PropTypes from '../../_util/vue-types' import PropTypes from '../../_util/vue-types'
import BaseMixin from '../../_util/BaseMixin' import BaseMixin from '../../_util/BaseMixin'
import { initDefaultProps, hasProp } from '../../_util/props-util' import { initDefaultProps, hasProp } from '../../_util/props-util'
@ -32,7 +31,7 @@ const Range = {
}), }),
data () { data () {
const { count, min, max } = this const { count, min, max } = this
const initialValue = Array.apply(null, Array(count + 1)) const initialValue = Array(...Array(count + 1))
.map(() => min) .map(() => min)
const defaultValue = hasProp(this, 'defaultValue') ? this.defaultValue : initialValue const defaultValue = hasProp(this, 'defaultValue') ? this.defaultValue : initialValue
let { value } = this let { value } = this
@ -78,7 +77,10 @@ const Range = {
this.setState({ bounds: nextBounds }) this.setState({ bounds: nextBounds })
if (bounds.some(v => utils.isValueOutOfRange(v, minAmaxProps))) { if (bounds.some(v => utils.isValueOutOfRange(v, minAmaxProps))) {
this.$emit('change', nextBounds) const newValues = value.map((v) => {
return utils.ensureValueInRange(v, minAmaxProps)
})
this.$emit('change', newValues)
} }
}, },
onChange (state) { onChange (state) {
@ -102,48 +104,46 @@ const Range = {
this.startPosition = position this.startPosition = position
const closestBound = this.getClosestBound(value) const closestBound = this.getClosestBound(value)
const boundNeedMoving = this.getBoundNeedMoving(value, closestBound) this.prevMovedHandleIndex = this.getBoundNeedMoving(value, closestBound)
this.setState({ this.setState({
sHandle: boundNeedMoving, sHandle: this.prevMovedHandleIndex,
recent: boundNeedMoving, recent: this.prevMovedHandleIndex,
}) })
const prevValue = bounds[boundNeedMoving] const prevValue = bounds[this.prevMovedHandleIndex]
if (value === prevValue) return if (value === prevValue) return
const nextBounds = [...bounds] const nextBounds = [...bounds]
nextBounds[boundNeedMoving] = value nextBounds[this.prevMovedHandleIndex] = value
this.onChange({ bounds: nextBounds }) this.onChange({ bounds: nextBounds })
}, },
onEnd () { onEnd () {
this.setState({ sHandle: null }) this.setState({ sHandle: null }, this.onBlur)
this.removeDocumentEvents() this.removeDocumentEvents()
this.$emit('afterChange', this.bounds) this.$emit('afterChange', this.bounds)
}, },
onMove (e, position) { onMove (e, position) {
utils.pauseEvent(e) utils.pauseEvent(e)
const props = this.$props
const { bounds, sHandle } = this const { bounds, sHandle } = this
const value = this.calcValueByPos(position) const value = this.calcValueByPos(position)
const oldValue = bounds[sHandle] const oldValue = bounds[sHandle]
if (value === oldValue) return if (value === oldValue) return
const nextBounds = [...bounds] this.moveTo(value)
nextBounds[sHandle] = value
let nextHandle = sHandle
if (props.pushable !== false) {
this.pushSurroundingHandles(nextBounds, nextHandle)
} else if (props.allowCross) {
nextBounds.sort((a, b) => a - b)
nextHandle = nextBounds.indexOf(value)
}
this.onChange({
sHandle: nextHandle,
bounds: nextBounds,
})
}, },
onKeyboard () { onKeyboard (e) {
warning(true, 'Keyboard support is not yet supported for ranges.') const valueMutator = utils.getKeyboardValueMutator(e)
if (valueMutator) {
utils.pauseEvent(e)
const { bounds, sHandle } = this
const oldValue = bounds[sHandle]
const mutatedValue = valueMutator(oldValue, this.$props)
const value = this.trimAlignValue(mutatedValue)
if (value === oldValue) return
const isFromKeyboardEvent = true
this.moveTo(value, isFromKeyboardEvent)
}
}, },
getClosestBound (value) { getClosestBound (value) {
const { bounds } = this const { bounds } = this
@ -152,7 +152,7 @@ const Range = {
if (value > bounds[i]) { closestBound = i } if (value > bounds[i]) { closestBound = i }
} }
if (Math.abs(bounds[closestBound + 1] - value) < Math.abs(bounds[closestBound] - value)) { if (Math.abs(bounds[closestBound + 1] - value) < Math.abs(bounds[closestBound] - value)) {
closestBound = closestBound + 1 closestBound += 1
} }
return closestBound return closestBound
}, },
@ -197,6 +197,33 @@ const Range = {
} }
return this._getPointsCache.points return this._getPointsCache.points
}, },
moveTo (value, isFromKeyboardEvent) {
const nextBounds = [...this.bounds]
const { sHandle } = this
nextBounds[sHandle] = value
let nextHandle = sHandle
if (this.$props.pushable !== false) {
this.pushSurroundingHandles(nextBounds, nextHandle)
} else if (this.$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 hackbut not elegant
this.setState({}, () => {
this.handlesRefs[nextHandle].focus()
})
}
},
pushSurroundingHandles (bounds, handle) { pushSurroundingHandles (bounds, handle) {
const value = bounds[handle] const value = bounds[handle]
let { pushable: threshold } = this let { pushable: threshold } = this
@ -322,6 +349,7 @@ const Range = {
[handleClassName]: true, [handleClassName]: true,
[`${handleClassName}-${i + 1}`]: true, [`${handleClassName}-${i + 1}`]: true,
}), }),
prefixCls,
vertical, vertical,
offset: offsets[i], offset: offsets[i],
value: v, value: v,

View File

@ -98,6 +98,7 @@ const Slider = {
this.startPosition = position this.startPosition = position
if (value === sValue) return if (value === sValue) return
this.prevMovedHandleIndex = 0
this.onChange({ sValue: value }) this.onChange({ sValue: value })
}, },
onEnd () { onEnd () {
@ -170,6 +171,7 @@ const Slider = {
const offset = this.calcOffset(sValue) const offset = this.calcOffset(sValue)
const handle = handleGenerator(this.$createElement, { const handle = handleGenerator(this.$createElement, {
className: `${prefixCls}-handle`, className: `${prefixCls}-handle`,
prefixCls,
vertical, vertical,
offset, offset,
value: sValue, value: sValue,

View File

@ -11,10 +11,10 @@ const Marks = {
included, included,
upperBound, upperBound,
lowerBound, lowerBound,
max, min, max,
min,
} = context.props } = context.props
// antd const { clickLabel } = context.listeners
// const { clickLabel } = context.listeners
const marksKeys = Object.keys(marks) const marksKeys = Object.keys(marks)
const marksCount = marksKeys.length const marksCount = marksKeys.length
const unit = marksCount > 1 ? 100 / (marksCount - 1) : 100 const unit = marksCount > 1 ? 100 / (marksCount - 1) : 100
@ -56,6 +56,8 @@ const Marks = {
class={markClassName} class={markClassName}
style={markStyle} style={markStyle}
key={point} key={point}
onMousedown={(e) => clickLabel(e, point)}
onTouchstart={(e) => clickLabel(e, point)}
> >
{markLabel} {markLabel}
</span> </span>

View File

@ -8,9 +8,10 @@ const calcPoints = (vertical, marks, dots, step, min, max) => {
) )
const points = Object.keys(marks).map(parseFloat) const points = Object.keys(marks).map(parseFloat)
if (dots) { if (dots) {
for (let i = min; i <= max; i = i + step) { for (let i = min; i <= max; i += step) {
if (points.indexOf(i) >= 0) continue if (points.indexOf(i) === -1) {
points.push(i) points.push(i)
}
} }
} }
return points return points

View File

@ -80,12 +80,6 @@ export default function createSlider (Component) {
} }
return {} return {}
}, },
beforeDestroy () {
this.$nextTick(() => {
// if (super.componentWillUnmount) super.componentWillUnmount()
this.removeDocumentEvents()
})
},
mounted () { mounted () {
this.$nextTick(() => { this.$nextTick(() => {
// Snapshot testing cannot handle refs, so be sure to null-check this. // Snapshot testing cannot handle refs, so be sure to null-check this.
@ -93,6 +87,12 @@ export default function createSlider (Component) {
// this.setHandleRefs() // this.setHandleRefs()
}) })
}, },
beforeDestroy () {
this.$nextTick(() => {
// if (super.componentWillUnmount) super.componentWillUnmount()
this.removeDocumentEvents()
})
},
computed: { computed: {
handlesRefs () { handlesRefs () {
const handlesRefs = [] const handlesRefs = []
@ -152,23 +152,10 @@ export default function createSlider (Component) {
this.onEnd(e) this.onEnd(e)
this.$emit('blur', e) this.$emit('blur', e)
}, },
addDocumentTouchEvents () { onMouseUp () {
// just work for Chrome iOS Safari and Android Browser if (this.handlesRefs[this.prevMovedHandleIndex]) {
this.onTouchMoveListener = addEventListener(this.document, 'touchmove', this.onTouchMove) this.handlesRefs[this.prevMovedHandleIndex].clickFocus()
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()
this.onMouseMoveListener && this.onMouseMoveListener.remove()
this.onMouseUpListener && this.onMouseUpListener.remove()
/* eslint-enable no-unused-expressions */
}, },
onMouseMove (e) { onMouseMove (e) {
if (!this.$refs.sliderRef) { if (!this.$refs.sliderRef) {
@ -192,15 +179,9 @@ export default function createSlider (Component) {
this.onKeyboard(e) this.onKeyboard(e)
} }
}, },
focus () { onClickMarkLabel (e, value) {
if (!this.disabled) { e.stopPropagation()
this.handlesRefs[0].focus() this.onChange({ value })
}
},
blur () {
if (!this.disabled) {
this.handlesRefs[0].blur()
}
}, },
getSliderStart () { getSliderStart () {
const slider = this.$refs.sliderRef const slider = this.$refs.sliderRef
@ -217,6 +198,38 @@ export default function createSlider (Component) {
const coords = slider.getBoundingClientRect() const coords = slider.getBoundingClientRect()
return this.vertical ? coords.height : coords.width return this.vertical ? coords.height : coords.width
}, },
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()
this.onMouseMoveListener && this.onMouseMoveListener.remove()
this.onMouseUpListener && this.onMouseUpListener.remove()
/* eslint-enable no-unused-expressions */
},
focus () {
if (!this.disabled) {
this.handlesRefs[0].focus()
}
},
blur () {
if (!this.disabled) {
Object.keys(this.handlesRefs).forEach((key) => {
if (this.handlesRefs[key] && this.handlesRefs[key].blur) {
this.handlesRefs[key].blur()
}
})
}
},
calcValue (offset) { calcValue (offset) {
const { vertical, min, max } = this const { vertical, min, max } = this
const ratio = Math.abs(Math.max(offset, 0) / this.getSliderLength()) const ratio = Math.abs(Math.max(offset, 0) / this.getSliderLength())
@ -268,6 +281,9 @@ export default function createSlider (Component) {
min, min,
className: `${prefixCls}-mark`, className: `${prefixCls}-mark`,
}, },
listeners: {
clickLabel: disabled ? noop : this.onClickMarkLabel,
},
} }
return ( return (
<div <div
@ -275,6 +291,7 @@ export default function createSlider (Component) {
class={sliderClassName} class={sliderClassName}
onTouchstart={disabled ? noop : this.onTouchStart} onTouchstart={disabled ? noop : this.onTouchStart}
onMousedown={disabled ? noop : this.onMouseDown} onMousedown={disabled ? noop : this.onMouseDown}
onMouseup={disabled ? noop : this.onMouseUp}
onKeydown={disabled ? noop : this.onKeyDown} onKeydown={disabled ? noop : this.onKeyDown}
onFocus={disabled ? noop : this.onFocus} onFocus={disabled ? noop : this.onFocus}
onBlur={disabled ? noop : this.onBlur} onBlur={disabled ? noop : this.onBlur}

View File

@ -10,7 +10,7 @@ export default function createSliderWithTooltip (Component) {
props: { props: {
...Component.props, ...Component.props,
tipFormatter: PropTypes.func.def((value) => { return value }), tipFormatter: PropTypes.func.def((value) => { return value }),
handleStyle: PropTypes.arrayOf(PropTypes.object), handleStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]),
tipProps: PropTypes.object.def({}), tipProps: PropTypes.object.def({}),
}, },
data () { data () {
@ -40,8 +40,16 @@ export default function createSliderWithTooltip (Component) {
prefixCls = 'rc-slider-tooltip', prefixCls = 'rc-slider-tooltip',
overlay = tipFormatter(value), overlay = tipFormatter(value),
placement = 'top', placement = 'top',
visible = visible || false, visible = false,
...restTooltipProps } = tipProps ...restTooltipProps
} = tipProps
let handleStyleWithIndex
if (Array.isArray(handleStyle)) {
handleStyleWithIndex = handleStyle[index] || handleStyle[0]
} else {
handleStyleWithIndex = handleStyle
}
const tooltipProps = { const tooltipProps = {
props: { props: {
@ -63,7 +71,7 @@ export default function createSliderWithTooltip (Component) {
mouseleave: () => this.handleTooltipVisibleChange(index, false), mouseleave: () => this.handleTooltipVisibleChange(index, false),
}, },
style: { style: {
...handleStyle[0], ...handleStyleWithIndex,
}, },
} }