From 5b233da008c19aeb69899444533807b03e5b43d4 Mon Sep 17 00:00:00 2001 From: Jeremy <15975785+jw-foss@users.noreply.github.com> Date: Wed, 8 Jun 2022 09:17:23 +0800 Subject: [PATCH] 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> --- .../date-picker/src/date-picker.tsx | 1 - .../time-picker/src/common/picker.vue | 1054 ++++++++--------- .../time-picker/src/common/props.ts | 65 +- .../src/time-picker-com/panel-time-range.vue | 2 +- .../components/time-picker/src/time-picker.ts | 55 - .../time-picker/src/time-picker.tsx | 63 + 6 files changed, 616 insertions(+), 624 deletions(-) delete mode 100644 packages/components/time-picker/src/time-picker.ts create mode 100644 packages/components/time-picker/src/time-picker.tsx diff --git a/packages/components/date-picker/src/date-picker.tsx b/packages/components/date-picker/src/date-picker.tsx index 01a89042f7..daaa3bf4c6 100644 --- a/packages/components/date-picker/src/date-picker.tsx +++ b/packages/components/date-picker/src/date-picker.tsx @@ -49,7 +49,6 @@ export default defineComponent({ const commonPicker = ref>() const refProps = { - ...props, focus: (focusStartInput = true) => { commonPicker.value?.focus(focusStartInput) }, diff --git a/packages/components/time-picker/src/common/picker.vue b/packages/components/time-picker/src/common/picker.vue index cdab300ece..3408cebaec 100644 --- a/packages/components/time-picker/src/common/picker.vue +++ b/packages/components/time-picker/src/common/picker.vue @@ -23,10 +23,10 @@ - diff --git a/packages/components/time-picker/src/common/props.ts b/packages/components/time-picker/src/common/props.ts index e80c72d4e0..0500f926b7 100644 --- a/packages/components/time-picker/src/common/props.ts +++ b/packages/components/time-picker/src/common/props.ts @@ -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] +export type DateModelType = number | string | Date +export type ModelValueType = SingleOrRange +export type DayOrDays = SingleOrRange +export type DateOrDates = SingleOrRange +export type UserInput = SingleOrRange + +export const timePickerDefaultProps = buildProps({ id: { - type: [Array, String], + type: definePropType>([Array, String]), }, name: { - type: [Array, String], + type: definePropType>([Array, String]), default: '', }, popperClass: { type: String, default: '', }, - format: { - type: String, - }, - valueFormat: { - type: String as PropType, - }, + format: String, + valueFormat: String, type: { type: String, default: '', @@ -32,7 +36,7 @@ export const timePickerDefaultProps = { default: true, }, clearIcon: { - type: [String, Object] as PropType, + type: definePropType([String, Object]), default: CircleClose, }, editable: { @@ -40,13 +44,10 @@ export const timePickerDefaultProps = { default: true, }, prefixIcon: { - type: [String, Object] as PropType, + type: definePropType([String, Object]), default: '', }, - size: { - type: String as PropType, - validator: isValidComponentSize, - }, + size: useSizeProp, readonly: { type: Boolean, default: false, @@ -60,13 +61,11 @@ export const timePickerDefaultProps = { default: '', }, popperOptions: { - type: Object as PropType>, + type: definePropType>(Object), default: () => ({}), }, modelValue: { - type: [Date, Array, String, Number] as PropType< - number | string | Date | (number | string | Date)[] - >, + type: definePropType([Date, Array, String, Number]), default: '', }, rangeSeparator: { @@ -76,10 +75,10 @@ export const timePickerDefaultProps = { startPlaceholder: String, endPlaceholder: String, defaultValue: { - type: [Date, Array] as PropType, + type: definePropType>([Date, Array]), }, defaultTime: { - type: [Date, Array] as PropType, + type: definePropType>([Date, Array]), }, isRange: { type: Boolean, @@ -113,7 +112,7 @@ export const timePickerDefaultProps = { default: undefined, }, tabindex: { - type: [String, Number], + type: definePropType([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 } diff --git a/packages/components/time-picker/src/time-picker-com/panel-time-range.vue b/packages/components/time-picker/src/time-picker-com/panel-time-range.vue index 2bf03cff3a..dd2e109a1e 100644 --- a/packages/components/time-picker/src/time-picker-com/panel-time-range.vue +++ b/packages/components/time-picker/src/time-picker-com/panel-time-range.vue @@ -258,7 +258,7 @@ const getRangeAvailableTime = ([start, end]: Array) => { return [ getAvailableTime(start, 'start', true, end), getAvailableTime(end, 'end', false, start), - ] + ] as const } const { getAvailableHours, getAvailableMinutes, getAvailableSeconds } = diff --git a/packages/components/time-picker/src/time-picker.ts b/packages/components/time-picker/src/time-picker.ts deleted file mode 100644 index 57956a3d62..0000000000 --- a/packages/components/time-picker/src/time-picker.ts +++ /dev/null @@ -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), - } - ) - } - }, -}) diff --git a/packages/components/time-picker/src/time-picker.tsx b/packages/components/time-picker/src/time-picker.tsx new file mode 100644 index 0000000000..6b49817ca6 --- /dev/null +++ b/packages/components/time-picker/src/time-picker.tsx @@ -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>() + 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 ( + + {{ + default: (props: any) => , + }} + + ) + } + }, +})