@@ -10,6 +10,7 @@ export default class Year extends React.Component {
10
10
disabledKeyboardNavigation : PropTypes . bool ,
11
11
onDayClick : PropTypes . func ,
12
12
preSelection : PropTypes . instanceOf ( Date ) ,
13
+ setPreSelection : PropTypes . func ,
13
14
selected : PropTypes . object ,
14
15
inline : PropTypes . bool ,
15
16
maxDate : PropTypes . instanceOf ( Date ) ,
@@ -21,12 +22,42 @@ export default class Year extends React.Component {
21
22
super ( props ) ;
22
23
}
23
24
25
+ YEAR_REFS = [ ...Array ( this . props . yearItemNumber ) ] . map ( ( ) =>
26
+ React . createRef ( )
27
+ ) ;
28
+
29
+ isDisabled = ( date ) => utils . isDayDisabled ( date , this . props ) ;
30
+
31
+ isExcluded = ( date ) => utils . isDayExcluded ( date , this . props ) ;
32
+
33
+ updateFocusOnPaginate = ( refIndex ) => {
34
+ const waitForReRender = function ( ) {
35
+ this . YEAR_REFS [ refIndex ] . current . focus ( ) ;
36
+ } . bind ( this ) ;
37
+
38
+ window . requestAnimationFrame ( waitForReRender ) ;
39
+ } ;
40
+
24
41
handleYearClick = ( day , event ) => {
25
42
if ( this . props . onDayClick ) {
26
43
this . props . onDayClick ( day , event ) ;
27
44
}
28
45
} ;
29
46
47
+ handleYearNavigation = ( newYear , newDate ) => {
48
+ const { date, yearItemNumber } = this . props ;
49
+ const { startPeriod } = utils . getYearsPeriod ( date , yearItemNumber ) ;
50
+
51
+ if ( this . isDisabled ( newDate ) || this . isExcluded ( newDate ) ) return ;
52
+ this . props . setPreSelection ( newDate ) ;
53
+
54
+ if ( newYear - startPeriod === - 1 ) {
55
+ this . updateFocusOnPaginate ( yearItemNumber - 1 ) ;
56
+ } else if ( newYear - startPeriod === yearItemNumber ) {
57
+ this . updateFocusOnPaginate ( 0 ) ;
58
+ } else this . YEAR_REFS [ newYear - startPeriod ] . current . focus ( ) ;
59
+ } ;
60
+
30
61
isSameDay = ( y , other ) => utils . isSameDay ( y , other ) ;
31
62
32
63
isKeyboardSelected = ( y ) => {
@@ -44,6 +75,30 @@ export default class Year extends React.Component {
44
75
this . handleYearClick ( utils . getStartOfYear ( utils . setYear ( date , y ) ) , e ) ;
45
76
} ;
46
77
78
+ onYearKeyDown = ( e , y ) => {
79
+ const { key } = e ;
80
+ if ( ! this . props . disabledKeyboardNavigation ) {
81
+ switch ( key ) {
82
+ case "Enter" :
83
+ this . onYearClick ( e , y ) ;
84
+ this . props . setPreSelection ( this . props . selected ) ;
85
+ break ;
86
+ case "ArrowRight" :
87
+ this . handleYearNavigation (
88
+ y + 1 ,
89
+ utils . addYears ( this . props . preSelection , 1 )
90
+ ) ;
91
+ break ;
92
+ case "ArrowLeft" :
93
+ this . handleYearNavigation (
94
+ y - 1 ,
95
+ utils . subYears ( this . props . preSelection , 1 )
96
+ ) ;
97
+ break ;
98
+ }
99
+ }
100
+ } ;
101
+
47
102
getYearClassNames = ( y ) => {
48
103
const { minDate, maxDate, selected } = this . props ;
49
104
return classnames ( "react-datepicker__year-text" , {
@@ -56,6 +111,13 @@ export default class Year extends React.Component {
56
111
} ) ;
57
112
} ;
58
113
114
+ getYearTabIndex = ( y ) => {
115
+ if ( this . props . disabledKeyboardNavigation ) return "-1" ;
116
+ const preSelected = utils . getYear ( this . props . preSelection ) ;
117
+
118
+ return y === preSelected ? "0" : "-1" ;
119
+ } ;
120
+
59
121
render ( ) {
60
122
const yearsList = [ ] ;
61
123
const { date, yearItemNumber } = this . props ;
@@ -67,16 +129,22 @@ export default class Year extends React.Component {
67
129
for ( let y = startPeriod ; y <= endPeriod ; y ++ ) {
68
130
yearsList . push (
69
131
< div
132
+ ref = { this . YEAR_REFS [ y - startPeriod ] }
70
133
onClick = { ( ev ) => {
71
134
this . onYearClick ( ev , y ) ;
72
135
} }
136
+ onKeyDown = { ( ev ) => {
137
+ this . onYearKeyDown ( ev , y ) ;
138
+ } }
139
+ tabIndex = { this . getYearTabIndex ( y ) }
73
140
className = { this . getYearClassNames ( y ) }
74
141
key = { y }
75
142
>
76
143
{ y }
77
144
</ div >
78
145
) ;
79
146
}
147
+
80
148
return (
81
149
< div className = "react-datepicker__year" >
82
150
< div className = "react-datepicker__year-wrapper" > { yearsList } </ div >
0 commit comments