@@ -27,14 +27,14 @@ import type { DateRender } from './panels/DatePanel/DateBody';
2727import DatetimePanel from './panels/DatetimePanel' ;
2828import DecadePanel from './panels/DecadePanel' ;
2929import MonthPanel from './panels/MonthPanel' ;
30- import type { MonthCellRender } from './panels/MonthPanel/MonthBody' ;
30+ import { MONTH_COL_COUNT , type MonthCellRender } from './panels/MonthPanel/MonthBody' ;
3131import QuarterPanel from './panels/QuarterPanel' ;
3232import type { SharedTimeProps } from './panels/TimePanel' ;
3333import TimePanel from './panels/TimePanel' ;
3434import WeekPanel from './panels/WeekPanel' ;
3535import YearPanel from './panels/YearPanel' ;
3636import RangeContext from './RangeContext' ;
37- import { isEqual } from './utils/dateUtil' ;
37+ import { isEqual , WEEK_DAY_COUNT } from './utils/dateUtil' ;
3838import getExtraFooter from './utils/getExtraFooter' ;
3939import getRanges from './utils/getRanges' ;
4040import { getLowerBoundTime , setDateTime , setTime } from './utils/timeUtil' ;
@@ -125,6 +125,9 @@ type MergedPickerPanelProps<DateType> = {
125125 picker ?: PickerMode ;
126126} & OmitType < DateType > ;
127127
128+ // Calendar picker type
129+ const CALENDAR_PANEL_MODE : PanelMode [ ] = [ 'date' , 'month' ] ;
130+
128131function PickerPanel < DateType > ( props : PickerPanelProps < DateType > ) {
129132 const {
130133 prefixCls = 'rc-picker' ,
@@ -297,9 +300,49 @@ function PickerPanel<DateType>(props: PickerPanelProps<DateType>) {
297300 }
298301 } ;
299302
303+ const isSelectable = ( key ) => {
304+ if ( CALENDAR_PANEL_MODE . includes ( mergedMode ) ) {
305+ let date ;
306+ let operationFnc ;
307+ const isDateMode = mergedMode === 'date' ;
308+ if ( key === KeyCode . PAGE_UP || key === KeyCode . PAGE_DOWN ) {
309+ operationFnc = isDateMode ? generateConfig . addMonth : generateConfig . addYear ;
310+ } else {
311+ operationFnc = isDateMode ? generateConfig . addDate : generateConfig . addMonth ;
312+ }
313+
314+ switch ( key ) {
315+ case KeyCode . LEFT :
316+ case KeyCode . PAGE_UP :
317+ date = operationFnc ( viewDate , - 1 ) ;
318+ break ;
319+ case KeyCode . RIGHT :
320+ case KeyCode . PAGE_DOWN :
321+ date = operationFnc ( viewDate , 1 ) ;
322+ break ;
323+ case KeyCode . UP :
324+ case KeyCode . DOWN :
325+ date = operationFnc (
326+ viewDate ,
327+ Number (
328+ `${ key === KeyCode . UP ? '-' : '' } ${ isDateMode ? WEEK_DAY_COUNT : MONTH_COL_COUNT } ` ,
329+ ) ,
330+ ) ;
331+ break ;
332+ }
333+
334+ if ( date ) {
335+ return ! disabledDate ?.( date ) ;
336+ }
337+ }
338+ return true ;
339+ } ;
340+
300341 // ========================= Interactive ==========================
301342 const onInternalKeyDown = ( e : React . KeyboardEvent < HTMLElement > ) => {
302343 if ( panelRef . current && panelRef . current . onKeyDown ) {
344+ let selectable = true ;
345+ const { which } = e ;
303346 if (
304347 [
305348 KeyCode . LEFT ,
@@ -309,11 +352,18 @@ function PickerPanel<DateType>(props: PickerPanelProps<DateType>) {
309352 KeyCode . PAGE_UP ,
310353 KeyCode . PAGE_DOWN ,
311354 KeyCode . ENTER ,
312- ] . includes ( e . which )
355+ ] . includes ( which )
313356 ) {
314357 e . preventDefault ( ) ;
358+ if ( which !== KeyCode . ENTER && tabIndex === 0 ) {
359+ selectable = isSelectable ( which ) ;
360+ }
361+ }
362+
363+ // Cannot use keyboard to select disabled date
364+ if ( selectable ) {
365+ return panelRef . current . onKeyDown ( e ) ;
315366 }
316- return panelRef . current . onKeyDown ( e ) ;
317367 }
318368
319369 /* istanbul ignore next */
@@ -379,7 +429,6 @@ function PickerPanel<DateType>(props: PickerPanelProps<DateType>) {
379429 delete pickerProps . onChange ;
380430 delete pickerProps . onSelect ;
381431
382-
383432 switch ( mergedMode ) {
384433 case 'decade' :
385434 panelNode = (
0 commit comments