1- import Calendar from " ./calendar" ;
2- import React from " react" ;
3- import PropTypes from " prop-types" ;
4- import PopperComponent , { popperPlacementPositions } from " ./popper_component" ;
5- import classnames from " classnames" ;
1+ import Calendar from ' ./calendar' ;
2+ import React from ' react' ;
3+ import PropTypes from ' prop-types' ;
4+ import PopperComponent , { popperPlacementPositions } from ' ./popper_component' ;
5+ import classnames from ' classnames' ;
66import {
77 newDate ,
88 now ,
@@ -34,13 +34,13 @@ import {
3434 safeDateFormat ,
3535 getHightLightDaysMap ,
3636 getYear ,
37- getMonth
38- } from " ./date_utils" ;
39- import onClickOutside from " react-onclickoutside" ;
37+ getMonth ,
38+ } from ' ./date_utils' ;
39+ import onClickOutside from ' react-onclickoutside' ;
4040
41- export { default as CalendarContainer } from " ./calendar_container" ;
41+ export { default as CalendarContainer } from ' ./calendar_container' ;
4242
43- const outsideClickIgnoreClass = " react-datepicker-ignore-onclickoutside" ;
43+ const outsideClickIgnoreClass = ' react-datepicker-ignore-onclickoutside' ;
4444const WrappedCalendar = onClickOutside ( Calendar ) ;
4545
4646// Compares dates year+month combinations
@@ -65,6 +65,7 @@ function hasSelectionChanged(date1, date2) {
6565/**
6666 * General datepicker component.
6767 */
68+ const INPUT_ERR_1 = 'Date input not valid.' ;
6869
6970export default class DatePicker extends React . Component {
7071 static propTypes = {
@@ -84,7 +85,7 @@ export default class DatePicker extends React.Component {
8485 dayClassName : PropTypes . func ,
8586 disabled : PropTypes . bool ,
8687 disabledKeyboardNavigation : PropTypes . bool ,
87- dropdownMode : PropTypes . oneOf ( [ " scroll" , " select" ] ) . isRequired ,
88+ dropdownMode : PropTypes . oneOf ( [ ' scroll' , ' select' ] ) . isRequired ,
8889 endDate : PropTypes . object ,
8990 excludeDates : PropTypes . array ,
9091 filterDate : PropTypes . func ,
@@ -113,6 +114,7 @@ export default class DatePicker extends React.Component {
113114 onKeyDown : PropTypes . func ,
114115 onMonthChange : PropTypes . func ,
115116 onYearChange : PropTypes . func ,
117+ onInputError : PropTypes . func ,
116118 open : PropTypes . bool ,
117119 openToDate : PropTypes . object ,
118120 peekNextMonth : PropTypes . bool ,
@@ -166,12 +168,12 @@ export default class DatePicker extends React.Component {
166168 static get defaultProps ( ) {
167169 return {
168170 allowSameDay : false ,
169- dateFormat : "L" ,
170- dateFormatCalendar : " MMMM YYYY" ,
171+ dateFormat : 'L' ,
172+ dateFormatCalendar : ' MMMM YYYY' ,
171173 onChange ( ) { } ,
172174 disabled : false ,
173175 disabledKeyboardNavigation : false ,
174- dropdownMode : " scroll" ,
176+ dropdownMode : ' scroll' ,
175177 onFocus ( ) { } ,
176178 onBlur ( ) { } ,
177179 onKeyDown ( ) { } ,
@@ -181,15 +183,16 @@ export default class DatePicker extends React.Component {
181183 onMonthChange ( ) { } ,
182184 preventOpenOnFocus : false ,
183185 onYearChange ( ) { } ,
186+ onInputError ( ) { } ,
184187 monthsShown : 1 ,
185188 readOnly : false ,
186189 withPortal : false ,
187190 shouldCloseOnSelect : true ,
188191 showTimeSelect : false ,
189192 timeIntervals : 30 ,
190- timeCaption : " Time" ,
191- previousMonthButtonLabel : " Previous Month" ,
192- nextMonthButtonLabel : " Next month"
193+ timeCaption : ' Time' ,
194+ previousMonthButtonLabel : ' Previous Month' ,
195+ nextMonthButtonLabel : ' Next month' ,
193196 } ;
194197 }
195198
@@ -207,7 +210,7 @@ export default class DatePicker extends React.Component {
207210 }
208211 if ( prevProps . highlightDates !== this . props . highlightDates ) {
209212 this . setState ( {
210- highlightDates : getHightLightDaysMap ( this . props . highlightDates )
213+ highlightDates : getHightLightDaysMap ( this . props . highlightDates ) ,
211214 } ) ;
212215 }
213216 if (
@@ -250,7 +253,7 @@ export default class DatePicker extends React.Component {
250253 // transforming highlighted days (perhaps nested array)
251254 // to flat Map for faster access in day.jsx
252255 highlightDates : getHightLightDaysMap ( this . props . highlightDates ) ,
253- focused : false
256+ focused : false ,
254257 } ;
255258 } ;
256259
@@ -273,9 +276,11 @@ export default class DatePicker extends React.Component {
273276 open && this . state . open
274277 ? this . state . preSelection
275278 : this . calcInitialState ( ) . preSelection ,
276- lastPreSelectChange : PRESELECT_CHANGE_VIA_NAVIGATE
279+ lastPreSelectChange : PRESELECT_CHANGE_VIA_NAVIGATE ,
277280 } ) ;
278281 } ;
282+ inputOk = ( ) =>
283+ isMoment ( this . state . preSelection ) || isDate ( this . state . preSelection ) ;
279284
280285 isCalendarOpen = ( ) =>
281286 this . props . open === undefined
@@ -330,15 +335,15 @@ export default class DatePicker extends React.Component {
330335 if ( this . props . onChangeRaw ) {
331336 this . props . onChangeRaw . apply ( this , allArgs ) ;
332337 if (
333- typeof event . isDefaultPrevented !== " function" ||
338+ typeof event . isDefaultPrevented !== ' function' ||
334339 event . isDefaultPrevented ( )
335340 ) {
336341 return ;
337342 }
338343 }
339344 this . setState ( {
340345 inputValue : event . target . value ,
341- lastPreSelectChange : PRESELECT_CHANGE_VIA_INPUT
346+ lastPreSelectChange : PRESELECT_CHANGE_VIA_INPUT ,
342347 } ) ;
343348 const date = parseDate ( event . target . value , this . props ) ;
344349 if ( date || ! event . target . value ) {
@@ -352,7 +357,7 @@ export default class DatePicker extends React.Component {
352357 this . setState ( { preventFocus : true } , ( ) => {
353358 this . preventFocusTimeout = setTimeout (
354359 ( ) => this . setState ( { preventFocus : false } ) ,
355- 50
360+ 50 ,
356361 ) ;
357362 return this . preventFocusTimeout ;
358363 } ) ;
@@ -391,12 +396,12 @@ export default class DatePicker extends React.Component {
391396 changedDate = setTime ( newDate ( changedDate ) , {
392397 hour : getHour ( selected ) ,
393398 minute : getMinute ( selected ) ,
394- second : getSecond ( selected )
399+ second : getSecond ( selected ) ,
395400 } ) ;
396401 }
397402 if ( ! this . props . inline ) {
398403 this . setState ( {
399- preSelection : changedDate
404+ preSelection : changedDate ,
400405 } ) ;
401406 }
402407 }
@@ -412,15 +417,15 @@ export default class DatePicker extends React.Component {
412417
413418 setPreSelection = date => {
414419 const isDateRangePresent =
415- typeof this . props . minDate !== " undefined" &&
416- typeof this . props . maxDate !== " undefined" ;
420+ typeof this . props . minDate !== ' undefined' &&
421+ typeof this . props . maxDate !== ' undefined' ;
417422 const isValidDateSelection =
418423 isDateRangePresent && date
419424 ? isDayInRange ( date , this . props . minDate , this . props . maxDate )
420425 : true ;
421426 if ( isValidDateSelection ) {
422427 this . setState ( {
423- preSelection : date
428+ preSelection : date ,
424429 } ) ;
425430 }
426431 } ;
@@ -431,11 +436,11 @@ export default class DatePicker extends React.Component {
431436 : this . getPreSelection ( ) ;
432437 let changedDate = setTime ( cloneDate ( selected ) , {
433438 hour : getHour ( time ) ,
434- minute : getMinute ( time )
439+ minute : getMinute ( time ) ,
435440 } ) ;
436441
437442 this . setState ( {
438- preSelection : changedDate
443+ preSelection : changedDate ,
439444 } ) ;
440445
441446 this . props . onChange ( changedDate ) ;
@@ -459,17 +464,16 @@ export default class DatePicker extends React.Component {
459464 ! this . props . inline &&
460465 ! this . props . preventOpenOnFocus
461466 ) {
462- if ( eventKey === " ArrowDown" || eventKey === " ArrowUp" ) {
467+ if ( eventKey === ' ArrowDown' || eventKey === ' ArrowUp' ) {
463468 this . onInputClick ( ) ;
464469 }
465470 return ;
466471 }
467472 const copy = newDate ( this . state . preSelection ) ;
468- if ( eventKey === " Enter" ) {
473+ if ( eventKey === ' Enter' ) {
469474 event . preventDefault ( ) ;
470475 if (
471- ( isMoment ( this . state . preSelection ) ||
472- isDate ( this . state . preSelection ) ) &&
476+ this . inputOk ( ) &&
473477 this . state . lastPreSelectChange === PRESELECT_CHANGE_VIA_NAVIGATE
474478 ) {
475479 this . handleSelect ( copy , event ) ;
@@ -481,45 +485,53 @@ export default class DatePicker extends React.Component {
481485
482486 this . setOpen ( false ) ;
483487 }
484- } else if ( eventKey === " Escape" ) {
488+ } else if ( eventKey === ' Escape' ) {
485489 event . preventDefault ( ) ;
486490
487491 this . input . blur ( ) ;
488492 this . props . onBlur ( copy ) ;
489493 this . cancelFocusInput ( ) ;
490494
491495 this . setOpen ( false ) ;
492- } else if ( eventKey === "Tab" ) {
496+ if ( ! this . inputOk ( ) ) {
497+ this . props . onInputError ( { code : 1 , msg : INPUT_ERR_1 } ) ;
498+ }
499+ } else if ( eventKey === 'Tab' ) {
493500 this . setOpen ( false ) ;
494501 } else if ( ! this . props . disabledKeyboardNavigation ) {
495502 let newSelection ;
496503 switch ( eventKey ) {
497- case " ArrowLeft" :
504+ case ' ArrowLeft' :
498505 newSelection = subtractDays ( copy , 1 ) ;
499506 break ;
500- case " ArrowRight" :
507+ case ' ArrowRight' :
501508 newSelection = addDays ( copy , 1 ) ;
502509 break ;
503- case " ArrowUp" :
510+ case ' ArrowUp' :
504511 newSelection = subtractWeeks ( copy , 1 ) ;
505512 break ;
506- case " ArrowDown" :
513+ case ' ArrowDown' :
507514 newSelection = addWeeks ( copy , 1 ) ;
508515 break ;
509- case " PageUp" :
516+ case ' PageUp' :
510517 newSelection = subtractMonths ( copy , 1 ) ;
511518 break ;
512- case " PageDown" :
519+ case ' PageDown' :
513520 newSelection = addMonths ( copy , 1 ) ;
514521 break ;
515- case " Home" :
522+ case ' Home' :
516523 newSelection = subtractYears ( copy , 1 ) ;
517524 break ;
518- case " End" :
525+ case ' End' :
519526 newSelection = addYears ( copy , 1 ) ;
520527 break ;
521528 }
522- if ( ! newSelection ) return ; // Let the input component handle this keydown
529+ if ( ! newSelection ) {
530+ if ( this . props . onInputError ) {
531+ this . props . onInputError ( { code : 1 , msg : INPUT_ERR_1 } ) ;
532+ }
533+ return ; // Let the input component handle this keydown
534+ }
523535 event . preventDefault ( ) ;
524536 this . setState ( { lastPreSelectChange : PRESELECT_CHANGE_VIA_NAVIGATE } ) ;
525537 if ( this . props . adjustDateOnChange ) {
@@ -628,11 +640,11 @@ export default class DatePicker extends React.Component {
628640 } ) ;
629641
630642 const customInput = this . props . customInput || < input type = "text" /> ;
631- const customInputRef = this . props . customInputRef || " ref" ;
643+ const customInputRef = this . props . customInputRef || ' ref' ;
632644 const inputValue =
633- typeof this . props . value === " string"
645+ typeof this . props . value === ' string'
634646 ? this . props . value
635- : typeof this . state . inputValue === " string"
647+ : typeof this . state . inputValue === ' string'
636648 ? this . state . inputValue
637649 : safeDateFormat ( this . props . selected , this . props ) ;
638650
@@ -656,7 +668,7 @@ export default class DatePicker extends React.Component {
656668 title : this . props . title ,
657669 readOnly : this . props . readOnly ,
658670 required : this . props . required ,
659- tabIndex : this . props . tabIndex
671+ tabIndex : this . props . tabIndex ,
660672 } ) ;
661673 } ;
662674
@@ -718,5 +730,5 @@ export default class DatePicker extends React.Component {
718730 }
719731}
720732
721- const PRESELECT_CHANGE_VIA_INPUT = " input" ;
722- const PRESELECT_CHANGE_VIA_NAVIGATE = " navigate" ;
733+ const PRESELECT_CHANGE_VIA_INPUT = ' input' ;
734+ const PRESELECT_CHANGE_VIA_NAVIGATE = ' navigate' ;
0 commit comments