Skip to content

Commit f0ae965

Browse files
authored
fix: Select date should align the selected time by time panel (#712)
* fix: align time * fix: hover logic * test: add test case * fix: time defaultValue not working
1 parent 6f13f6c commit f0ae965

File tree

5 files changed

+86
-100
lines changed

5 files changed

+86
-100
lines changed

docs/examples/debug.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,9 @@ export default () => {
149149
<SinglePicker
150150
// Shared
151151
{...sharedLocale}
152-
picker="week"
153-
multiple
152+
// picker="week"
153+
// multiple
154+
showTime
154155
defaultValue={[
155156
dayjs(),
156157
// dayjs('2000-01-01'),
@@ -186,12 +187,12 @@ export default () => {
186187
}}
187188
/>
188189
<br />
189-
{/* <RangePicker
190+
<RangePicker
190191
{...sharedLocale}
191192
value={rangeValue}
192-
disabledDate={() => true}
193-
picker="time"
194-
showTime
193+
showTime={{
194+
defaultValue: [dayjs('2000-01-01 01:02:03'), dayjs('2000-01-01 05:06:07')],
195+
}}
195196
changeOnBlur={false}
196197
showNow
197198
panelRender={(ori) => <>2333{ori}</>}
@@ -226,7 +227,7 @@ export default () => {
226227
start: 'inputStart',
227228
end: 'inputEnd',
228229
}}
229-
/> */}
230+
/>
230231
<br />
231232

232233
<button

src/PickerInput/hooks/useRangePickerValue.ts

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
33
import * as React from 'react';
44
import type { GenerateConfig } from '../../generate';
55
import type { InternalMode, Locale, PanelMode } from '../../interface';
6-
import { isSame } from '../../utils/dateUtil';
6+
import { fillTime, isSame } from '../../utils/dateUtil';
77
import type { RangePickerProps } from '../RangePicker';
88

99
export function offsetPanelDate<DateType = any>(
@@ -34,28 +34,6 @@ export function offsetPanelDate<DateType = any>(
3434

3535
const EMPTY_LIST = [];
3636

37-
/** Merge the `showTime.defaultValue` into `pickerValue` */
38-
function fillTimePickerValue<DateType>(
39-
generateConfig: GenerateConfig<DateType>,
40-
date: DateType,
41-
timePickerValue?: DateType,
42-
) {
43-
let tmpDate = date;
44-
45-
const getFn = ['getHour', 'getMinute', 'getSecond', 'getMillisecond'] as const;
46-
const setFn = ['setHour', 'setMinute', 'setSecond', 'setMillisecond'] as const;
47-
48-
setFn.forEach((fn, index) => {
49-
if (timePickerValue) {
50-
tmpDate = generateConfig[fn](tmpDate, generateConfig[getFn[index]](timePickerValue));
51-
} else {
52-
tmpDate = generateConfig[fn](tmpDate, 0);
53-
}
54-
});
55-
56-
return tmpDate;
57-
}
58-
5937
export default function useRangePickerValue<DateType extends object, ValueType extends DateType[]>(
6038
generateConfig: GenerateConfig<DateType>,
6139
locale: Locale,
@@ -100,7 +78,8 @@ export default function useRangePickerValue<DateType extends object, ValueType e
10078
// Current PickerValue
10179
const currentPickerValue = React.useMemo(
10280
() =>
103-
fillTimePickerValue(
81+
// Merge the `showTime.defaultValue` into `pickerValue`
82+
fillTime(
10483
generateConfig,
10584
[mergedStartPickerValue, mergedEndPickerValue][mergedActiveIndex],
10685
timeDefaultValue[mergedActiveIndex],

src/PickerPanel/DateTimePanel/index.tsx

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,46 @@
11
import * as React from 'react';
22
import useTimeInfo from '../../hooks/useTimeInfo';
33
import type { SharedPanelProps } from '../../interface';
4+
import { fillTime } from '../../utils/dateUtil';
45
import DatePanel from '../DatePanel';
56
import TimePanel from '../TimePanel';
67

78
export default function DateTimePanel<DateType extends object = any>(
89
props: SharedPanelProps<DateType>,
910
) {
10-
const { prefixCls, generateConfig, showTime, onSelect } = props;
11+
const { prefixCls, generateConfig, showTime, onSelect, value, pickerValue, onHover } = props;
1112

1213
const panelPrefixCls = `${prefixCls}-datetime-panel`;
1314

14-
// ============================== Select ==============================
15+
// =============================== Time ===============================
1516
const [getValidTime] = useTimeInfo(generateConfig, showTime);
1617

18+
// Merge the time info from `value` or `pickerValue`
19+
const mergeTime = (date: DateType) => {
20+
if (value) {
21+
return fillTime(generateConfig, date, value);
22+
}
23+
24+
return fillTime(generateConfig, date, pickerValue);
25+
};
26+
27+
// ============================== Hover ===============================
28+
const onDateHover = (date: DateType) => {
29+
onHover(date ? mergeTime(date) : date);
30+
};
31+
32+
// ============================== Select ==============================
1733
const onDateSelect = (date: DateType) => {
18-
onSelect(getValidTime(date, date));
34+
// Merge with current time
35+
const cloneDate = mergeTime(date);
36+
37+
onSelect(getValidTime(cloneDate, cloneDate));
1938
};
2039

2140
// ============================== Render ==============================
2241
return (
2342
<div className={panelPrefixCls}>
24-
<DatePanel {...props} onSelect={onDateSelect} />
43+
<DatePanel {...props} onSelect={onDateSelect} onHover={onDateHover} />
2544
<TimePanel {...props} />
2645
</div>
2746
);

src/utils/dateUtil.ts

Lines changed: 24 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,6 @@ import type { CustomFormat, InternalMode, Locale, NullableDateType } from '../in
33

44
export const WEEK_DAY_COUNT = 7;
55

6-
// export function isNullEqual<T>(value1: T, value2: T): boolean | undefined {
7-
// if (!value1 && !value2) {
8-
// return true;
9-
// }
10-
// if (!value1 || !value2) {
11-
// return false;
12-
// }
13-
// return undefined;
14-
// }
15-
166
/**
177
* Wrap the compare logic.
188
* This will compare the each of value is empty first.
@@ -79,16 +69,6 @@ export function isSameMonth<DateType>(
7969
month1: NullableDateType<DateType>,
8070
month2: NullableDateType<DateType>,
8171
) {
82-
// const equal = isNullEqual(month1, month2);
83-
// if (typeof equal === 'boolean') {
84-
// return equal;
85-
// }
86-
87-
// return (
88-
// isSameYear(generateConfig, month1, month2) &&
89-
// generateConfig.getMonth(month1!) === generateConfig.getMonth(month2!)
90-
// );
91-
9272
return nullableCompare(
9373
month1,
9474
month2,
@@ -103,17 +83,6 @@ export function isSameDate<DateType>(
10383
date1: NullableDateType<DateType>,
10484
date2: NullableDateType<DateType>,
10585
) {
106-
// const equal = isNullEqual(date1, date2);
107-
// if (typeof equal === 'boolean') {
108-
// return equal;
109-
// }
110-
111-
// return (
112-
// generateConfig.getYear(date1!) === generateConfig.getYear(date2!) &&
113-
// generateConfig.getMonth(date1!) === generateConfig.getMonth(date2!) &&
114-
// generateConfig.getDate(date1!) === generateConfig.getDate(date2!)
115-
// );
116-
11786
return nullableCompare(
11887
date1,
11988
date2,
@@ -129,17 +98,6 @@ export function isSameTime<DateType>(
12998
time1: NullableDateType<DateType>,
13099
time2: NullableDateType<DateType>,
131100
) {
132-
// const equal = isNullEqual(time1, time2);
133-
// if (typeof equal === 'boolean') {
134-
// return equal;
135-
// }
136-
137-
// return (
138-
// generateConfig.getHour(time1!) === generateConfig.getHour(time2!) &&
139-
// generateConfig.getMinute(time1!) === generateConfig.getMinute(time2!) &&
140-
// generateConfig.getSecond(time1!) === generateConfig.getSecond(time2!)
141-
// );
142-
143101
return nullableCompare(
144102
time1,
145103
time2,
@@ -158,15 +116,6 @@ export function isSameTimestamp<DateType>(
158116
time1: NullableDateType<DateType>,
159117
time2: NullableDateType<DateType>,
160118
) {
161-
// return (
162-
// // Same object
163-
// time1 === time2 ||
164-
// // Date
165-
// (isSameDate(generateConfig, time1, time2) &&
166-
// isSameTime(generateConfig, time1, time2) &&
167-
// generateConfig.getMillisecond(time1) === generateConfig.getMillisecond(time2))
168-
// );
169-
170119
return nullableCompare(
171120
time1,
172121
time2,
@@ -183,18 +132,6 @@ export function isSameWeek<DateType>(
183132
date1: NullableDateType<DateType>,
184133
date2: NullableDateType<DateType>,
185134
) {
186-
// const equal = isNullEqual(date1, date2);
187-
// if (typeof equal === 'boolean') {
188-
// return equal;
189-
// }
190-
191-
// const weekStartDate1 = getWeekStartDate(locale, generateConfig, date1);
192-
// const weekStartDate2 = getWeekStartDate(locale, generateConfig, date2);
193-
194-
// return (
195-
// isSameYear(generateConfig, weekStartDate1, weekStartDate2) &&
196-
// generateConfig.locale.getWeek(locale, date1) === generateConfig.locale.getWeek(locale, date2)
197-
// );
198135
return nullableCompare(date1, date2, () => {
199136
const weekStartDate1 = getWeekStartDate(locale, generateConfig, date1);
200137
const weekStartDate2 = getWeekStartDate(locale, generateConfig, date2);
@@ -300,3 +237,27 @@ export function formatValue<DateType>(
300237
? format(value)
301238
: generateConfig.locale.format(locale.locale, value, format);
302239
}
240+
241+
/**
242+
* Fill the time info into Date if provided.
243+
*/
244+
export function fillTime<DateType>(
245+
generateConfig: GenerateConfig<DateType>,
246+
date: DateType,
247+
time?: DateType,
248+
) {
249+
let tmpDate = date;
250+
251+
const getFn = ['getHour', 'getMinute', 'getSecond', 'getMillisecond'] as const;
252+
const setFn = ['setHour', 'setMinute', 'setSecond', 'setMillisecond'] as const;
253+
254+
setFn.forEach((fn, index) => {
255+
if (time) {
256+
tmpDate = generateConfig[fn](tmpDate, generateConfig[getFn[index]](time));
257+
} else {
258+
tmpDate = generateConfig[fn](tmpDate, 0);
259+
}
260+
});
261+
262+
return tmpDate;
263+
}

tests/picker.spec.tsx

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,10 +1287,36 @@ describe('Picker.Basic', () => {
12871287
/>,
12881288
);
12891289

1290-
// console.log(document.body.innerHTML);
1291-
12921290
expect(document.querySelector('.rc-picker-time-panel .rc-picker-header').textContent).toBe(
12931291
'03:05:07',
12941292
);
12951293
});
1294+
1295+
it('select date should keep time with showTime', () => {
1296+
const onCalendarChange = jest.fn();
1297+
const { container } = render(<DayPicker showTime onCalendarChange={onCalendarChange} />);
1298+
1299+
openPicker(container);
1300+
1301+
// Select time column
1302+
selectColumn(0, 13);
1303+
expect(onCalendarChange).toHaveBeenCalledWith(
1304+
expect.anything(),
1305+
'1990-09-03 13:00:00',
1306+
expect.anything(),
1307+
);
1308+
1309+
// Hover date
1310+
const cell = findCell(18);
1311+
fireEvent.mouseEnter(cell);
1312+
expect(container.querySelector('input')).toHaveValue('1990-09-18 13:00:00');
1313+
1314+
// Click to trigger onChange
1315+
fireEvent.click(cell);
1316+
expect(onCalendarChange).toHaveBeenCalledWith(
1317+
expect.anything(),
1318+
'1990-09-18 13:00:00',
1319+
expect.anything(),
1320+
);
1321+
});
12961322
});

0 commit comments

Comments
 (0)