Skip to content

Commit dc5f54e

Browse files
authored
feat(DatePicker): improve preset handling and popup visibility (#3798)
* feat(DatePicker): improve preset handling and popup visibility management * fix(DateRangePicker): correct onChange call to use formattedPreset directly
1 parent 1b94da5 commit dc5f54e

File tree

2 files changed

+52
-28
lines changed

2 files changed

+52
-28
lines changed

packages/components/date-picker/DatePicker.tsx

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
import React, { forwardRef, useCallback, useEffect } from 'react';
2+
23
import classNames from 'classnames';
34
import dayjs from 'dayjs';
45
import { isDate } from 'lodash-es';
6+
57
import { formatDate, formatTime, getDefaultFormat, parseToDayjs } from '@tdesign/common-js/date-picker/format';
68
import { addMonth, covertToDate, extractTimeObj, isSame, subtractMonth } from '@tdesign/common-js/date-picker/utils';
7-
import type { StyledProps } from '../common';
9+
810
import useConfig from '../hooks/useConfig';
911
import useDefaultProps from '../hooks/useDefaultProps';
1012
import useLatest from '../hooks/useLatest';
1113
import useUpdateEffect from '../hooks/useUpdateEffect';
1214
import { useLocaleReceiver } from '../locale/LocalReceiver';
1315
import SelectInput from '../select-input';
14-
import type { TagInputRemoveContext } from '../tag-input';
1516
import { datePickerDefaultProps } from './defaultProps';
1617
import useSingle from './hooks/useSingle';
1718
import SinglePanel from './panel/SinglePanel';
19+
20+
import type { StyledProps } from '../common';
21+
import type { TagInputRemoveContext } from '../tag-input';
1822
import type { DateMultipleValue, DateValue, PresetDate, TdDatePickerProps } from './type';
1923

2024
export interface DatePickerProps extends TdDatePickerProps, StyledProps {}
@@ -149,11 +153,11 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((originalProps, r
149153
if (enableTimePicker) {
150154
setCacheValue(formatDate(date, { format }));
151155
if (props.needConfirm) return;
156+
handlePopupInvisible();
152157
onChange(formatDate(date, { format, targetFormat: valueType }), {
153158
dayjsValue: parseToDayjs(date, format),
154159
trigger: 'pick',
155160
});
156-
handlePopupInvisible();
157161
} else {
158162
if (multiple) {
159163
const newDate = processDate(date);
@@ -163,11 +167,11 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((originalProps, r
163167
});
164168
return;
165169
}
170+
handlePopupInvisible();
166171
onChange(formatDate(date, { format, targetFormat: valueType }), {
167172
dayjsValue: parseToDayjs(date, format),
168173
trigger: 'pick',
169174
});
170-
handlePopupInvisible();
171175
}
172176
}
173177
// 头部快速切换
@@ -218,7 +222,7 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((originalProps, r
218222
function onConfirmClick({ e }) {
219223
const nextValue = formatDate(inputValue, { format });
220224
props?.onConfirm?.({ e, date: nextValue });
221-
225+
handlePopupInvisible();
222226
if (nextValue) {
223227
onChange(formatDate(inputValue, { format, targetFormat: valueType }), {
224228
dayjsValue: parseToDayjs(inputValue, format),
@@ -227,7 +231,6 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((originalProps, r
227231
} else {
228232
setInputValue(formatDate(value, { format }));
229233
}
230-
handlePopupInvisible();
231234
}
232235

233236
// 预设
@@ -236,19 +239,24 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((originalProps, r
236239
if (typeof preset === 'function') {
237240
presetValue = preset();
238241
}
239-
const formattedPresetValue = formatDate(presetValue, { format, targetFormat: valueType });
240-
const formattedInputValue = formatDate(presetValue, { format });
242+
const formattedPreset = formatDate(presetValue, { format, targetFormat: valueType });
243+
const formattedInput = formatDate(presetValue, { format });
244+
245+
setInputValue(formattedInput);
246+
setCacheValue(formattedInput);
241247

242-
// preset 不需要 confirm 就同步
243-
setInputValue(formattedInputValue);
244-
setCacheValue(formattedInputValue);
248+
setTime(formatTime(presetValue, format, timeFormat, props.defaultTime));
249+
setYear(parseToDayjs(presetValue, format).year());
250+
setMonth(parseToDayjs(presetValue, format).month());
245251

246-
onChange(formattedPresetValue, {
252+
// 先回调 onVisibleChange
253+
handlePopupInvisible();
254+
// 再回调 onChange(方便用户覆盖弹窗开闭状态)
255+
onChange(formattedPreset, {
247256
dayjsValue: parseToDayjs(presetValue, format),
248257
trigger: 'preset',
249258
});
250259
props.onPresetClick?.(context);
251-
handlePopupInvisible();
252260
}
253261

254262
const onYearChange = useCallback((year: number) => {

packages/components/date-picker/DateRangePicker.tsx

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
import React, { forwardRef, useEffect, useState } from 'react';
2+
23
import classNames from 'classnames';
34
import dayjs from 'dayjs';
5+
46
import {
5-
parseToDayjs,
6-
formatTime,
77
formatDate,
8-
isValidDate,
8+
formatTime,
99
getDefaultFormat,
1010
initYearMonthTime,
11+
isValidDate,
12+
parseToDayjs,
1113
} from '@tdesign/common-js/date-picker/format';
12-
import { subtractMonth, addMonth, extractTimeObj } from '@tdesign/common-js/date-picker/utils';
14+
import { addMonth, extractTimeObj, subtractMonth } from '@tdesign/common-js/date-picker/utils';
1315
import log from '@tdesign/common-js/log/index';
16+
1417
import useConfig from '../hooks/useConfig';
15-
import { StyledProps } from '../common';
16-
import { TdDateRangePickerProps, PresetDate } from './type';
18+
import useDefaultProps from '../hooks/useDefaultProps';
1719
import { RangeInputPopup } from '../range-input';
18-
import RangePanel from './panel/RangePanel';
19-
import useRange from './hooks/useRange';
2020
import { dateRangePickerDefaultProps } from './defaultProps';
21-
import useDefaultProps from '../hooks/useDefaultProps';
21+
import useRange from './hooks/useRange';
22+
import RangePanel from './panel/RangePanel';
2223
import { dateCorrection } from './utils';
2324

25+
import type { StyledProps } from '../common';
26+
import type { DateRangeValue, PresetDate, TdDateRangePickerProps } from './type';
27+
2428
export interface DateRangePickerProps extends TdDateRangePickerProps, StyledProps {}
2529

2630
const DateRangePicker = forwardRef<HTMLDivElement, DateRangePickerProps>((originalProps, ref) => {
@@ -274,20 +278,32 @@ const DateRangePicker = forwardRef<HTMLDivElement, DateRangePickerProps>((origin
274278
}
275279

276280
// 预设
277-
function onPresetClick(preset, context: { preset: PresetDate; e: React.MouseEvent<HTMLDivElement> }) {
281+
function onPresetClick(
282+
preset: DateRangeValue | (() => DateRangeValue),
283+
context: { preset: PresetDate; e: React.MouseEvent<HTMLDivElement> },
284+
) {
278285
let presetValue = preset;
279286
if (typeof preset === 'function') {
280287
presetValue = preset();
281288
}
282289
if (!Array.isArray(presetValue)) {
283290
log.error('DateRangePicker', `preset: ${preset} must be Array!`);
284291
} else {
285-
onChange(formatDate(presetValue, { format, targetFormat: valueType, autoSwap: true }), {
286-
dayjsValue: presetValue.map((p) => parseToDayjs(p, format)),
287-
trigger: 'preset',
288-
});
289-
props.onPresetClick?.(context);
292+
const formattedPreset = formatDate(presetValue, { format });
293+
setInputValue(formattedPreset);
294+
setCacheValue(formattedPreset);
295+
setTime(formatTime(formattedPreset, format, timeFormat, props.defaultTime));
296+
const newYear = formattedPreset.map((v) => parseToDayjs(v, format).year());
297+
const newMonth = formattedPreset.map((v) => parseToDayjs(v, format).month());
298+
299+
setYear(newYear);
300+
setMonth(newMonth);
301+
setIsSelected(true);
302+
setIsFirstValueSelected(true);
303+
290304
handlePopupInvisible();
305+
onChange(formattedPreset, { dayjsValue: formattedPreset.map((p) => parseToDayjs(p, format)), trigger: 'preset' });
306+
props.onPresetClick?.(context);
291307
}
292308
}
293309

0 commit comments

Comments
 (0)