refactor: datepicker type

pull/6246/head^2
tangjinzhou 2023-02-12 11:18:49 +08:00
parent 80918cba98
commit 1d774507c0
67 changed files with 173 additions and 144 deletions

View File

@ -15,13 +15,14 @@ import type { CommonProps, RangePickerProps } from './props';
import { commonProps, rangePickerProps } from './props';
import type { PanelMode, RangeValue } from '../../vc-picker/interface';
import type { RangePickerSharedProps } from '../../vc-picker/RangePicker';
import devWarning from '../../vc-util/devWarning';
import { FormItemInputContext, useInjectFormItemContext } from '../../form/FormItemContext';
import omit from '../../_util/omit';
import { getMergedStatus, getStatusClassNames } from '../../_util/statusUtils';
//CSSINJS
import useStyle from '../style';
import { useCompactItemContext } from '../../space/Compact';
import devWarning from '../../vc-util/devWarning';
export default function generateRangePicker<DateType, ExtraProps = {}>(
generateConfig: GenerateConfig<DateType>,
@ -52,19 +53,27 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
const props = _props as unknown as CommonProps<DateType> & RangePickerProps<DateType>;
const formItemContext = useInjectFormItemContext();
const formItemInputContext = FormItemInputContext.useInject();
devWarning(
!attrs.getCalendarContainer,
'DatePicker',
'`getCalendarContainer` is deprecated. Please use `getPopupContainer"` instead.',
);
const { prefixCls, direction, getPopupContainer, size, rootPrefixCls } = useConfigInject(
'picker',
props,
);
// =================== Warning =====================
if (process.env.NODE_ENV !== 'production') {
devWarning(
!props.dropdownClassName,
'RangePicker',
'`dropdownClassName` is deprecated. Please use `popupClassName` instead.',
);
devWarning(
!attrs.getCalendarContainer,
'DatePicker',
'`getCalendarContainer` is deprecated. Please use `getPopupContainer"` instead.',
);
}
const { prefixCls, direction, getPopupContainer, size, rootPrefixCls, disabled } =
useConfigInject('picker', props);
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction);
const mergedSize = computed(() => compactSize.value || size.value);
// style
const [wrapSSR, hashId] = useStyle(prefixCls);
const pickerRef = ref();
expose({
focus: () => {
@ -186,13 +195,14 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
}
ref={pickerRef}
dropdownAlign={transPlacement2DropdownAlign(direction.value, props.placement)}
placeholder={getRangePlaceholder(picker, locale, placeholder as [string, string])}
placeholder={getRangePlaceholder(locale, picker, placeholder as [string, string])}
suffixIcon={suffixNode}
clearIcon={clearIcon || <CloseCircleFilled />}
allowClear={allowClear}
transitionName={transitionName || `${rootPrefixCls.value}-slide-up`}
{...restProps}
{...additionalOverrideProps}
disabled={disabled.value}
id={id}
value={value.value}
defaultValue={defaultValue.value}
@ -200,7 +210,7 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
picker={picker}
class={classNames(
{
[`${pre}-${size.value}`]: size.value,
[`${pre}-${mergedSize.value}`]: mergedSize.value,
[`${pre}-borderless`]: !bordered,
},
getStatusClassNames(
@ -210,6 +220,7 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
),
attrs.class,
hashId.value,
compactItemClassnames.value,
)}
locale={locale!.lang}
prefixCls={pre}
@ -221,7 +232,11 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
superNextIcon={slots.superNextIcon?.() || <span class={`${pre}-super-next-icon`} />}
components={Components}
direction={direction.value}
dropdownClassName={classNames(hashId.value)}
dropdownClassName={classNames(
hashId.value,
props.popupClassName,
props.dropdownClassName,
)}
onChange={onChange}
onOpenChange={onOpenChange}
onFocus={onFocus}

View File

@ -17,6 +17,7 @@ import { commonProps, datePickerProps } from './props';
import devWarning from '../../vc-util/devWarning';
import { FormItemInputContext, useInjectFormItemContext } from '../../form/FormItemContext';
import { getMergedStatus, getStatusClassNames } from '../../_util/statusUtils';
import { useCompactItemContext } from '../../space/Compact';
//CSSINJS
import useStyle from '../style';
@ -55,22 +56,36 @@ export default function generateSinglePicker<DateType, ExtraProps = {}>(
ExtraProps;
const formItemContext = useInjectFormItemContext();
const formItemInputContext = FormItemInputContext.useInject();
devWarning(
!(props.monthCellContentRender || slots.monthCellContentRender),
'DatePicker',
'`monthCellContentRender` is deprecated. Please use `monthCellRender"` instead.',
);
// =================== Warning =====================
if (process.env.NODE_ENV !== 'production') {
devWarning(
picker !== 'quarter',
displayName || 'DatePicker',
`DatePicker.${displayName} is legacy usage. Please use DatePicker[picker='${picker}'] directly.`,
);
devWarning(
!attrs.getCalendarContainer,
'DatePicker',
'`getCalendarContainer` is deprecated. Please use `getPopupContainer"` instead.',
);
const { prefixCls, direction, getPopupContainer, size, rootPrefixCls } = useConfigInject(
'picker',
props,
);
devWarning(
!props.dropdownClassName,
displayName || 'DatePicker',
'`dropdownClassName` is deprecated. Please use `popupClassName` instead.',
);
devWarning(
!(props.monthCellContentRender || slots.monthCellContentRender),
displayName || 'DatePicker',
'`monthCellContentRender` is deprecated. Please use `monthCellRender"` instead.',
);
devWarning(
!attrs.getCalendarContainer,
displayName || 'DatePicker',
'`getCalendarContainer` is deprecated. Please use `getPopupContainer"` instead.',
);
}
const { prefixCls, direction, getPopupContainer, size, rootPrefixCls, disabled } =
useConfigInject('picker', props);
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction);
const mergedSize = computed(() => compactSize.value || size.value);
// style
const [wrapSSR, hashId] = useStyle(prefixCls);
@ -198,7 +213,7 @@ export default function generateSinglePicker<DateType, ExtraProps = {}>(
dateRender={dateRender}
renderExtraFooter={renderExtraFooter}
ref={pickerRef}
placeholder={getPlaceholder(mergedPicker, locale, placeholder)}
placeholder={getPlaceholder(locale, mergedPicker, placeholder)}
suffixIcon={suffixNode}
dropdownAlign={transPlacement2DropdownAlign(direction.value, props.placement)}
clearIcon={clearIcon || <CloseCircleFilled />}
@ -215,7 +230,7 @@ export default function generateSinglePicker<DateType, ExtraProps = {}>(
locale={locale!.lang}
class={classNames(
{
[`${pre}-${size.value}`]: size.value,
[`${pre}-${mergedSize.value}`]: mergedSize.value,
[`${pre}-borderless`]: !bordered,
},
getStatusClassNames(
@ -225,7 +240,9 @@ export default function generateSinglePicker<DateType, ExtraProps = {}>(
),
attrs.class,
hashId.value,
compactItemClassnames.value,
)}
disabled={disabled.value}
prefixCls={pre}
getPopupContainer={attrs.getCalendarContainer || getPopupContainer.value}
generateConfig={generateConfig}
@ -235,7 +252,11 @@ export default function generateSinglePicker<DateType, ExtraProps = {}>(
superNextIcon={slots.superNextIcon?.() || <span class={`${pre}-super-next-icon`} />}
components={Components}
direction={direction.value}
dropdownClassName={classNames(hashId.value)}
dropdownClassName={classNames(
hashId.value,
props.popupClassName,
props.dropdownClassName,
)}
onChange={onChange}
onOpenChange={onOpenChange}
onFocus={onFocus}

View File

@ -1,5 +1,5 @@
import type { FocusEventHandler, MouseEventHandler } from '../../_util/EventInterface';
import type { CSSProperties, PropType } from 'vue';
import type { CSSProperties } from 'vue';
import type { PickerLocale } from '.';
import type { SizeType } from '../../config-provider';
import type {
@ -16,27 +16,39 @@ import type { MonthCellRender } from '../../vc-picker/panels/MonthPanel/MonthBod
import type { SharedTimeProps } from '../../vc-picker/panels/TimePanel';
import type { RangeDateRender, RangeInfo, RangeType } from '../../vc-picker/RangePicker';
import type { VueNode } from '../../_util/type';
import { tuple } from '../../_util/type';
import {
stringType,
arrayType,
someType,
booleanType,
objectType,
functionType,
} from '../../_util/type';
import type { InputStatus } from '../../_util/statusUtils';
const DataPickerPlacements = tuple('bottomLeft', 'bottomRight', 'topLeft', 'topRight');
type DataPickerPlacement = typeof DataPickerPlacements[number];
const DataPickerPlacements = ['bottomLeft', 'bottomRight', 'topLeft', 'topRight'] as const;
type DataPickerPlacement = (typeof DataPickerPlacements)[number];
function commonProps<DateType = any>() {
return {
id: String,
/**
* @deprecated `dropdownClassName` is deprecated which will be removed in next major
* version.Please use `popupClassName` instead.
*/
dropdownClassName: String,
popupStyle: { type: Object as PropType<CSSProperties> },
popupClassName: String,
popupStyle: objectType<CSSProperties>(),
transitionName: String,
placeholder: String,
allowClear: { type: Boolean, default: undefined },
autofocus: { type: Boolean, default: undefined },
disabled: { type: Boolean, default: undefined },
allowClear: booleanType(),
autofocus: booleanType(),
disabled: booleanType(),
tabindex: Number,
open: { type: Boolean, default: undefined },
defaultOpen: { type: Boolean, default: undefined },
open: booleanType(),
defaultOpen: booleanType(),
/** Make input readOnly to avoid popup keyboard in mobile */
inputReadOnly: { type: Boolean, default: undefined },
inputReadOnly: booleanType(),
// Value
// format: string | CustomFormat<DateType> | (string | CustomFormat<DateType>)[];
// Render
@ -46,61 +58,59 @@ function commonProps<DateType = any>() {
// nextIcon?: VueNode;
// superPrevIcon?: VueNode;
// superNextIcon?: VueNode;
getPopupContainer: { type: Function as PropType<(node: HTMLElement) => HTMLElement> },
panelRender: { type: Function as PropType<(originPanel: VueNode) => VueNode> },
getPopupContainer: functionType<(node: HTMLElement) => HTMLElement>(),
panelRender: functionType<(originPanel: VueNode) => VueNode>(),
// // Events
onChange: {
type: Function as PropType<(value: DateType | string | null, dateString: string) => void>,
},
'onUpdate:value': { type: Function as PropType<(value: DateType | string | null) => void> },
onOk: { type: Function as PropType<(value: DateType | string | null) => void> },
onOpenChange: { type: Function as PropType<(open: boolean) => void> },
'onUpdate:open': { type: Function as PropType<(open: boolean) => void> },
onFocus: { type: Function as PropType<FocusEventHandler> },
onBlur: { type: Function as PropType<FocusEventHandler> },
onMousedown: { type: Function as PropType<MouseEventHandler> },
onMouseup: { type: Function as PropType<MouseEventHandler> },
onMouseenter: { type: Function as PropType<MouseEventHandler> },
onMouseleave: { type: Function as PropType<MouseEventHandler> },
onClick: { type: Function as PropType<MouseEventHandler> },
onContextmenu: { type: Function as PropType<MouseEventHandler> },
onKeydown: {
type: Function as PropType<(event: KeyboardEvent, preventDefault: () => void) => void>,
},
onChange: functionType<(value: DateType | string | null, dateString: string) => void>(),
'onUpdate:value': functionType<(value: DateType | string | null) => void>(),
onOk: functionType<(value: DateType | string | null) => void>(),
onOpenChange: functionType<(open: boolean) => void>(),
'onUpdate:open': functionType<(open: boolean) => void>(),
onFocus: functionType<FocusEventHandler>(),
onBlur: functionType<FocusEventHandler>(),
onMousedown: functionType<MouseEventHandler>(),
onMouseup: functionType<MouseEventHandler>(),
onMouseenter: functionType<MouseEventHandler>(),
onMouseleave: functionType<MouseEventHandler>(),
onClick: functionType<MouseEventHandler>(),
onContextmenu: functionType<MouseEventHandler>(),
onKeydown: functionType<(event: KeyboardEvent, preventDefault: () => void) => void>(),
// WAI-ARIA
role: String,
name: String,
autocomplete: String,
direction: { type: String as PropType<'ltr' | 'rtl'> },
showToday: { type: Boolean, default: undefined },
showTime: {
type: [Boolean, Object] as PropType<boolean | SharedTimeProps<DateType>>,
default: undefined,
},
locale: { type: Object as PropType<PickerLocale> },
size: { type: String as PropType<SizeType> },
bordered: { type: Boolean, default: undefined },
dateRender: { type: Function as PropType<DateRender<DateType>> },
disabledDate: { type: Function as PropType<(date: DateType) => boolean> },
mode: { type: String as PropType<PanelMode> },
picker: { type: String as PropType<PickerMode> },
direction: stringType<'ltr' | 'rtl'>(),
showToday: booleanType(),
showTime: someType<boolean | SharedTimeProps<DateType>>([Boolean, Object]),
locale: objectType<PickerLocale>(),
size: stringType<SizeType>(),
bordered: booleanType(),
dateRender: functionType<DateRender<DateType>>(),
disabledDate: functionType<(date: DateType) => boolean>(),
mode: stringType<PanelMode>(),
picker: stringType<PickerMode>(),
valueFormat: String,
placement: String as PropType<DataPickerPlacement>,
status: String as PropType<InputStatus>,
placement: stringType<DataPickerPlacement>(),
status: stringType<InputStatus>(),
/** @deprecated Please use `disabledTime` instead. */
disabledHours: Function as PropType<DisabledTimes['disabledHours']>,
disabledHours: functionType<DisabledTimes['disabledHours']>(),
/** @deprecated Please use `disabledTime` instead. */
disabledMinutes: Function as PropType<DisabledTimes['disabledMinutes']>,
disabledMinutes: functionType<DisabledTimes['disabledMinutes']>(),
/** @deprecated Please use `disabledTime` instead. */
disabledSeconds: Function as PropType<DisabledTimes['disabledSeconds']>,
disabledSeconds: functionType<DisabledTimes['disabledSeconds']>(),
};
}
export interface CommonProps<DateType> {
id?: string;
prefixCls?: string;
/**
* @deprecated `dropdownClassName` is deprecated which will be removed in next major
* version.Please use `popupClassName` instead.
*/
dropdownClassName?: string;
popupClassName?: string;
popupStyle?: CSSProperties;
transitionName?: string;
placeholder?: string;
@ -153,20 +163,20 @@ export interface CommonProps<DateType> {
function datePickerProps<DateType = any>() {
return {
defaultPickerValue: { type: [String, Object] as PropType<DateType | string> },
defaultValue: { type: [String, Object] as PropType<DateType | string> },
value: { type: [String, Object] as PropType<DateType | string> },
disabledTime: { type: Function as PropType<DisabledTime<DateType>> },
format: {
type: [String, Function, Array] as PropType<
string | CustomFormat<DateType> | (string | CustomFormat<DateType>)[]
>,
},
renderExtraFooter: { type: Function as PropType<(mode: PanelMode) => VueNode> },
showNow: { type: Boolean, default: undefined },
monthCellRender: { type: Function as PropType<MonthCellRender<DateType>> },
defaultPickerValue: someType<DateType | string>([Object, String]),
defaultValue: someType<DateType | string>([Object, String]),
value: someType<DateType | string>([Object, String]),
disabledTime: functionType<DisabledTime<DateType>>(),
format: someType<string | CustomFormat<DateType> | (string | CustomFormat<DateType>)[]>([
String,
Function,
Array,
]),
renderExtraFooter: functionType<(mode: PanelMode) => VueNode>(),
showNow: booleanType(),
monthCellRender: functionType<MonthCellRender<DateType>>(),
// deprecated Please use `monthCellRender"` instead.',
monthCellContentRender: { type: Function as PropType<MonthCellRender<DateType>> },
monthCellContentRender: functionType<MonthCellRender<DateType>>(),
};
}
@ -185,58 +195,47 @@ export interface DatePickerProps<DateType> {
function rangePickerProps<DateType>() {
return {
allowEmpty: { type: Array as unknown as PropType<[boolean, boolean]> },
dateRender: { type: Function as PropType<RangeDateRender<DateType>> },
defaultPickerValue: {
type: Array as unknown as PropType<RangeValue<DateType> | RangeValue<string>>,
},
defaultValue: { type: Array as unknown as PropType<RangeValue<DateType> | RangeValue<string>> },
value: { type: Array as unknown as PropType<RangeValue<DateType> | RangeValue<string>> },
disabledTime: {
type: Function as PropType<(date: EventValue<DateType>, type: RangeType) => DisabledTimes>,
},
disabled: { type: [Boolean, Array] as unknown as PropType<boolean | [boolean, boolean]> },
allowEmpty: arrayType<[boolean, boolean]>(),
dateRender: functionType<RangeDateRender<DateType>>(),
defaultPickerValue: arrayType<RangeValue<DateType> | RangeValue<string>>(),
defaultValue: arrayType<RangeValue<DateType> | RangeValue<string>>(),
value: arrayType<RangeValue<DateType> | RangeValue<string>>(),
disabledTime: functionType<(date: EventValue<DateType>, type: RangeType) => DisabledTimes>(),
disabled: someType<boolean | [boolean, boolean]>([Boolean, Array]),
format: String,
renderExtraFooter: { type: Function as PropType<() => VueNode> },
renderExtraFooter: functionType<() => VueNode>(),
separator: { type: String },
ranges: {
type: Object as PropType<
ranges:
objectType<
Record<
string,
Exclude<RangeValue<DateType>, null> | (() => Exclude<RangeValue<DateType>, null>)
>
>,
},
placeholder: Array,
mode: { type: Array as unknown as PropType<[PanelMode, PanelMode]> },
onChange: {
type: Function as PropType<
>(),
placeholder: arrayType<string[]>(),
mode: arrayType<[PanelMode, PanelMode]>(),
onChange:
functionType<
(
value: RangeValue<DateType> | RangeValue<string> | null,
dateString: [string, string],
) => void
>,
},
'onUpdate:value': {
type: Function as PropType<(value: RangeValue<DateType> | RangeValue<string> | null) => void>,
},
onCalendarChange: {
type: Function as PropType<
>(),
'onUpdate:value':
functionType<(value: RangeValue<DateType> | RangeValue<string> | null) => void>(),
onCalendarChange:
functionType<
(
values: RangeValue<DateType> | RangeValue<string>,
formatString: [string, string],
info: RangeInfo,
) => void
>,
},
onPanelChange: {
type: Function as PropType<
>(),
onPanelChange:
functionType<
(values: RangeValue<DateType> | RangeValue<string>, modes: [PanelMode, PanelMode]) => void
>,
},
onOk: {
type: Function as PropType<(dates: RangeValue<DateType> | RangeValue<string>) => void>,
},
>(),
onOk: functionType<(dates: RangeValue<DateType> | RangeValue<string>) => void>(),
};
}

View File

@ -2,7 +2,7 @@
category: Components
type: Data Entry
title: DatePicker
cover: https://gw.alipayobjects.com/zos/alicdn/RT_USzA48/DatePicker.svg
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*xXA9TJ8BTioAAAAAAAAAAAAADrJ8AQ/original
---
To select or input a date.

View File

@ -3,7 +3,7 @@ category: Components
type: 数据录入
title: DatePicker
subtitle: 日期选择框
cover: https://gw.alipayobjects.com/zos/alicdn/RT_USzA48/DatePicker.svg
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*xXA9TJ8BTioAAAAAAAAAAAAADrJ8AQ/original
---
输入或选择日期的控件。

View File

@ -4,8 +4,8 @@ import type { PickerLocale } from './generatePicker';
import type { DirectionType } from '../config-provider';
export function getPlaceholder(
picker: PickerMode | undefined,
locale: PickerLocale,
picker: PickerMode,
customizePlaceholder?: string,
): string {
if (customizePlaceholder !== undefined) {
@ -31,8 +31,8 @@ export function getPlaceholder(
}
export function getRangePlaceholder(
picker: PickerMode | undefined,
locale: PickerLocale,
picker: PickerMode,
customizePlaceholder?: [string, string],
) {
if (customizePlaceholder !== undefined) {
@ -92,17 +92,11 @@ export function transPlacement2DropdownAlign(
};
}
default: {
return direction === 'rtl'
? {
points: ['tr', 'br'],
offset: [0, 4],
overflow,
}
: {
points: ['tl', 'bl'],
offset: [0, 4],
overflow,
};
return {
points: direction === 'rtl' ? ['tr', 'br'] : ['tl', 'bl'],
offset: [0, 4],
overflow,
};
}
}
}