From d7bb8fb74c7d8bb232d26bfdb8fafa7e35dd920f Mon Sep 17 00:00:00 2001 From: dogle <15707274049@163.com> Date: Thu, 3 Sep 2026 16:34:12 +0800 Subject: [PATCH] fix: use current time in time picker disabledTime --- src/PickerInput/RangePicker.tsx | 6 ++- src/PickerInput/SinglePicker.tsx | 17 ++++++- src/PickerInput/hooks/useInvalidate.ts | 3 +- tests/disabledTime.spec.tsx | 66 ++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/PickerInput/RangePicker.tsx b/src/PickerInput/RangePicker.tsx index 36c2dda2e..9d5084c2c 100644 --- a/src/PickerInput/RangePicker.tsx +++ b/src/PickerInput/RangePicker.tsx @@ -369,14 +369,16 @@ function RangePicker( ? (date: DateType) => { const range = getActiveRange(activeIndex); const fromDate = getFromDate(calendarValue, triggeredFields, activeIndex); - return disabledTime(date, range, { + const targetDate = picker === 'time' ? generateConfig.getNow() : date; + + return disabledTime(targetDate, range, { from: fromDate, }); } : undefined; return { ...showTime, disabledTime: proxyDisabledTime }; - }, [showTime, activeIndex, calendarValue, triggeredFields]); + }, [showTime, activeIndex, calendarValue, triggeredFields, picker, generateConfig]); // ========================= Mode ========================= const [modes, setModes] = useControlledState<[PanelMode, PanelMode]>([picker, picker], mode); diff --git a/src/PickerInput/SinglePicker.tsx b/src/PickerInput/SinglePicker.tsx index 96f221906..9e57afa80 100644 --- a/src/PickerInput/SinglePicker.tsx +++ b/src/PickerInput/SinglePicker.tsx @@ -356,6 +356,21 @@ function Picker( [mergedOpen], ); + // ======================= ShowTime ======================= + /** Used for Popup panel */ + const mergedShowTime = React.useMemo>(() => { + if (!showTime) { + return null; + } + + const { disabledTime } = showTime; + const proxyDisabledTime = disabledTime + ? (date: DateType) => disabledTime(picker === 'time' ? generateConfig.getNow() : date) + : undefined; + + return { ...showTime, disabledTime: proxyDisabledTime }; + }, [showTime, picker, generateConfig]); + // ======================= Validate ======================= const [submitInvalidates, onSelectorInvalid] = useFieldsInvalidate( calendarValue, @@ -561,7 +576,7 @@ function Picker( // MISC {...panelProps} showNow={mergedShowNow} - showTime={showTime} + showTime={mergedShowTime} // Disabled disabledDate={disabledDate} // Focus diff --git a/src/PickerInput/hooks/useInvalidate.ts b/src/PickerInput/hooks/useInvalidate.ts index df907bb6a..7b8d704f8 100644 --- a/src/PickerInput/hooks/useInvalidate.ts +++ b/src/PickerInput/hooks/useInvalidate.ts @@ -33,8 +33,9 @@ export default function useInvalidate( if ((picker === 'date' || picker === 'time') && showTime) { const range = info && info.activeIndex === 1 ? 'end' : 'start'; + const targetDate = picker === 'time' ? generateConfig.getNow() : date; const { disabledHours, disabledMinutes, disabledSeconds, disabledMilliseconds } = - showTime.disabledTime?.(date, range, { from: outsideInfo.from }) || {}; + showTime.disabledTime?.(targetDate, range, { from: outsideInfo.from }) || {}; const { disabledHours: legacyDisabledHours, diff --git a/tests/disabledTime.spec.tsx b/tests/disabledTime.spec.tsx index 7149975cf..028035585 100644 --- a/tests/disabledTime.spec.tsx +++ b/tests/disabledTime.spec.tsx @@ -15,6 +15,13 @@ import { const fakeTime = getDay('1990-09-03 00:00:00').valueOf(); +function getHourTexts() { + return Array.from( + document.querySelector('.rc-picker-time-panel-column').querySelectorAll('li'), + (cell) => cell.textContent, + ); +} + describe('Picker.DisabledTime', () => { beforeEach(() => { resetWarned(); @@ -44,6 +51,39 @@ describe('Picker.DisabledTime', () => { ).toHaveLength(59); }); + it('uses current time for disabledTime on TimePicker', () => { + jest.setSystemTime(getDay('1990-09-03 12:00:00').valueOf()); + const disabledTime = jest.fn((now: Dayjs) => ({ + disabledHours: () => [now.hour()], + })); + + render(); + + expect(getHourTexts()).not.toContain('12'); + expect(getHourTexts()).toContain('14'); + + const callCountBeforeSelect = disabledTime.mock.calls.length; + selectCell('14'); + + expect(disabledTime.mock.calls.length).toBeGreaterThan(callCountBeforeSelect); + disabledTime.mock.calls.forEach(([now]) => { + expect(now.hour()).toBe(12); + }); + expect(getHourTexts()).not.toContain('12'); + expect(getHourTexts()).toContain('14'); + }); + + it('uses selected date for disabledTime on DatePicker with showTime', () => { + const disabledTime = jest.fn((date: Dayjs) => ({ + disabledHours: () => [date.hour() + 1], + })); + const selectedDate = getDay('1989-11-28 14:00:00'); + + render(); + + expect(disabledTime.mock.calls.some(([date]) => date.isSame(selectedDate, 'day'))).toBeTruthy(); + }); + it('disabledTime on TimeRangePicker', () => { const { container } = render( { ).toHaveLength(2); }); + it('uses current time for disabledTime on TimeRangePicker', () => { + jest.setSystemTime(getDay('1990-09-03 12:00:00').valueOf()); + const disabledTime = jest.fn((now: Dayjs) => ({ + disabledHours: () => [now.hour()], + })); + + const { container } = render( + , + ); + + openPicker(container); + + expect(getHourTexts()).not.toContain('12'); + expect(getHourTexts()).toContain('14'); + + const callCountBeforeSelect = disabledTime.mock.calls.length; + selectCell('14'); + + expect(disabledTime.mock.calls.length).toBeGreaterThan(callCountBeforeSelect); + disabledTime.mock.calls.forEach(([now]) => { + expect(now.hour()).toBe(12); + }); + expect(getHourTexts()).not.toContain('12'); + expect(getHourTexts()).toContain('14'); + }); + it('disabledTime', async () => { /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ const disabledTime = jest.fn((_: Dayjs | null, __: 'start' | 'end') => {