diff --git a/components/vc-slider/index.js b/components/vc-slider/index.js index b70004e1a..884c90092 100644 --- a/components/vc-slider/index.js +++ b/components/vc-slider/index.js @@ -1,4 +1,4 @@ -// base rc-slider 8.7.1 +// base rc-slider 9.7.2 import Slider from './src/'; export default Slider; diff --git a/components/vc-slider/src/Handle.jsx b/components/vc-slider/src/Handle.jsx deleted file mode 100644 index 5edfdf534..000000000 --- a/components/vc-slider/src/Handle.jsx +++ /dev/null @@ -1,151 +0,0 @@ -import { defineComponent } from 'vue'; -import classNames from '../../_util/classNames'; -import PropTypes from '../../_util/vue-types'; -import BaseMixin from '../../_util/BaseMixin'; -import { getOptionProps } from '../../_util/props-util'; -import addEventListener from '../../vc-util/Dom/addEventListener'; - -export default defineComponent({ - name: 'Handle', - mixins: [BaseMixin], - inheritAttrs: false, - props: { - prefixCls: PropTypes.string, - vertical: PropTypes.looseBool, - offset: PropTypes.number, - disabled: PropTypes.looseBool, - min: PropTypes.number, - max: PropTypes.number, - value: PropTypes.number, - tabindex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - reverse: PropTypes.looseBool, - ariaLabel: String, - ariaLabelledBy: String, - ariaValueTextFormatter: Function, - // handleFocus: PropTypes.func.def(noop), - // handleBlur: PropTypes.func.def(noop), - }, - data() { - return { - clickFocused: false, - }; - }, - mounted() { - // mouseup won't trigger if mouse moved out of handle - // so we listen on document here. - this.onMouseUpListener = addEventListener(document, 'mouseup', this.handleMouseUp); - }, - beforeUnmount() { - if (this.onMouseUpListener) { - this.onMouseUpListener.remove(); - } - }, - methods: { - setHandleRef(node) { - this.handle = node; - }, - setClickFocus(focused) { - this.setState({ clickFocused: focused }); - }, - handleMouseUp() { - if (document.activeElement === this.handle) { - this.setClickFocus(true); - } - }, - handleBlur(e) { - this.setClickFocus(false); - this.__emit('blur', e); - }, - handleKeyDown() { - this.setClickFocus(false); - }, - clickFocus() { - this.setClickFocus(true); - this.focus(); - }, - focus() { - this.handle.focus(); - }, - blur() { - this.handle.blur(); - }, - // when click can not focus in vue, use mousedown trigger focus - handleMousedown(e) { - e.preventDefault(); - this.focus(); - this.__emit('mousedown', e); - }, - }, - render() { - const { - prefixCls, - vertical, - reverse, - offset, - disabled, - min, - max, - value, - tabindex, - ariaLabel, - ariaLabelledBy, - ariaValueTextFormatter, - } = getOptionProps(this); - const className = classNames(this.$attrs.class, { - [`${prefixCls}-handle-click-focused`]: this.clickFocused, - }); - - const positionStyle = vertical - ? { - [reverse ? 'top' : 'bottom']: `${offset}%`, - [reverse ? 'bottom' : 'top']: 'auto', - transform: reverse ? null : `translateY(+50%)`, - } - : { - [reverse ? 'right' : 'left']: `${offset}%`, - [reverse ? 'left' : 'right']: 'auto', - transform: `translateX(${reverse ? '+' : '-'}50%)`, - }; - - const ariaProps = { - 'aria-valuemin': min, - 'aria-valuemax': max, - 'aria-valuenow': value, - 'aria-disabled': !!disabled, - }; - const elStyle = { - ...this.$attrs.style, - ...positionStyle, - }; - let mergedTabIndex = tabindex || 0; - if (disabled || tabindex === null) { - mergedTabIndex = null; - } - - let ariaValueText; - if (ariaValueTextFormatter) { - ariaValueText = ariaValueTextFormatter(value); - } - - const handleProps = { - ...this.$attrs, - role: 'slider', - tabindex: mergedTabIndex, - ...ariaProps, - class: className, - onBlur: this.handleBlur, - onKeydown: this.handleKeyDown, - onMousedown: this.handleMousedown, - ref: this.setHandleRef, - style: elStyle, - }; - return ( -
- ); - }, -}); diff --git a/components/vc-slider/src/Handle.tsx b/components/vc-slider/src/Handle.tsx new file mode 100644 index 000000000..efdf37fd0 --- /dev/null +++ b/components/vc-slider/src/Handle.tsx @@ -0,0 +1,265 @@ +import { computed, CSSProperties, defineComponent, ref } from 'vue'; +import classNames from '../../_util/classNames'; +import PropTypes from '../../_util/vue-types'; +import addEventListener from '../../vc-util/Dom/addEventListener'; +import { onMounted } from 'vue'; +import { onBeforeUnmount } from 'vue'; + +export default defineComponent({ + name: 'Handle', + inheritAttrs: false, + props: { + prefixCls: PropTypes.string, + vertical: PropTypes.looseBool, + offset: PropTypes.number, + disabled: PropTypes.looseBool, + min: PropTypes.number, + max: PropTypes.number, + value: PropTypes.number, + tabindex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + reverse: PropTypes.looseBool, + ariaLabel: String, + ariaLabelledBy: String, + ariaValueTextFormatter: Function, + }, + setup(props, { attrs, emit, expose }) { + const clickFocused = ref(false); + const handle = ref(); + const handleMouseUp = () => { + if (document.activeElement === handle.value) { + clickFocused.value = true; + } + }; + const handleBlur = () => { + clickFocused.value = false; + emit('blur'); + }; + const handleKeyDown = () => { + clickFocused.value = false; + }; + const focus = () => { + handle.value?.focus(); + }; + const blur = () => { + handle.value?.blur(); + }; + const clickFocus = () => { + clickFocused.value = true; + focus(); + }; + + // when click can not focus in vue, use mousedown trigger focus + const handleMousedown = (e: MouseEvent) => { + e.preventDefault(); + focus(); + emit('mousedown', e); + }; + expose({ + focus, + blur, + clickFocus, + }); + let onMouseUpListener = null; + onMounted(() => { + onMouseUpListener = addEventListener(document, 'mouseup', handleMouseUp); + }); + onBeforeUnmount(() => { + onMouseUpListener?.remove(); + }); + + const positionStyle = computed(() => { + const { vertical, offset, reverse } = props; + return vertical + ? { + [reverse ? 'top' : 'bottom']: `${offset}%`, + [reverse ? 'bottom' : 'top']: 'auto', + transform: reverse ? null : `translateY(+50%)`, + } + : { + [reverse ? 'right' : 'left']: `${offset}%`, + [reverse ? 'left' : 'right']: 'auto', + transform: `translateX(${reverse ? '+' : '-'}50%)`, + }; + }); + return () => { + const { + prefixCls, + disabled, + min, + max, + value, + tabindex, + ariaLabel, + ariaLabelledBy, + ariaValueTextFormatter, + } = props; + const className = classNames(attrs.class, { + [`${prefixCls}-handle-click-focused`]: clickFocused.value, + }); + + const ariaProps = { + 'aria-valuemin': min, + 'aria-valuemax': max, + 'aria-valuenow': value, + 'aria-disabled': !!disabled, + }; + const elStyle = { + ...(attrs.style as CSSProperties), + ...positionStyle.value, + }; + let mergedTabIndex = tabindex || 0; + if (disabled || tabindex === null) { + mergedTabIndex = null; + } + + let ariaValueText; + if (ariaValueTextFormatter) { + ariaValueText = ariaValueTextFormatter(value); + } + + const handleProps = { + ...attrs, + role: 'slider', + tabindex: mergedTabIndex, + ...ariaProps, + class: className, + onBlur: handleBlur, + onKeydown: handleKeyDown, + onMousedown: handleMousedown, + ref: handle, + style: elStyle, + }; + return ( +
+ ); + }; + }, + // data() { + // return { + // clickFocused: false, + // }; + // }, + // mounted() { + // // mouseup won't trigger if mouse moved out of handle + // // so we listen on document here. + // this.onMouseUpListener = addEventListener(document, 'mouseup', this.handleMouseUp); + // }, + // beforeUnmount() { + // if (this.onMouseUpListener) { + // this.onMouseUpListener.remove(); + // } + // }, + // methods: { + // setHandleRef(node) { + // this.handle = node; + // }, + // setClickFocus(focused) { + // this.setState({ clickFocused: focused }); + // }, + // handleMouseUp() { + // if (document.activeElement === this.handle) { + // this.setClickFocus(true); + // } + // }, + // handleBlur(e) { + // this.setClickFocus(false); + // this.__emit('blur', e); + // }, + // handleKeyDown() { + // this.setClickFocus(false); + // }, + // clickFocus() { + // this.setClickFocus(true); + // this.focus(); + // }, + // focus() { + // this.handle.focus(); + // }, + // blur() { + // this.handle.blur(); + // }, + // // when click can not focus in vue, use mousedown trigger focus + // handleMousedown(e) { + // e.preventDefault(); + // this.focus(); + // this.__emit('mousedown', e); + // }, + // }, + // render() { + // const { + // prefixCls, + // vertical, + // reverse, + // offset, + // disabled, + // min, + // max, + // value, + // tabindex, + // ariaLabel, + // ariaLabelledBy, + // ariaValueTextFormatter, + // } = getOptionProps(this); + // const className = classNames(this.$attrs.class, { + // [`${prefixCls}-handle-click-focused`]: this.clickFocused, + // }); + + // const positionStyle = vertical + // ? { + // [reverse ? 'top' : 'bottom']: `${offset}%`, + // [reverse ? 'bottom' : 'top']: 'auto', + // transform: reverse ? null : `translateY(+50%)`, + // } + // : { + // [reverse ? 'right' : 'left']: `${offset}%`, + // [reverse ? 'left' : 'right']: 'auto', + // transform: `translateX(${reverse ? '+' : '-'}50%)`, + // }; + + // const ariaProps = { + // 'aria-valuemin': min, + // 'aria-valuemax': max, + // 'aria-valuenow': value, + // 'aria-disabled': !!disabled, + // }; + // const elStyle = { + // ...this.$attrs.style, + // ...positionStyle, + // }; + // let mergedTabIndex = tabindex || 0; + // if (disabled || tabindex === null) { + // mergedTabIndex = null; + // } + + // let ariaValueText; + // if (ariaValueTextFormatter) { + // ariaValueText = ariaValueTextFormatter(value); + // } + + // const handleProps = { + // ...this.$attrs, + // role: 'slider', + // tabindex: mergedTabIndex, + // ...ariaProps, + // class: className, + // onBlur: this.handleBlur, + // onKeydown: this.handleKeyDown, + // onMousedown: this.handleMousedown, + // ref: this.setHandleRef, + // style: elStyle, + // }; + // return ( + //
+ // ); + // }, +}); diff --git a/components/vc-slider/src/Range.jsx b/components/vc-slider/src/Range.tsx similarity index 100% rename from components/vc-slider/src/Range.jsx rename to components/vc-slider/src/Range.tsx diff --git a/components/vc-slider/src/Slider.jsx b/components/vc-slider/src/Slider.tsx similarity index 100% rename from components/vc-slider/src/Slider.jsx rename to components/vc-slider/src/Slider.tsx diff --git a/components/vc-slider/src/common/Marks.jsx b/components/vc-slider/src/common/Marks.tsx similarity index 97% rename from components/vc-slider/src/common/Marks.jsx rename to components/vc-slider/src/common/Marks.tsx index ea5f3ee25..286b3c323 100644 --- a/components/vc-slider/src/common/Marks.jsx +++ b/components/vc-slider/src/common/Marks.tsx @@ -2,7 +2,7 @@ import supportsPassive from '../../../_util/supportsPassive'; import classNames from '../../../_util/classNames'; import { isValidElement } from '../../../_util/props-util'; -const Marks = (_, { attrs, slots }) => { +const Marks = (_: any, { attrs, slots }: any) => { const { class: className, vertical, diff --git a/components/vc-slider/src/common/Steps.jsx b/components/vc-slider/src/common/Steps.tsx similarity index 83% rename from components/vc-slider/src/common/Steps.jsx rename to components/vc-slider/src/common/Steps.tsx index c34be3990..289d8141c 100644 --- a/components/vc-slider/src/common/Steps.jsx +++ b/components/vc-slider/src/common/Steps.tsx @@ -1,7 +1,16 @@ +import { CSSProperties } from 'vue'; import classNames from '../../../_util/classNames'; +import { VueNode } from '../../../_util/type'; import warning from '../../../_util/warning'; -const calcPoints = (vertical, marks, dots, step, min, max) => { +const calcPoints = ( + _vertical: boolean, + marks: Record, + dots: boolean, + step: number, + min: number, + max: number, +) => { warning( dots ? step > 0 : true, 'Slider', @@ -20,7 +29,7 @@ const calcPoints = (vertical, marks, dots, step, min, max) => { return points; }; -const Steps = (_, { attrs }) => { +const Steps = (_: any, { attrs }) => { const { prefixCls, vertical, diff --git a/components/vc-slider/src/common/Track.jsx b/components/vc-slider/src/common/Track.tsx similarity index 100% rename from components/vc-slider/src/common/Track.jsx rename to components/vc-slider/src/common/Track.tsx diff --git a/components/vc-slider/src/common/createSlider.jsx b/components/vc-slider/src/common/createSlider.tsx similarity index 100% rename from components/vc-slider/src/common/createSlider.jsx rename to components/vc-slider/src/common/createSlider.tsx diff --git a/components/vc-slider/src/createSliderWithTooltip.jsx b/components/vc-slider/src/createSliderWithTooltip.jsx deleted file mode 100644 index a954186e4..000000000 --- a/components/vc-slider/src/createSliderWithTooltip.jsx +++ /dev/null @@ -1,87 +0,0 @@ -import PropTypes from '../../_util/vue-types'; -import BaseMixin from '../../_util/BaseMixin'; -import Tooltip from '../../vc-tooltip'; -import { getOptionProps } from '../../_util/props-util'; -import Handle from './Handle'; - -export default function createSliderWithTooltip(Component) { - return { - name: 'SliderTooltip', - inheritAttrs: false, - mixins: [BaseMixin, Component], - props: { - ...Component.props, - tipFormatter: PropTypes.func.def(value => { - return value; - }), - handleStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]), - tipProps: PropTypes.object.def(() => ({})), - getTooltipContainer: PropTypes.func.def(node => node.parentNode), - }, - 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, getTooltipContainer } = this.$props; - - const { - prefixCls = 'rc-slider-tooltip', - overlay = tipFormatter(value), - placement = 'top', - visible = false, - ...restTooltipProps - } = tipProps; - - let handleStyleWithIndex; - if (Array.isArray(handleStyle)) { - handleStyleWithIndex = handleStyle[index] || handleStyle[0]; - } else { - handleStyleWithIndex = handleStyle; - } - - const tooltipProps = { - ...restTooltipProps, - getTooltipContainer, - prefixCls, - overlay, - placement, - visible: (!disabled && (this.visibles[index] || dragging)) || visible, - key: index, - }; - const handleProps = { - value, - ...restProps, - onMouseenter: () => this.handleTooltipVisibleChange(index, true), - onMouseleave: () => this.handleTooltipVisibleChange(index, false), - style: handleStyleWithIndex, - }; - - return ( - - - - ); - }, - }, - render() { - const componentProps = { - ...getOptionProps(this), - handle: this.handleWithTooltip, - }; - return ; - }, - }; -} diff --git a/components/vc-slider/src/index.js b/components/vc-slider/src/index.js deleted file mode 100644 index 93f25dddd..000000000 --- a/components/vc-slider/src/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import Slider from './Slider'; -import Range from './Range'; -import Handle from './Handle'; -import createSliderWithTooltip from './createSliderWithTooltip'; - -Slider.Range = Range; -Slider.Handle = Handle; -Slider.createSliderWithTooltip = createSliderWithTooltip; -export default Slider; -export { Range, Handle, createSliderWithTooltip }; diff --git a/components/vc-slider/src/index.ts b/components/vc-slider/src/index.ts new file mode 100644 index 000000000..8434bd4de --- /dev/null +++ b/components/vc-slider/src/index.ts @@ -0,0 +1,8 @@ +import Slider from './Slider'; +import Range from './Range'; +import Handle from './Handle'; + +Slider.Range = Range; +Slider.Handle = Handle; +export default Slider; +export { Range, Handle }; diff --git a/components/vc-slider/src/utils.js b/components/vc-slider/src/utils.ts similarity index 78% rename from components/vc-slider/src/utils.js rename to components/vc-slider/src/utils.ts index 99b506658..030358f17 100644 --- a/components/vc-slider/src/utils.js +++ b/components/vc-slider/src/utils.ts @@ -1,7 +1,7 @@ import keyCode from '../../_util/KeyCode'; import { findDOMNode } from '../../_util/props-util'; -export function isEventFromHandle(e, handles) { +export function isEventFromHandle(e: { target: HTMLElement }, handles) { try { return Object.keys(handles).some( key => e.target === findDOMNode(handles[key]) || e.target === handles[key], @@ -11,15 +11,15 @@ export function isEventFromHandle(e, handles) { } } -export function isValueOutOfRange(value, { min, max }) { +export function isValueOutOfRange(value: number, { min, max }: { min?: number; max?: number }) { return value < min || value > max; } -export function isNotTouchEvent(e) { +export function isNotTouchEvent(e: TouchEvent) { return e.touches.length > 1 || (e.type.toLowerCase() === 'touchend' && e.touches.length > 0); } -export function getClosestPoint(val, { marks, step, min, max }) { +export function getClosestPoint(val: number, { marks, step, min, max }) { const points = Object.keys(marks).map(parseFloat); if (step !== null) { const baseNum = 10 ** getPrecision(step); @@ -32,7 +32,7 @@ export function getClosestPoint(val, { marks, step, min, max }) { return points[diffs.indexOf(Math.min(...diffs))]; } -export function getPrecision(step) { +export function getPrecision(step: number) { const stepString = step.toString(); let precision = 0; if (stepString.indexOf('.') >= 0) { @@ -41,7 +41,7 @@ export function getPrecision(step) { return precision; } -export function getMousePosition(vertical, e) { +export function getMousePosition(vertical: boolean, e: MouseEvent) { let zoom = 1; if (window.visualViewport) { zoom = +(window.visualViewport.width / document.body.getBoundingClientRect().width).toFixed(2); @@ -49,7 +49,7 @@ export function getMousePosition(vertical, e) { return (vertical ? e.clientY : e.pageX) / zoom; } -export function getTouchPosition(vertical, e) { +export function getTouchPosition(vertical: boolean, e: TouchEvent) { let zoom = 1; if (window.visualViewport) { zoom = +(window.visualViewport.width / document.body.getBoundingClientRect().width).toFixed(2); @@ -57,14 +57,14 @@ export function getTouchPosition(vertical, e) { return (vertical ? e.touches[0].clientY : e.touches[0].pageX) / zoom; } -export function getHandleCenterPosition(vertical, handle) { +export function getHandleCenterPosition(vertical: boolean, handle: HTMLElement) { const coords = handle.getBoundingClientRect(); return vertical ? coords.top + coords.height * 0.5 : window.pageXOffset + coords.left + coords.width * 0.5; } -export function ensureValueInRange(val, { max, min }) { +export function ensureValueInRange(val: number, { max, min }: { max?: number; min?: number }) { if (val <= min) { return min; } @@ -74,13 +74,13 @@ export function ensureValueInRange(val, { max, min }) { return val; } -export function ensureValuePrecision(val, props) { +export function ensureValuePrecision(val: number, props: any) { const { step } = props; const closestPoint = isFinite(getClosestPoint(val, props)) ? getClosestPoint(val, props) : 0; // eslint-disable-line return step === null ? closestPoint : parseFloat(closestPoint.toFixed(getPrecision(step))); } -export function pauseEvent(e) { +export function pauseEvent(e: Event) { e.stopPropagation(); e.preventDefault(); } @@ -103,7 +103,7 @@ export function calculateNextValue(func, value, props) { return value; } -export function getKeyboardValueMutator(e, vertical, reverse) { +export function getKeyboardValueMutator(e: KeyboardEvent, vertical: boolean, reverse: boolean) { const increase = 'increase'; const decrease = 'decrease'; let method = increase; @@ -122,9 +122,9 @@ export function getKeyboardValueMutator(e, vertical, reverse) { break; case keyCode.END: - return (value, props) => props.max; + return (_value, props) => props.max; case keyCode.HOME: - return (value, props) => props.min; + return (_value, props) => props.min; case keyCode.PAGE_UP: return (value, props) => value + props.step * 2; case keyCode.PAGE_DOWN: diff --git a/v2-doc b/v2-doc index 157cce105..36b2776cb 160000 --- a/v2-doc +++ b/v2-doc @@ -1 +1 @@ -Subproject commit 157cce105e1f0a369658dfb29cc802ebc09d0d93 +Subproject commit 36b2776cbf91e0db3b14d40d14879417490c56eb