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)
},

File diff suppressed because it is too large Load Diff

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>
)
}
},
})