refactor: date

pull/4499/head
tangjinzhou 2021-07-21 12:05:03 +08:00
parent 4a21e41223
commit e1277cdee0
12 changed files with 102 additions and 57 deletions

View File

@ -13,7 +13,7 @@ export default function useMergedState<T, R = Ref<T>>(
postState?: (val: T) => T; postState?: (val: T) => T;
}, },
): [R, (val: T) => void] { ): [R, (val: T) => void] {
const { defaultValue, value } = option || {}; const { defaultValue, value = ref() } = option || {};
let initValue: T = let initValue: T =
typeof defaultStateValue === 'function' ? (defaultStateValue as any)() : defaultStateValue; typeof defaultStateValue === 'function' ? (defaultStateValue as any)() : defaultStateValue;
if (value.value !== undefined) { if (value.value !== undefined) {

View File

@ -51,7 +51,13 @@ export { default as Comment } from './comment';
export { default as ConfigProvider } from './config-provider'; export { default as ConfigProvider } from './config-provider';
export type { DatePickerProps } from './date-picker'; export type { DatePickerProps } from './date-picker';
export { default as DatePicker } from './date-picker'; export {
default as DatePicker,
MonthPicker,
WeekPicker,
RangePicker,
QuarterPicker,
} from './date-picker';
export type { DescriptionsProps } from './descriptions'; export type { DescriptionsProps } from './descriptions';
export { default as Descriptions, DescriptionsItem } from './descriptions'; export { default as Descriptions, DescriptionsItem } from './descriptions';

View File

@ -17,9 +17,10 @@ export default function generateRangePicker<DateType>(generateConfig: GenerateCo
const RangePicker = defineComponent<RangePickerProps<DateType>>({ const RangePicker = defineComponent<RangePickerProps<DateType>>({
name: 'ARangePicker', name: 'ARangePicker',
inheritAttrs: false, inheritAttrs: false,
props: ['size', 'prefixCls', 'direction', 'getPopupContainer', 'locale'] as any, props: ['size', 'prefixCls', 'direction', 'getPopupContainer', 'locale', 'value'] as any,
slots: ['suffixIcon'], slots: ['suffixIcon'],
setup(props, { expose, slots, attrs }) { emits: ['change', 'panelChange', 'ok', 'openChange', 'update:value', 'calendarChange'],
setup(props, { expose, slots, attrs, emit }) {
const { prefixCls, direction, getPopupContainer, size, rootPrefixCls } = useConfigInject( const { prefixCls, direction, getPopupContainer, size, rootPrefixCls } = useConfigInject(
'picker', 'picker',
props, props,
@ -33,6 +34,10 @@ export default function generateRangePicker<DateType>(generateConfig: GenerateCo
pickerRef.value?.blur(); pickerRef.value?.blur();
}, },
}); });
const onChange = (dates: [DateType, DateType], dateStrings: [string, string]) => {
emit('update:value', dates);
emit('change', dates, dateStrings);
};
const [contextLocale] = useLocaleReceiver('DatePicker', enUS); const [contextLocale] = useLocaleReceiver('DatePicker', enUS);
return () => { return () => {
const locale = { ...contextLocale.value, ...props.locale }; const locale = { ...contextLocale.value, ...props.locale };
@ -88,6 +93,7 @@ export default function generateRangePicker<DateType>(generateConfig: GenerateCo
superNextIcon={<span class={`${pre}-super-next-icon`} />} superNextIcon={<span class={`${pre}-super-next-icon`} />}
components={Components} components={Components}
direction={direction.value} direction={direction.value}
onChange={onChange}
/> />
); );
}; };

View File

@ -23,9 +23,10 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
return defineComponent<InnerPickerProps>({ return defineComponent<InnerPickerProps>({
name: displayName, name: displayName,
inheritAttrs: false, inheritAttrs: false,
props: ['size', 'prefixCls', 'direction', 'getPopupContainer', 'locale'] as any, props: ['size', 'prefixCls', 'direction', 'getPopupContainer', 'locale', 'value'] as any,
slots: ['suffixIcon'], slots: ['suffixIcon'],
setup(props, { slots, expose, attrs }) { emits: ['change', 'panelChange', 'ok', 'openChange', 'update:value'],
setup(props, { slots, expose, attrs, emit }) {
const { prefixCls, direction, getPopupContainer, size, rootPrefixCls } = useConfigInject( const { prefixCls, direction, getPopupContainer, size, rootPrefixCls } = useConfigInject(
'picker', 'picker',
props, props,
@ -39,6 +40,11 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
pickerRef.value?.blur(); pickerRef.value?.blur();
}, },
}); });
const onChange = (date: DateType, dateString: string) => {
emit('update:value', date);
emit('change', date, dateString);
};
const [contextLocale] = useLocaleReceiver('DatePicker', enUS); const [contextLocale] = useLocaleReceiver('DatePicker', enUS);
return () => { return () => {
const locale = { ...contextLocale.value, ...props.locale }; const locale = { ...contextLocale.value, ...props.locale };
@ -47,14 +53,11 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
bordered = true, bordered = true,
placeholder, placeholder,
suffixIcon = slots.suffixIcon?.(), suffixIcon = slots.suffixIcon?.(),
showToday = true,
...restProps ...restProps
} = p; } = p;
const { format, showTime } = p as any; const { format, showTime } = p as any;
const additionalProps = {
showToday: true,
};
let additionalOverrideProps: any = {}; let additionalOverrideProps: any = {};
if (picker) { if (picker) {
additionalOverrideProps.picker = picker; additionalOverrideProps.picker = picker;
@ -80,9 +83,9 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
clearIcon={<CloseCircleFilled />} clearIcon={<CloseCircleFilled />}
allowClear allowClear
transitionName={`${rootPrefixCls.value}-slide-up`} transitionName={`${rootPrefixCls.value}-slide-up`}
{...additionalProps}
{...restProps} {...restProps}
{...additionalOverrideProps} {...additionalOverrideProps}
showToday={showToday}
locale={locale!.lang} locale={locale!.lang}
class={classNames( class={classNames(
{ {
@ -100,6 +103,7 @@ export default function generatePicker<DateType>(generateConfig: GenerateConfig<
superNextIcon={<span class={`${pre}-super-next-icon`} />} superNextIcon={<span class={`${pre}-super-next-icon`} />}
components={Components} components={Components}
direction={direction.value} direction={direction.value}
onChange={onChange}
/> />
); );
}; };

View File

@ -1,6 +1,6 @@
import type { Moment } from 'moment'; import type { Moment } from 'moment';
import { App } from 'vue';
import momentGenerateConfig from '../vc-picker/generate/moment'; import momentGenerateConfig from '../vc-picker/generate/moment';
import { withInstall } from '../_util/type';
import type { import type {
PickerProps, PickerProps,
PickerDateProps, PickerDateProps,
@ -15,4 +15,21 @@ export type RangePickerProps = BaseRangePickerProps<Moment>;
const DatePicker = generatePicker<Moment>(momentGenerateConfig); const DatePicker = generatePicker<Moment>(momentGenerateConfig);
export default withInstall(DatePicker); const RangePicker = DatePicker.RangePicker;
const MonthPicker = DatePicker.MonthPicker;
const WeekPicker = DatePicker.WeekPicker;
const QuarterPicker = DatePicker.QuarterPicker;
/* istanbul ignore next */
DatePicker.install = function (app: App) {
app.component(DatePicker.name, DatePicker);
app.component(RangePicker.name, RangePicker);
app.component(MonthPicker.name, MonthPicker);
app.component(WeekPicker.name, WeekPicker);
app.component(QuarterPicker.name, QuarterPicker);
return app;
};
export { RangePicker, WeekPicker, MonthPicker, QuarterPicker };
export default DatePicker as typeof DatePicker & Plugin;

View File

@ -90,6 +90,7 @@ export type PickerSharedProps<DateType> = {
autocomplete?: string; autocomplete?: string;
direction?: 'ltr' | 'rtl'; direction?: 'ltr' | 'rtl';
showToday?: boolean;
} & HtmlHTMLAttributes; } & HtmlHTMLAttributes;
type OmitPanelProps<Props> = Omit< type OmitPanelProps<Props> = Omit<
@ -173,6 +174,7 @@ function Picker<DateType>() {
'onSelect', 'onSelect',
'direction', 'direction',
'autocomplete', 'autocomplete',
'showToday',
] as any, ] as any,
slots: [ slots: [
'suffixIcon', 'suffixIcon',
@ -440,6 +442,7 @@ function Picker<DateType>() {
const panelProps = { const panelProps = {
// Remove `picker` & `format` here since TimePicker is little different with other panel // Remove `picker` & `format` here since TimePicker is little different with other panel
...(props as Omit<MergedPickerProps<DateType>, 'picker' | 'format'>), ...(props as Omit<MergedPickerProps<DateType>, 'picker' | 'format'>),
...attrs,
pickerValue: undefined, pickerValue: undefined,
onPickerValueChange: undefined, onPickerValueChange: undefined,
onChange: null, onChange: null,
@ -538,7 +541,7 @@ function Picker<DateType>() {
<div <div
class={classNames(prefixCls, attrs.class, { class={classNames(prefixCls, attrs.class, {
[`${prefixCls}-disabled`]: disabled, [`${prefixCls}-disabled`]: disabled,
[`${prefixCls}-focused`]: focused, [`${prefixCls}-focused`]: focused.value,
[`${prefixCls}-rtl`]: direction === 'rtl', [`${prefixCls}-rtl`]: direction === 'rtl',
})} })}
style={attrs.style} style={attrs.style}
@ -562,7 +565,7 @@ function Picker<DateType>() {
readonly={ readonly={
inputReadOnly || typeof formatList.value[0] === 'function' || !typing.value inputReadOnly || typeof formatList.value[0] === 'function' || !typing.value
} }
value={hoverValue || text} value={hoverValue.value || text.value}
onChange={(e: ChangeEvent) => { onChange={(e: ChangeEvent) => {
triggerTextChange(e.target.value); triggerTextChange(e.target.value);
}} }}

View File

@ -122,35 +122,35 @@ function PickerPanel<DateType>() {
return defineComponent<MergedPickerPanelProps<DateType>>({ return defineComponent<MergedPickerPanelProps<DateType>>({
name: 'PickerPanel', name: 'PickerPanel',
inheritAttrs: false, inheritAttrs: false,
props: [ props: {
'prefixCls', prefixCls: String,
'locale', locale: Object,
'generateConfig', generateConfig: Object,
'value', value: Object,
'defaultValue', defaultValue: Object,
'pickerValue', pickerValue: Object,
'defaultPickerValue', defaultPickerValue: Object,
'disabledDate', disabledDate: Function,
'mode', mode: String,
{ picker: { default: 'date' } }, picker: String,
{ tabindex: { default: 0 } }, tabindex: [Number, String],
'showNow', showNow: Boolean,
'showTime', showTime: Boolean,
'showToday', showToday: Boolean,
'renderExtraFooter', renderExtraFooter: Function,
'hideHeader', hideHeader: Boolean,
'onSelect', onSelect: Function,
'onChange', onChange: Function,
'onPanelChange', onPanelChange: Function,
'onMousedown', onMousedown: Function,
'onPickerValueChange', onPickerValueChange: Function,
'onOk', onOk: Function,
'components', components: Object,
'direction', direction: String,
{ hourStep: { default: 1 } }, hourStep: { type: Number, default: 1 },
{ minuteStep: { default: 1 } }, minuteStep: { type: Number, default: 1 },
{ secondStep: { default: 1 } }, secondStep: { type: Number, default: 1 },
] as any, } as any,
setup(props, { attrs }) { setup(props, { attrs }) {
const needConfirmButton = computed( const needConfirmButton = computed(
() => (props.picker === 'date' && !!props.showTime) || props.picker === 'time', () => (props.picker === 'date' && !!props.showTime) || props.picker === 'time',
@ -197,7 +197,7 @@ function PickerPanel<DateType>() {
value: toRef(props, 'value'), value: toRef(props, 'value'),
defaultValue: props.defaultValue, defaultValue: props.defaultValue,
postState: val => { postState: val => {
if (!val && defaultOpenValue.value && props.picker === 'time') { if (!val && defaultOpenValue?.value && props.picker === 'time') {
return defaultOpenValue.value; return defaultOpenValue.value;
} }
return val; return val;
@ -534,7 +534,7 @@ function PickerPanel<DateType>() {
let extraFooter: VueNode; let extraFooter: VueNode;
let rangesNode: VueNode; let rangesNode: VueNode;
if (!hideRanges) { if (!hideRanges?.value) {
extraFooter = getExtraFooter(prefixCls, mergedMode.value, renderExtraFooter); extraFooter = getExtraFooter(prefixCls, mergedMode.value, renderExtraFooter);
rangesNode = getRanges({ rangesNode = getRanges({
prefixCls, prefixCls,

View File

@ -31,7 +31,12 @@ export const useProvideRange = (props: RangeContextProps) => {
}; };
export const useInjectRange = () => { export const useInjectRange = () => {
return inject(RangeContextKey); return inject(RangeContextKey, {
rangedValue: ref(),
hoverRangedValue: ref(),
inRange: ref(),
panelPosition: ref(),
});
}; };
export const RangeContextProvider = defineComponent({ export const RangeContextProvider = defineComponent({

View File

@ -823,7 +823,7 @@ function RangerPicker<DateType>() {
{...panelProps} {...panelProps}
dateRender={panelDateRender} dateRender={panelDateRender}
showTime={panelShowTime} showTime={panelShowTime}
mode={mergedModes[mergedActivePickerIndex.value]} mode={mergedModes.value[mergedActivePickerIndex.value]}
generateConfig={generateConfig} generateConfig={generateConfig}
style={undefined} style={undefined}
direction={direction} direction={direction}
@ -859,7 +859,7 @@ function RangerPicker<DateType>() {
let viewDate = date; let viewDate = date;
if ( if (
panelPosition === 'right' && panelPosition === 'right' &&
mergedModes[mergedActivePickerIndex.value] === newMode mergedModes.value[mergedActivePickerIndex.value] === newMode
) { ) {
viewDate = getClosingViewDate(viewDate, newMode as any, generateConfig, -1); viewDate = getClosingViewDate(viewDate, newMode as any, generateConfig, -1);
} }
@ -958,7 +958,7 @@ function RangerPicker<DateType>() {
let panels: VueNode; let panels: VueNode;
const extraNode = getExtraFooter( const extraNode = getExtraFooter(
prefixCls, prefixCls,
mergedModes[mergedActivePickerIndex.value], mergedModes.value[mergedActivePickerIndex.value],
renderExtraFooter, renderExtraFooter,
); );
@ -987,7 +987,7 @@ function RangerPicker<DateType>() {
? startViewDate.value ? startViewDate.value
: endViewDate.value; : endViewDate.value;
const nextViewDate = getClosingViewDate(viewDate, picker, generateConfig); const nextViewDate = getClosingViewDate(viewDate, picker, generateConfig);
const currentMode = mergedModes[mergedActivePickerIndex.value]; const currentMode = mergedModes.value[mergedActivePickerIndex.value];
const showDoublePanel = currentMode === picker; const showDoublePanel = currentMode === picker;
const leftPanel = renderPanel(showDoublePanel ? 'left' : false, { const leftPanel = renderPanel(showDoublePanel ? 'left' : false, {

View File

@ -45,7 +45,7 @@ export default function useRangeDisabled<DateType>(
} }
const disabledStartDate = (date: DateType) => { const disabledStartDate = (date: DateType) => {
if (disabledDate && disabledDate.value(date)) { if (disabledDate && disabledDate?.value?.(date)) {
return true; return true;
} }

View File

@ -27,7 +27,7 @@ export default function useValueTexts<DateType>(
const fullValueTexts: string[] = []; const fullValueTexts: string[] = [];
for (let i = 0; i < formatList.value.length; i += 1) { for (let i = 0; i < formatList.value.length; i += 1) {
const format = formatList[i]; const format = formatList.value[i];
const formatStr = formatValue(value.value, { const formatStr = formatValue(value.value, {
generateConfig: generateConfig.value, generateConfig: generateConfig.value,
locale: locale.value, locale: locale.value,

View File

@ -1,18 +1,22 @@
<template> <template>
<a-space direction="vertical"> <a-space direction="vertical">
<a-date-picker v-model:value="value1" /> <!-- <a-date-picker v-model:value="value1" /> -->
<!-- <a-month-picker v-model:value="value2" placeholder="Select month" /> <!-- <a-month-picker v-model:value="value2" placeholder="Select month" />
<a-range-picker v-model:value="value3" />
<a-week-picker v-model:value="value4" placeholder="Select week" /> --> <a-week-picker v-model:value="value4" placeholder="Select week" /> -->
<a-range-picker v-model:value="value3" />
</a-space> </a-space>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from 'vue'; import { defineComponent, ref, watch } from 'vue';
import { Moment } from 'moment'; import { Moment } from 'moment';
export default defineComponent({ export default defineComponent({
setup() { setup() {
const value1 = ref<Moment>();
watch(value1, () => {
console.log(value1);
});
return { return {
value1: ref<Moment>(), value1,
value2: ref<Moment>(), value2: ref<Moment>(),
value3: ref<Moment[]>([]), value3: ref<Moment[]>([]),
value4: ref<Moment>(), value4: ref<Moment>(),