refactor(components): [time-picker] panel-time-pick (#8115)

* Refactor `panel-time-pick` to script setup.

Co-authored-by: JeremyWuuuuu <15975785+JeremyWuuuuu@users.noreply.github.com>
This commit is contained in:
Jeremy 2022-06-06 11:53:56 +08:00 committed by GitHub
parent 364014a35a
commit 207baf89c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -37,8 +37,8 @@
</transition>
</template>
<script lang="ts">
import { computed, defineComponent, inject, ref } from 'vue'
<script lang="ts" setup>
import { computed, inject, ref } from 'vue'
import dayjs from 'dayjs'
import { EVENT_CODE } from '@element-plus/constants'
import { useLocale, useNamespace } from '@element-plus/hooks'
@ -49,179 +49,161 @@ import { getAvailableArrs, useOldValue } from './useTimePicker'
import type { Dayjs } from 'dayjs'
export default defineComponent({
components: {
TimeSpinner,
},
const props = defineProps(panelTimePickerProps)
const emit = defineEmits(['pick', 'select-range', 'set-picker-option'])
props: panelTimePickerProps,
emits: ['pick', 'select-range', 'set-picker-option'],
setup(props, ctx) {
const ns = useNamespace('time')
const { t, lang } = useLocale()
// data
const selectionRange = ref([0, 2])
const oldValue = useOldValue(props)
// computed
const transitionName = computed(() => {
return isUndefined(props.actualVisible)
? `${ns.namespace.value}-zoom-in-top`
: ''
})
const showSeconds = computed(() => {
return props.format.includes('ss')
})
const amPmMode = computed(() => {
if (props.format.includes('A')) return 'A'
if (props.format.includes('a')) return 'a'
return ''
})
// method
const isValidValue = (_date: Dayjs) => {
const parsedDate = dayjs(_date).locale(lang.value)
const result = getRangeAvailableTime(parsedDate)
return parsedDate.isSame(result)
}
const handleCancel = () => {
ctx.emit('pick', oldValue.value, false)
}
const handleConfirm = (visible = false, first = false) => {
if (first) return
ctx.emit('pick', props.parsedValue, visible)
}
const handleChange = (_date: Dayjs) => {
// visible avoids edge cases, when use scrolls during panel closing animation
if (!props.visible) {
return
}
const result = getRangeAvailableTime(_date).millisecond(0)
ctx.emit('pick', result, true)
}
const setSelectionRange = (start, end) => {
ctx.emit('select-range', start, end)
selectionRange.value = [start, end]
}
const changeSelectionRange = (step: number) => {
const list = [0, 3].concat(showSeconds.value ? [6] : [])
const mapping = ['hours', 'minutes'].concat(
showSeconds.value ? ['seconds'] : []
)
const index = list.indexOf(selectionRange.value[0])
const next = (index + step + list.length) % list.length
timePickerOptions['start_emitSelectRange'](mapping[next])
}
const handleKeydown = (event: KeyboardEvent) => {
const code = event.code
if (code === EVENT_CODE.left || code === EVENT_CODE.right) {
const step = code === EVENT_CODE.left ? -1 : 1
changeSelectionRange(step)
event.preventDefault()
return
}
if (code === EVENT_CODE.up || code === EVENT_CODE.down) {
const step = code === EVENT_CODE.up ? -1 : 1
timePickerOptions['start_scrollDown'](step)
event.preventDefault()
return
}
}
const getRangeAvailableTime = (date: Dayjs) => {
const availableMap = {
hour: getAvailableHours,
minute: getAvailableMinutes,
second: getAvailableSeconds,
}
let result = date
;['hour', 'minute', 'second'].forEach((_) => {
if (availableMap[_]) {
let availableArr
const method = availableMap[_]
if (_ === 'minute') {
availableArr = method(result.hour(), props.datetimeRole)
} else if (_ === 'second') {
availableArr = method(
result.hour(),
result.minute(),
props.datetimeRole
)
} else {
availableArr = method(props.datetimeRole)
}
if (
availableArr &&
availableArr.length &&
!availableArr.includes(result[_]())
) {
result = result[_](availableArr[0])
}
}
})
return result
}
const parseUserInput = (value: Dayjs) => {
if (!value) return null
return dayjs(value, props.format).locale(lang.value)
}
const formatToString = (value: Dayjs) => {
if (!value) return null
return value.format(props.format)
}
const getDefaultValue = () => {
return dayjs(defaultValue).locale(lang.value)
}
ctx.emit('set-picker-option', ['isValidValue', isValidValue])
ctx.emit('set-picker-option', ['formatToString', formatToString])
ctx.emit('set-picker-option', ['parseUserInput', parseUserInput])
ctx.emit('set-picker-option', ['handleKeydownInput', handleKeydown])
ctx.emit('set-picker-option', [
'getRangeAvailableTime',
getRangeAvailableTime,
])
ctx.emit('set-picker-option', ['getDefaultValue', getDefaultValue])
const timePickerOptions = {} as any
const onSetOption = (e) => {
timePickerOptions[e[0]] = e[1]
}
const pickerBase = inject('EP_PICKER_BASE') as any
const {
arrowControl,
disabledHours,
disabledMinutes,
disabledSeconds,
defaultValue,
} = pickerBase.props
const { getAvailableHours, getAvailableMinutes, getAvailableSeconds } =
getAvailableArrs(disabledHours, disabledMinutes, disabledSeconds)
return {
ns,
transitionName,
arrowControl,
onSetOption,
t,
handleConfirm,
handleChange,
setSelectionRange,
amPmMode,
showSeconds,
handleCancel,
disabledHours,
disabledMinutes,
disabledSeconds,
}
},
const ns = useNamespace('time')
const { t, lang } = useLocale()
// data
const selectionRange = ref([0, 2])
const oldValue = useOldValue(props)
// computed
const transitionName = computed(() => {
return isUndefined(props.actualVisible)
? `${ns.namespace.value}-zoom-in-top`
: ''
})
const showSeconds = computed(() => {
return props.format.includes('ss')
})
const amPmMode = computed(() => {
if (props.format.includes('A')) return 'A'
if (props.format.includes('a')) return 'a'
return ''
})
// method
const isValidValue = (_date: Dayjs) => {
const parsedDate = dayjs(_date).locale(lang.value)
const result = getRangeAvailableTime(parsedDate)
return parsedDate.isSame(result)
}
const handleCancel = () => {
emit('pick', oldValue.value, false)
}
const handleConfirm = (visible = false, first = false) => {
if (first) return
emit('pick', props.parsedValue, visible)
}
const handleChange = (_date: Dayjs) => {
// visible avoids edge cases, when use scrolls during panel closing animation
if (!props.visible) {
return
}
const result = getRangeAvailableTime(_date).millisecond(0)
emit('pick', result, true)
}
const setSelectionRange = (start: number, end: number) => {
emit('select-range', start, end)
selectionRange.value = [start, end]
}
const changeSelectionRange = (step: number) => {
const list = [0, 3].concat(showSeconds.value ? [6] : [])
const mapping = ['hours', 'minutes'].concat(
showSeconds.value ? ['seconds'] : []
)
const index = list.indexOf(selectionRange.value[0])
const next = (index + step + list.length) % list.length
timePickerOptions['start_emitSelectRange'](mapping[next])
}
const handleKeydown = (event: KeyboardEvent) => {
const code = event.code
if (code === EVENT_CODE.left || code === EVENT_CODE.right) {
const step = code === EVENT_CODE.left ? -1 : 1
changeSelectionRange(step)
event.preventDefault()
return
}
if (code === EVENT_CODE.up || code === EVENT_CODE.down) {
const step = code === EVENT_CODE.up ? -1 : 1
timePickerOptions['start_scrollDown'](step)
event.preventDefault()
return
}
}
const getRangeAvailableTime = (date: Dayjs) => {
const availableTimeGetters = {
hour: getAvailableHours,
minute: getAvailableMinutes,
second: getAvailableSeconds,
} as const
let result = date
;(['hour', 'minute', 'second'] as const).forEach((type) => {
if (availableTimeGetters[type]) {
let availableTimeSlots
const method = availableTimeGetters[type]
switch (type) {
case 'minute': {
availableTimeSlots = (method as typeof getAvailableMinutes)(
result.hour(),
props.datetimeRole
)
break
}
case 'second': {
availableTimeSlots = (method as typeof getAvailableSeconds)(
result.hour(),
result.minute(),
props.datetimeRole
)
break
}
default: {
availableTimeSlots = (method as typeof getAvailableHours)(
props.datetimeRole
)
break
}
}
if (
availableTimeSlots?.length &&
!availableTimeSlots.includes(result[type]())
) {
result = result[type](availableTimeSlots[0]) as unknown as Dayjs
}
}
})
return result
}
const parseUserInput = (value: Dayjs) => {
if (!value) return null
return dayjs(value, props.format).locale(lang.value)
}
const formatToString = (value: Dayjs) => {
if (!value) return null
return value.format(props.format)
}
const getDefaultValue = () => {
return dayjs(defaultValue).locale(lang.value)
}
emit('set-picker-option', ['isValidValue', isValidValue])
emit('set-picker-option', ['formatToString', formatToString])
emit('set-picker-option', ['parseUserInput', parseUserInput])
emit('set-picker-option', ['handleKeydownInput', handleKeydown])
emit('set-picker-option', ['getRangeAvailableTime', getRangeAvailableTime])
emit('set-picker-option', ['getDefaultValue', getDefaultValue])
const timePickerOptions = {} as any
const onSetOption = (e: [string, number]) => {
timePickerOptions[e[0]] = e[1]
}
const pickerBase = inject('EP_PICKER_BASE') as any
const {
arrowControl,
disabledHours,
disabledMinutes,
disabledSeconds,
defaultValue,
} = pickerBase.props
const { getAvailableHours, getAvailableMinutes, getAvailableSeconds } =
getAvailableArrs(disabledHours, disabledMinutes, disabledSeconds)
</script>