UNPKG

element-plus

Version:

A Component Library for Vue 3

1 lines 15.9 kB
{"version":3,"file":"use-slider-button.mjs","names":["clamp"],"sources":["../../../../../../../packages/components/slider/src/composables/use-slider-button.ts"],"sourcesContent":["import { computed, inject, nextTick, ref, watch } from 'vue'\nimport { clamp, debounce } from 'lodash-unified'\nimport { useEventListener } from '@vueuse/core'\nimport { EVENT_CODE, UPDATE_MODEL_EVENT } from '@element-plus/constants'\nimport { getEventCode, isNumber } from '@element-plus/utils'\nimport { sliderContextKey } from '../constants'\n\nimport type { CSSProperties, ComputedRef, Ref, SetupContext } from 'vue'\nimport type { SliderProps } from '../slider'\nimport type {\n SliderButtonEmits,\n SliderButtonInitData,\n SliderButtonProps,\n} from '../button'\nimport type { TooltipInstance } from '@element-plus/components/tooltip'\n\nconst useTooltip = (\n props: SliderButtonProps,\n formatTooltip: Ref<SliderProps['formatTooltip']>,\n showTooltip: Ref<SliderProps['showTooltip']>\n) => {\n const tooltip = ref<TooltipInstance>()\n\n const tooltipVisible = ref(false)\n\n const enableFormat = computed(() => {\n return formatTooltip.value instanceof Function\n })\n\n const formatValue = computed(() => {\n return (\n (enableFormat.value && formatTooltip.value!(props.modelValue)) ||\n props.modelValue\n )\n })\n\n const displayTooltip = debounce(() => {\n showTooltip.value && (tooltipVisible.value = true)\n }, 50)\n\n const hideTooltip = debounce(() => {\n showTooltip.value && (tooltipVisible.value = false)\n }, 50)\n\n return {\n tooltip,\n tooltipVisible,\n formatValue,\n displayTooltip,\n hideTooltip,\n }\n}\n\nexport const useSliderButton = (\n props: SliderButtonProps,\n initData: SliderButtonInitData,\n emit: SetupContext<SliderButtonEmits>['emit']\n) => {\n const {\n disabled,\n min,\n max,\n step,\n showTooltip,\n persistent,\n precision,\n sliderSize,\n formatTooltip,\n emitChange,\n resetSize,\n updateDragging,\n markList,\n } = inject(sliderContextKey)!\n\n const { tooltip, tooltipVisible, formatValue, displayTooltip, hideTooltip } =\n useTooltip(props, formatTooltip!, showTooltip)\n\n const button = ref<HTMLDivElement>()\n\n const currentPosition = computed(() => {\n return `${\n ((props.modelValue - min.value) / (max.value - min.value)) * 100\n }%`\n })\n\n const wrapperStyle: ComputedRef<CSSProperties> = computed(() => {\n return props.vertical\n ? { bottom: currentPosition.value }\n : { left: currentPosition.value }\n })\n\n const shouldMoveToMark = computed(() => {\n return step.value === 'mark' && markList.value.length > 0\n })\n\n const handleMouseEnter = () => {\n initData.hovering = true\n displayTooltip()\n }\n\n const handleMouseLeave = () => {\n initData.hovering = false\n if (!initData.dragging) {\n hideTooltip()\n }\n }\n\n const onButtonDown = (event: MouseEvent | TouchEvent) => {\n if (disabled.value) return\n event.preventDefault()\n onDragStart(event)\n window.addEventListener('mousemove', onDragging)\n window.addEventListener('touchmove', onDragging)\n window.addEventListener('mouseup', onDragEnd)\n window.addEventListener('touchend', onDragEnd)\n window.addEventListener('contextmenu', onDragEnd)\n button.value!.focus()\n }\n\n const incrementPosition = (amount: number) => {\n if (disabled.value) return\n initData.newPosition =\n Number.parseFloat(currentPosition.value) +\n (amount / (max.value - min.value)) * 100\n setPosition(initData.newPosition)\n emitChange()\n }\n\n const moveToMark = (amount: number) => {\n if (disabled.value || !markList.value.length) return\n\n const current = props.modelValue\n const epsilon = Number.EPSILON\n const stride = Math.abs(amount)\n let target: number | undefined\n\n if (amount > 0) {\n const startIndex = markList.value.findIndex(\n (m) => m.point > current + epsilon\n )\n if (startIndex !== -1) {\n const targetIndex = Math.min(\n startIndex + stride - 1,\n markList.value.length - 1\n )\n target = markList.value[targetIndex].point\n }\n } else {\n let startIndex = -1\n for (let i = markList.value.length - 1; i >= 0; i--) {\n if (markList.value[i].point < current - epsilon) {\n startIndex = i\n break\n }\n }\n\n if (startIndex !== -1) {\n const targetIndex = Math.max(startIndex - (stride - 1), 0)\n target = markList.value[targetIndex].point\n }\n }\n\n if (target !== undefined && target !== current) {\n const newPos = ((target - min.value) / (max.value - min.value)) * 100\n setPosition(newPos)\n emitChange()\n }\n }\n\n const onLeftKeyDown = () => {\n if (shouldMoveToMark.value) {\n moveToMark(-1)\n } else if (isNumber(step.value)) {\n incrementPosition(-step.value)\n }\n }\n\n const onRightKeyDown = () => {\n if (shouldMoveToMark.value) {\n moveToMark(1)\n } else if (isNumber(step.value)) {\n incrementPosition(step.value)\n }\n }\n\n const onPageDownKeyDown = () => {\n if (shouldMoveToMark.value) {\n moveToMark(-4)\n } else if (isNumber(step.value)) {\n incrementPosition(-step.value * 4)\n }\n }\n\n const onPageUpKeyDown = () => {\n if (shouldMoveToMark.value) {\n moveToMark(4)\n } else if (isNumber(step.value)) {\n incrementPosition(step.value * 4)\n }\n }\n\n const onHomeKeyDown = () => {\n if (disabled.value) return\n setPosition(0)\n emitChange()\n }\n\n const onEndKeyDown = () => {\n if (disabled.value) return\n setPosition(100)\n emitChange()\n }\n\n const onKeyDown = (event: KeyboardEvent) => {\n const code = getEventCode(event)\n let isPreventDefault = true\n\n switch (code) {\n case EVENT_CODE.left:\n case EVENT_CODE.down:\n onLeftKeyDown()\n break\n case EVENT_CODE.right:\n case EVENT_CODE.up:\n onRightKeyDown()\n break\n case EVENT_CODE.home:\n onHomeKeyDown()\n break\n case EVENT_CODE.end:\n onEndKeyDown()\n break\n case EVENT_CODE.pageDown:\n onPageDownKeyDown()\n break\n case EVENT_CODE.pageUp:\n onPageUpKeyDown()\n break\n default:\n isPreventDefault = false\n break\n }\n\n isPreventDefault && event.preventDefault()\n }\n\n const getClientXY = (event: MouseEvent | TouchEvent) => {\n let clientX: number\n let clientY: number\n if (event.type.startsWith('touch')) {\n clientY = (event as TouchEvent).touches[0].clientY\n clientX = (event as TouchEvent).touches[0].clientX\n } else {\n clientY = (event as MouseEvent).clientY\n clientX = (event as MouseEvent).clientX\n }\n return {\n clientX,\n clientY,\n }\n }\n\n const onDragStart = (event: MouseEvent | TouchEvent) => {\n initData.dragging = true\n initData.isClick = true\n const { clientX, clientY } = getClientXY(event)\n if (props.vertical) {\n initData.startY = clientY\n } else {\n initData.startX = clientX\n }\n initData.startPosition = Number.parseFloat(currentPosition.value)\n initData.newPosition = initData.startPosition\n }\n\n const onDragging = (event: MouseEvent | TouchEvent) => {\n if (initData.dragging) {\n initData.isClick = false\n displayTooltip()\n resetSize()\n let diff: number\n const { clientX, clientY } = getClientXY(event)\n if (props.vertical) {\n initData.currentY = clientY\n diff = ((initData.startY - initData.currentY) / sliderSize.value) * 100\n } else {\n initData.currentX = clientX\n diff = ((initData.currentX - initData.startX) / sliderSize.value) * 100\n }\n initData.newPosition = initData.startPosition + diff\n setPosition(initData.newPosition)\n }\n }\n\n const onDragEnd = () => {\n if (initData.dragging) {\n /*\n * 防止在 mouseup 后立即触发 click,导致滑块有几率产生一小段位移\n * 不使用 preventDefault 是因为 mouseup 和 click 没有注册在同一个 DOM 上\n */\n setTimeout(() => {\n initData.dragging = false\n if (!initData.hovering) {\n hideTooltip()\n }\n if (!initData.isClick) {\n setPosition(initData.newPosition)\n }\n emitChange()\n }, 0)\n window.removeEventListener('mousemove', onDragging)\n window.removeEventListener('touchmove', onDragging)\n window.removeEventListener('mouseup', onDragEnd)\n window.removeEventListener('touchend', onDragEnd)\n window.removeEventListener('contextmenu', onDragEnd)\n }\n }\n\n const setPosition = async (newPosition: number) => {\n if (newPosition === null || Number.isNaN(+newPosition)) return\n\n newPosition = clamp(newPosition, 0, 100)\n let value: number\n\n if (step.value === 'mark') {\n if (markList.value.length === 0) {\n value = newPosition <= 50 ? min.value : max.value\n } else {\n const closestMark = markList.value.reduce((prev, curr) => {\n return Math.abs(curr.position - newPosition) <\n Math.abs(prev.position - newPosition)\n ? curr\n : prev\n })\n value = closestMark.point\n }\n } else {\n const fullSteps = Math.floor((max.value - min.value) / step.value)\n const fullRangePercentage =\n ((fullSteps * step.value) / (max.value - min.value)) * 100\n const threshold = fullRangePercentage + (100 - fullRangePercentage) / 2\n if (newPosition < fullRangePercentage) {\n const valueBetween = fullRangePercentage / fullSteps\n const steps = Math.round(newPosition / valueBetween)\n value = min.value + steps * step.value\n } else if (newPosition < threshold) {\n value = min.value + fullSteps * step.value\n } else {\n value = max.value\n }\n value = Number.parseFloat(value.toFixed(precision.value))\n }\n\n if (value !== props.modelValue) {\n emit(UPDATE_MODEL_EVENT, value)\n }\n\n if (!initData.dragging && props.modelValue !== initData.oldValue) {\n initData.oldValue = props.modelValue\n }\n\n await nextTick()\n initData.dragging && displayTooltip()\n tooltip.value!.updatePopper()\n }\n\n watch(\n () => initData.dragging,\n (val) => {\n updateDragging(val)\n }\n )\n\n useEventListener(button, 'touchstart', onButtonDown, { passive: false })\n\n return {\n disabled,\n button,\n tooltip,\n tooltipVisible,\n showTooltip,\n persistent,\n wrapperStyle,\n formatValue,\n handleMouseEnter,\n handleMouseLeave,\n onButtonDown,\n onKeyDown,\n setPosition,\n }\n}\n"],"mappings":"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"}