refactor(components): [time-picker] time-picker (#8160)

* refactor(components): [time-picker] time-picker

* Refactor `time-picker` to tsx.

* chore: refactor  to script setup

* chore: fix typing issue in `picker`

* chore: fix API exposing

Co-authored-by: JeremyWuuuuu <15975785+JeremyWuuuuu@users.noreply.github.com>
This commit is contained in:
Jeremy 2022-06-08 09:17:23 +08:00 committed by GitHub
parent 6b6c5a4a87
commit 5b233da008
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 616 additions and 624 deletions

View File

@ -49,7 +49,6 @@ export default defineComponent({
const commonPicker = ref<InstanceType<typeof CommonPicker>>()
const refProps = {
...props,
focus: (focusStartInput = true) => {
commonPicker.value?.focus(focusStartInput)
},

View File

@ -23,10 +23,10 @@
<template #default>
<el-input
v-if="!isRangeInput"
:id="id"
:id="(id as string | undefined)"
ref="inputRef"
container-role="combobox"
:model-value="displayValue"
:model-value="(displayValue as string)"
:name="name"
:size="pickerSize"
:disabled="pickerDisabled"
@ -39,7 +39,7 @@
@input="onUserInput"
@focus="handleFocusInput"
@blur="handleBlurInput"
@keydown="handleKeydownInput"
@keydown="handleKeydownInput as any"
@change="handleChange"
@mousedown="onMouseDownInput"
@mouseenter="onMouseEnter"
@ -80,7 +80,7 @@
pickerSize ? nsRange.bm('editor', pickerSize) : '',
$attrs.class,
]"
:style="$attrs.style"
:style="($attrs.style as any)"
@click="handleFocusInput"
@mousedown="onMouseDownInput"
@mouseenter="onMouseEnter"
@ -162,17 +162,8 @@
</template>
</el-tooltip>
</template>
<script lang="ts">
import {
computed,
defineComponent,
inject,
nextTick,
provide,
ref,
unref,
watch,
} from 'vue'
<script lang="ts" setup>
import { computed, inject, nextTick, provide, ref, unref, watch } from 'vue'
import dayjs from 'dayjs'
import { isEqual } from 'lodash-unified'
import { onClickOutside } from '@vueuse/core'
@ -181,27 +172,24 @@ import { formContextKey, formItemContextKey } from '@element-plus/tokens'
import ElInput from '@element-plus/components/input'
import ElIcon from '@element-plus/components/icon'
import ElTooltip from '@element-plus/components/tooltip'
import { debugWarn, isEmpty } from '@element-plus/utils'
import { debugWarn, isArray, isEmpty } from '@element-plus/utils'
import { EVENT_CODE } from '@element-plus/constants'
import { Calendar, Clock } from '@element-plus/icons-vue'
import { timePickerDefaultProps } from './props'
import type { Dayjs } from 'dayjs'
import type { ComponentPublicInstance } from 'vue'
import type { FormContext, FormItemContext } from '@element-plus/tokens'
import type { Options } from '@popperjs/core'
interface PickerOptions {
isValidValue: (date: Dayjs) => boolean
handleKeydownInput: (event: KeyboardEvent) => void
parseUserInput: (value: Dayjs) => dayjs.Dayjs
formatToString: (value: Dayjs) => string | string[]
getRangeAvailableTime: (date: Dayjs) => dayjs.Dayjs
getDefaultValue: () => Dayjs
panelReady: boolean
handleClear: () => void
handleFocusPicker?: () => void
}
import type { FormContext, FormItemContext } from '@element-plus/tokens'
import type {
DateModelType,
DateOrDates,
DayOrDays,
PickerOptions,
SingleOrRange,
TimePickerDefaultProps,
UserInput,
} from './props'
// Date object and string
const dateEquals = function (a: Date | any, b: Date | any) {
@ -217,8 +205,8 @@ const dateEquals = function (a: Date | any, b: Date | any) {
}
const valueEquals = function (a: Array<Date> | any, b: Array<Date> | any) {
const aIsArray = Array.isArray(a)
const bIsArray = Array.isArray(b)
const aIsArray = isArray(a)
const bIsArray = isArray(b)
if (aIsArray && bIsArray) {
if (a.length !== b.length) {
return false
@ -231,11 +219,11 @@ const valueEquals = function (a: Array<Date> | any, b: Array<Date> | any) {
return false
}
const parser = function (
const parseDate = function (
date: string | number | Date,
format: string,
format: string | undefined,
lang: string
): Dayjs {
) {
const day =
isEmpty(format) || format === 'x'
? dayjs(date).locale(lang)
@ -244,8 +232,8 @@ const parser = function (
}
const formatter = function (
date: string | number | Date,
format: string,
date: string | number | Date | Dayjs,
format: string | undefined,
lang: string
) {
if (isEmpty(format)) return date
@ -253,15 +241,12 @@ const formatter = function (
return dayjs(date).locale(lang).format(format)
}
export default defineComponent({
defineOptions({
name: 'Picker',
components: {
ElInput,
ElTooltip,
ElIcon,
},
props: timePickerDefaultProps,
emits: [
})
const props = defineProps(timePickerDefaultProps)
const emit = defineEmits([
'update:modelValue',
'change',
'focus',
@ -270,8 +255,8 @@ export default defineComponent({
'panel-change',
'visible-change',
'keydown',
],
setup(props, ctx) {
])
const { lang } = useLocale()
const nsDate = useNamespace('date')
@ -286,7 +271,7 @@ export default defineComponent({
const inputRef = ref<HTMLElement | ComponentPublicInstance>()
const pickerVisible = ref(false)
const pickerActualVisible = ref(false)
const valueOnOpen = ref(null)
const valueOnOpen = ref<TimePickerDefaultProps['modelValue'] | null>(null)
let hasJustTabExitedInput = false
let ignoreFocusEvent = false
@ -301,30 +286,34 @@ export default defineComponent({
valueOnOpen.value = props.modelValue
}
})
const emitChange = (val, isClear?: boolean) => {
const emitChange = (
val: TimePickerDefaultProps['modelValue'] | null,
isClear?: boolean
) => {
// determine user real change only
if (isClear || !valueEquals(val, valueOnOpen.value)) {
ctx.emit('change', val)
emit('change', val)
props.validateEvent &&
elFormItem.validate?.('change').catch((err) => debugWarn(err))
}
}
const emitInput = (val) => {
if (!valueEquals(props.modelValue, val)) {
let formatValue
if (Array.isArray(val)) {
formatValue = val.map((_) =>
formatter(_, props.valueFormat, lang.value)
const emitInput = (input: SingleOrRange<DateModelType | Dayjs> | null) => {
if (!valueEquals(props.modelValue, input)) {
let formatted
if (isArray(input)) {
formatted = input.map((item) =>
formatter(item, props.valueFormat, lang.value)
)
} else if (val) {
formatValue = formatter(val, props.valueFormat, lang.value)
} else if (input) {
formatted = formatter(input, props.valueFormat, lang.value)
}
ctx.emit('update:modelValue', val ? formatValue : val, lang.value)
emit('update:modelValue', input ? formatted : input, lang.value)
}
}
const emitKeydown = (e) => {
ctx.emit('keydown', e)
const emitKeydown = (e: KeyboardEvent) => {
emit('keydown', e)
}
const refInput = computed<HTMLInputElement[]>(() => {
if (inputRef.value) {
const _r = isRangeInput.value
@ -341,7 +330,7 @@ export default defineComponent({
return refInput?.value[1]
})
const setSelectionRange = (start, end, pos) => {
const setSelectionRange = (start: number, end: number, pos?: 'min' | 'max') => {
const _inputs = refInput.value
if (!_inputs.length) return
if (!pos || pos === 'min') {
@ -365,7 +354,7 @@ export default defineComponent({
}
pickerVisible.value = visible
let result
if (Array.isArray(date)) {
if (isArray(date)) {
result = date.map((_) => _.toDate())
} else {
// clear btn emit null
@ -380,7 +369,7 @@ export default defineComponent({
}
const onShow = () => {
ctx.emit('visible-change', true)
emit('visible-change', true)
}
const onKeydownPopperContent = (event: KeyboardEvent) => {
@ -392,7 +381,7 @@ export default defineComponent({
const onHide = () => {
pickerActualVisible.value = false
ignoreFocusEvent = false
ctx.emit('visible-change', false)
emit('visible-change', false)
}
const focus = (focusStartInput = true, isIgnoreFocusEvent = false) => {
@ -406,7 +395,7 @@ export default defineComponent({
}
}
const handleFocusInput = (e) => {
const handleFocusInput = (e?: FocusEvent) => {
if (
props.readonly ||
pickerDisabled.value ||
@ -416,20 +405,19 @@ export default defineComponent({
return
}
pickerVisible.value = true
ctx.emit('focus', e)
emit('focus', e)
}
let currentHandleBlurDeferCallback: () => void | undefined
let currentHandleBlurDeferCallback: () => Promise<void> | undefined
// Check if document.activeElement is inside popper or any input before popper close
const handleBlurInput = (e) => {
const handleBlurInput = (e?: FocusEvent) => {
const handleBlurDefer = async () => {
setTimeout(() => {
if (currentHandleBlurDeferCallback === handleBlurDefer) {
if (
!(
refPopper.value?.isFocusInsideContent() &&
!hasJustTabExitedInput
refPopper.value?.isFocusInsideContent() && !hasJustTabExitedInput
) &&
refInput.value.filter((input) => {
return input.contains(document.activeElement)
@ -437,7 +425,7 @@ export default defineComponent({
) {
handleChange()
pickerVisible.value = false
ctx.emit('blur', e)
emit('blur', e)
props.validateEvent &&
elFormItem.validate?.('blur').catch((err) => debugWarn(err))
}
@ -454,43 +442,44 @@ export default defineComponent({
})
const parsedValue = computed(() => {
let result
let dayOrDays: DayOrDays
if (valueIsEmpty.value) {
if (pickerOptions.value.getDefaultValue) {
result = pickerOptions.value.getDefaultValue()
dayOrDays = pickerOptions.value.getDefaultValue()
}
} else {
if (Array.isArray(props.modelValue)) {
result = props.modelValue.map((_) =>
parser(_, props.valueFormat, lang.value)
)
if (isArray(props.modelValue)) {
dayOrDays = props.modelValue.map((d) =>
parseDate(d, props.valueFormat, lang.value)
) as [Dayjs, Dayjs]
} else {
result = parser(props.modelValue, props.valueFormat, lang.value)
dayOrDays = parseDate(props.modelValue, props.valueFormat, lang.value)!
}
}
if (pickerOptions.value.getRangeAvailableTime) {
const availableResult =
pickerOptions.value.getRangeAvailableTime(result)
if (!isEqual(availableResult, result)) {
result = availableResult
const availableResult = pickerOptions.value.getRangeAvailableTime(
dayOrDays!
)
if (!isEqual(availableResult, dayOrDays!)) {
dayOrDays = availableResult
emitInput(
Array.isArray(result)
? result.map((_) => _.toDate())
: result.toDate()
(isArray(dayOrDays)
? dayOrDays.map((_) => _.toDate())
: dayOrDays.toDate()) as SingleOrRange<Date>
)
}
}
if (Array.isArray(result) && result.some((_) => !_)) {
result = []
if (isArray(dayOrDays!) && dayOrDays.some((day) => !day)) {
dayOrDays = [] as unknown as DayOrDays
}
return result
return dayOrDays!
})
const displayValue = computed(() => {
if (!pickerOptions.value.panelReady) return
const displayValue = computed<UserInput>(() => {
if (!pickerOptions.value.panelReady) return ''
const formattedValue = formatDayjsToString(parsedValue.value)
if (Array.isArray(userInput.value)) {
if (isArray(userInput.value)) {
return [
userInput.value[0] || (formattedValue && formattedValue[0]) || '',
userInput.value[1] || (formattedValue && formattedValue[1]) || '',
@ -498,8 +487,8 @@ export default defineComponent({
} else if (userInput.value !== null) {
return userInput.value
}
if (!isTimePicker.value && valueIsEmpty.value) return
if (!pickerVisible.value && valueIsEmpty.value) return
if (!isTimePicker.value && valueIsEmpty.value) return ''
if (!pickerVisible.value && valueIsEmpty.value) return ''
if (formattedValue) {
return isDatesPicker.value
? (formattedValue as Array<string>).join(', ')
@ -534,8 +523,7 @@ export default defineComponent({
}
const valueIsEmpty = computed(() => {
return (
!props.modelValue ||
(Array.isArray(props.modelValue) && !props.modelValue.length)
!props.modelValue || (isArray(props.modelValue) && !props.modelValue.length)
)
})
const onMouseDownInput = async (event: MouseEvent) => {
@ -569,10 +557,6 @@ export default defineComponent({
const pickerSize = useSize()
const popperPaneRef = computed(() => {
return refPopper.value?.popperRef?.contentRef
})
const popperEl = computed(() => unref(refPopper)?.popperRef?.contentRef)
const actualInputRef = computed(() => {
if (unref(isRangeInput)) {
@ -596,7 +580,7 @@ export default defineComponent({
pickerVisible.value = false
})
const userInput = ref(null)
const userInput = ref<UserInput>(null)
const handleChange = () => {
if (userInput.value) {
@ -604,9 +588,9 @@ export default defineComponent({
if (value) {
if (isValidValue(value)) {
emitInput(
Array.isArray(value)
(isArray(value)
? value.map((_) => _.toDate())
: value.toDate()
: value.toDate()) as DateOrDates
)
userInput.value = null
}
@ -619,22 +603,22 @@ export default defineComponent({
}
}
const parseUserInputToDayjs = (value) => {
const parseUserInputToDayjs = (value: UserInput) => {
if (!value) return null
return pickerOptions.value.parseUserInput(value)
return pickerOptions.value.parseUserInput!(value)
}
const formatDayjsToString = (value) => {
const formatDayjsToString = (value: DayOrDays) => {
if (!value) return null
return pickerOptions.value.formatToString(value)
return pickerOptions.value.formatToString!(value)
}
const isValidValue = (value) => {
return pickerOptions.value.isValidValue(value)
const isValidValue = (value: DayOrDays) => {
return pickerOptions.value.isValidValue!(value)
}
const handleKeydownInput = async (event) => {
const code = event.code
const handleKeydownInput = async (event: KeyboardEvent) => {
const { code } = event
emitKeydown(event)
if (code === EVENT_CODE.esc) {
if (pickerVisible.value === true) {
@ -669,7 +653,7 @@ export default defineComponent({
if (
userInput.value === null ||
userInput.value === '' ||
isValidValue(parseUserInputToDayjs(displayValue.value))
isValidValue(parseUserInputToDayjs(displayValue.value) as DayOrDays)
) {
handleChange()
pickerVisible.value = false
@ -687,7 +671,7 @@ export default defineComponent({
pickerOptions.value.handleKeydownInput(event)
}
}
const onUserInput = (e) => {
const onUserInput = (e: string) => {
userInput.value = e
// Temporary fix when the picker is dismissed and the input box
// is focused, just mimic the behavior of antdesign.
@ -696,27 +680,34 @@ export default defineComponent({
}
}
const handleStartInput = (event) => {
const handleStartInput = (event: Event) => {
const target = event.target as HTMLInputElement
if (userInput.value) {
userInput.value = [event.target.value, userInput.value[1]]
userInput.value = [target.value, userInput.value[1]]
} else {
userInput.value = [event.target.value, null]
userInput.value = [target.value, null]
}
}
const handleEndInput = (event) => {
const handleEndInput = (event: Event) => {
const target = event.target as HTMLInputElement
if (userInput.value) {
userInput.value = [userInput.value[0], event.target.value]
userInput.value = [userInput.value[0], target.value]
} else {
userInput.value = [null, event.target.value]
userInput.value = [null, target.value]
}
}
const handleStartChange = () => {
const value = parseUserInputToDayjs(userInput.value && userInput.value[0])
const values = userInput.value as string[]
const value = parseUserInputToDayjs(values && values[0]) as Dayjs
const parsedVal = unref(parsedValue) as [Dayjs, Dayjs]
if (value && value.isValid()) {
userInput.value = [formatDayjsToString(value), displayValue.value[1]]
const newValue = [value, parsedValue.value && parsedValue.value[1]]
userInput.value = [
formatDayjsToString(value) as string,
displayValue.value?.[1] || null,
]
const newValue = [value, parsedVal && (parsedVal[1] || null)] as DayOrDays
if (isValidValue(newValue)) {
emitInput(newValue)
userInput.value = null
@ -725,10 +716,15 @@ export default defineComponent({
}
const handleEndChange = () => {
const value = parseUserInputToDayjs(userInput.value && userInput.value[1])
const values = unref(userInput) as string[]
const value = parseUserInputToDayjs(values && values[1]) as Dayjs
const parsedVal = unref(parsedValue) as [Dayjs, Dayjs]
if (value && value.isValid()) {
userInput.value = [displayValue.value[0], formatDayjsToString(value)]
const newValue = [parsedValue.value && parsedValue.value[0], value]
userInput.value = [
unref(displayValue)?.[0] || null,
formatDayjsToString(value) as string,
]
const newValue = [parsedVal && parsedVal[0], value] as DayOrDays
if (isValidValue(newValue)) {
emitInput(newValue)
userInput.value = null
@ -744,64 +740,38 @@ export default defineComponent({
pickerOptions.value.panelReady = true
}
const onCalendarChange = (e) => {
ctx.emit('calendar-change', e)
const onCalendarChange = (e: [Date, false | Date]) => {
emit('calendar-change', e)
}
const onPanelChange = (value, mode, view) => {
ctx.emit('panel-change', value, mode, view)
const onPanelChange = (
value: [Dayjs, Dayjs],
mode: 'month' | 'year',
view: unknown
) => {
emit('panel-change', value, mode, view)
}
provide('EP_PICKER_BASE', {
props,
})
return {
nsDate,
nsInput,
nsRange,
// injected popper options
elPopperOptions,
isDatesPicker,
handleEndChange,
handleStartChange,
handleStartInput,
handleEndInput,
onUserInput,
handleChange,
handleKeydownInput,
popperPaneRef,
onClickOutside,
pickerSize,
isRangeInput,
onMouseDownInput,
onMouseLeave,
onMouseEnter,
onTouchStartInput,
onClearIconClick,
showClose,
triggerIcon,
onPick,
handleFocusInput,
handleBlurInput,
pickerVisible,
pickerActualVisible,
displayValue,
parsedValue,
setSelectionRange,
refPopper,
inputRef,
pickerDisabled,
onSetPickerOption,
onCalendarChange,
onPanelChange,
defineExpose({
/**
* @description focus input box.
*/
focus,
onShow,
onBeforeShow,
onHide,
onKeydownPopperContent,
}
},
/**
* @description emit focus event
*/
handleFocusInput,
/**
* @description emit blur event
*/
handleBlurInput,
/**
* @description pick item manually
*/
onPick,
})
</script>

View File

@ -1,28 +1,32 @@
import { isValidComponentSize } from '@element-plus/utils'
import { buildProps, definePropType } from '@element-plus/utils'
import { useSizeProp } from '@element-plus/hooks'
import { CircleClose } from '@element-plus/icons-vue'
import type { Component, PropType } from 'vue'
import type { Component, ExtractPropTypes } from 'vue'
import type { Options } from '@popperjs/core'
import type { ComponentSize } from '@element-plus/constants'
import type { Dayjs } from 'dayjs'
export const timePickerDefaultProps = {
export type SingleOrRange<T> = T | [T, T]
export type DateModelType = number | string | Date
export type ModelValueType = SingleOrRange<DateModelType>
export type DayOrDays = SingleOrRange<Dayjs>
export type DateOrDates = SingleOrRange<Date>
export type UserInput = SingleOrRange<string | null>
export const timePickerDefaultProps = buildProps({
id: {
type: [Array, String],
type: definePropType<SingleOrRange<string>>([Array, String]),
},
name: {
type: [Array, String],
type: definePropType<SingleOrRange<string>>([Array, String]),
default: '',
},
popperClass: {
type: String,
default: '',
},
format: {
type: String,
},
valueFormat: {
type: String as PropType<string>,
},
format: String,
valueFormat: String,
type: {
type: String,
default: '',
@ -32,7 +36,7 @@ export const timePickerDefaultProps = {
default: true,
},
clearIcon: {
type: [String, Object] as PropType<string | Component>,
type: definePropType<string | Component>([String, Object]),
default: CircleClose,
},
editable: {
@ -40,13 +44,10 @@ export const timePickerDefaultProps = {
default: true,
},
prefixIcon: {
type: [String, Object] as PropType<string | Component>,
type: definePropType<string | Component>([String, Object]),
default: '',
},
size: {
type: String as PropType<ComponentSize>,
validator: isValidComponentSize,
},
size: useSizeProp,
readonly: {
type: Boolean,
default: false,
@ -60,13 +61,11 @@ export const timePickerDefaultProps = {
default: '',
},
popperOptions: {
type: Object as PropType<Partial<Options>>,
type: definePropType<Partial<Options>>(Object),
default: () => ({}),
},
modelValue: {
type: [Date, Array, String, Number] as PropType<
number | string | Date | (number | string | Date)[]
>,
type: definePropType<ModelValueType>([Date, Array, String, Number]),
default: '',
},
rangeSeparator: {
@ -76,10 +75,10 @@ export const timePickerDefaultProps = {
startPlaceholder: String,
endPlaceholder: String,
defaultValue: {
type: [Date, Array] as PropType<Date | Date[]>,
type: definePropType<SingleOrRange<Date>>([Date, Array]),
},
defaultTime: {
type: [Date, Array] as PropType<Date | Date[]>,
type: definePropType<SingleOrRange<Date>>([Date, Array]),
},
isRange: {
type: Boolean,
@ -113,7 +112,7 @@ export const timePickerDefaultProps = {
default: undefined,
},
tabindex: {
type: [String, Number],
type: definePropType<string | number>([String, Number]),
default: 0,
},
validateEvent: {
@ -121,4 +120,20 @@ export const timePickerDefaultProps = {
default: true,
},
unlinkPanels: Boolean,
} as const)
export type TimePickerDefaultProps = ExtractPropTypes<
typeof timePickerDefaultProps
>
export interface PickerOptions {
isValidValue: (date: DayOrDays) => boolean
handleKeydownInput: (event: KeyboardEvent) => void
parseUserInput: (value: UserInput) => DayOrDays
formatToString: (value: DayOrDays) => UserInput
getRangeAvailableTime: (date: DayOrDays) => DayOrDays
getDefaultValue: () => DayOrDays
panelReady: boolean
handleClear: () => void
handleFocusPicker?: () => void
}

View File

@ -258,7 +258,7 @@ const getRangeAvailableTime = ([start, end]: Array<Dayjs>) => {
return [
getAvailableTime(start, 'start', true, end),
getAvailableTime(end, 'end', false, start),
]
] as const
}
const { getAvailableHours, getAvailableMinutes, getAvailableSeconds } =

View File

@ -1,55 +0,0 @@
import { defineComponent, h, provide, ref } from 'vue'
import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat.js'
import { DEFAULT_FORMATS_TIME } from './common/constant'
import Picker from './common/picker.vue'
import TimePickPanel from './time-picker-com/panel-time-pick.vue'
import TimeRangePanel from './time-picker-com/panel-time-range.vue'
import { timePickerDefaultProps } from './common/props'
dayjs.extend(customParseFormat)
export default defineComponent({
name: 'ElTimePicker',
install: null,
props: {
...timePickerDefaultProps,
isRange: {
type: Boolean,
default: false,
},
},
emits: ['update:modelValue'],
setup(props, ctx) {
const commonPicker = ref(null)
const type = props.isRange ? 'timerange' : 'time'
const panel = props.isRange ? TimeRangePanel : TimePickPanel
const refProps = {
...props,
focus: () => {
commonPicker.value?.handleFocusInput()
},
blur: () => {
commonPicker.value?.handleBlurInput()
},
}
provide('ElPopperOptions', props.popperOptions)
ctx.expose(refProps)
return () => {
const format = props.format ?? DEFAULT_FORMATS_TIME
return h(
Picker,
{
...props, // allow format to be overwrite
format,
type,
ref: commonPicker,
'onUpdate:modelValue': (value) =>
ctx.emit('update:modelValue', value),
},
{
default: (scopedProps) => h(panel, scopedProps),
}
)
}
},
})

View File

@ -0,0 +1,63 @@
import { defineComponent, provide, ref } from 'vue'
import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat.js'
import { DEFAULT_FORMATS_TIME } from './common/constant'
import Picker from './common/picker.vue'
import TimePickPanel from './time-picker-com/panel-time-pick.vue'
import TimeRangePanel from './time-picker-com/panel-time-range.vue'
import { timePickerDefaultProps } from './common/props'
dayjs.extend(customParseFormat)
export default defineComponent({
name: 'ElTimePicker',
install: null,
props: {
...timePickerDefaultProps,
isRange: {
type: Boolean,
default: false,
},
},
emits: ['update:modelValue'],
setup(props, ctx) {
const commonPicker = ref<InstanceType<typeof Picker>>()
const [type, Panel] = props.isRange
? ['timerange', TimeRangePanel]
: ['time', TimePickPanel]
const modelUpdater = (value: any) => ctx.emit('update:modelValue', value)
provide('ElPopperOptions', props.popperOptions)
ctx.expose({
/**
* @description focus on the input element
*/
focus: (e: FocusEvent | undefined) => {
commonPicker.value?.handleFocusInput(e)
},
/**
* @description blur from the input element
*/
blur: (e: FocusEvent | undefined) => {
commonPicker.value?.handleBlurInput(e)
},
})
return () => {
const format = props.format ?? DEFAULT_FORMATS_TIME
return (
<Picker
{...props}
ref={commonPicker}
type={type}
format={format}
onUpdate:modelValue={modelUpdater}
>
{{
default: (props: any) => <Panel {...props} />,
}}
</Picker>
)
}
},
})