mirror of
https://gitee.com/element-plus/element-plus.git
synced 2024-12-16 02:11:48 +08:00
7ee4f44e22
trigger update:modelValue by component itself fix #2282
169 lines
4.2 KiB
TypeScript
169 lines
4.2 KiB
TypeScript
import { computed, inject, nextTick, ref, shallowRef } from 'vue'
|
|
import {
|
|
CHANGE_EVENT,
|
|
UPDATE_MODEL_EVENT,
|
|
INPUT_EVENT,
|
|
} from '@element-plus/utils/constants'
|
|
import { elFormKey, elFormItemKey } from '@element-plus/tokens'
|
|
import type { CSSProperties } from 'vue'
|
|
import type { ButtonRefs, ISliderInitData, ISliderProps } from './slider.type'
|
|
|
|
import type { ElFormContext, ElFormItemContext } from '@element-plus/tokens'
|
|
import type { Nullable } from '@element-plus/utils/types'
|
|
|
|
export const useSlide = (
|
|
props: ISliderProps,
|
|
initData: ISliderInitData,
|
|
emit
|
|
) => {
|
|
const elForm = inject(elFormKey, {} as ElFormContext)
|
|
const elFormItem = inject(elFormItemKey, {} as ElFormItemContext)
|
|
|
|
const slider = shallowRef<Nullable<HTMLElement>>(null)
|
|
|
|
const firstButton = ref(null)
|
|
|
|
const secondButton = ref(null)
|
|
|
|
const buttonRefs: ButtonRefs = {
|
|
firstButton,
|
|
secondButton,
|
|
}
|
|
|
|
const sliderDisabled = computed(() => {
|
|
return props.disabled || elForm.disabled || false
|
|
})
|
|
|
|
const minValue = computed(() => {
|
|
return Math.min(initData.firstValue, initData.secondValue)
|
|
})
|
|
|
|
const maxValue = computed(() => {
|
|
return Math.max(initData.firstValue, initData.secondValue)
|
|
})
|
|
|
|
const barSize = computed(() => {
|
|
return props.range
|
|
? `${
|
|
(100 * (maxValue.value - minValue.value)) / (props.max - props.min)
|
|
}%`
|
|
: `${
|
|
(100 * (initData.firstValue - props.min)) / (props.max - props.min)
|
|
}%`
|
|
})
|
|
|
|
const barStart = computed(() => {
|
|
return props.range
|
|
? `${(100 * (minValue.value - props.min)) / (props.max - props.min)}%`
|
|
: '0%'
|
|
})
|
|
|
|
const runwayStyle = computed<CSSProperties>(() => {
|
|
return props.vertical ? { height: props.height } : {}
|
|
})
|
|
|
|
const barStyle = computed<CSSProperties>(() => {
|
|
return props.vertical
|
|
? {
|
|
height: barSize.value,
|
|
bottom: barStart.value,
|
|
}
|
|
: {
|
|
width: barSize.value,
|
|
left: barStart.value,
|
|
}
|
|
})
|
|
|
|
const resetSize = () => {
|
|
if (slider.value) {
|
|
initData.sliderSize =
|
|
slider.value[`client${props.vertical ? 'Height' : 'Width'}`]
|
|
}
|
|
}
|
|
|
|
const setPosition = (percent: number) => {
|
|
const targetValue = props.min + (percent * (props.max - props.min)) / 100
|
|
if (!props.range) {
|
|
firstButton.value.setPosition(percent)
|
|
return
|
|
}
|
|
let buttonRefName: string
|
|
if (
|
|
Math.abs(minValue.value - targetValue) <
|
|
Math.abs(maxValue.value - targetValue)
|
|
) {
|
|
buttonRefName =
|
|
initData.firstValue < initData.secondValue
|
|
? 'firstButton'
|
|
: 'secondButton'
|
|
} else {
|
|
buttonRefName =
|
|
initData.firstValue > initData.secondValue
|
|
? 'firstButton'
|
|
: 'secondButton'
|
|
}
|
|
buttonRefs[buttonRefName].value.setPosition(percent)
|
|
}
|
|
|
|
const setFirstValue = (firstValue: number) => {
|
|
initData.firstValue = firstValue
|
|
_emit(props.range ? [minValue.value, maxValue.value] : firstValue)
|
|
}
|
|
|
|
const setSecondValue = (secondValue: number) => {
|
|
initData.secondValue = secondValue
|
|
|
|
if (props.range) {
|
|
_emit([minValue.value, maxValue.value])
|
|
}
|
|
}
|
|
|
|
const _emit = (val: number | number[]) => {
|
|
emit(UPDATE_MODEL_EVENT, val)
|
|
emit(INPUT_EVENT, val)
|
|
}
|
|
|
|
const emitChange = async () => {
|
|
await nextTick()
|
|
emit(
|
|
CHANGE_EVENT,
|
|
props.range ? [minValue.value, maxValue.value] : props.modelValue
|
|
)
|
|
}
|
|
|
|
const onSliderClick = (event: MouseEvent) => {
|
|
if (sliderDisabled.value || initData.dragging) return
|
|
resetSize()
|
|
if (props.vertical) {
|
|
const sliderOffsetBottom = slider.value.getBoundingClientRect().bottom
|
|
setPosition(
|
|
((sliderOffsetBottom - event.clientY) / initData.sliderSize) * 100
|
|
)
|
|
} else {
|
|
const sliderOffsetLeft = slider.value.getBoundingClientRect().left
|
|
setPosition(
|
|
((event.clientX - sliderOffsetLeft) / initData.sliderSize) * 100
|
|
)
|
|
}
|
|
emitChange()
|
|
}
|
|
|
|
return {
|
|
elFormItem,
|
|
slider,
|
|
firstButton,
|
|
secondButton,
|
|
sliderDisabled,
|
|
minValue,
|
|
maxValue,
|
|
runwayStyle,
|
|
barStyle,
|
|
resetSize,
|
|
setPosition,
|
|
emitChange,
|
|
onSliderClick,
|
|
setFirstValue,
|
|
setSecondValue,
|
|
}
|
|
}
|