@@ -25,22 +25,22 @@ const dateRangeSeparator = ' - ';
2525class DatePicker extends Component {
2626 constructor ( props ) {
2727 super ( props ) ;
28- const formattedDate = props . defaultValue . length > 0 ? this . getFormattedDateStr ( props . defaultValue ) : '' ;
29- const isoFormattedDate = props . defaultValue . length > 0
30- ? moment ( props . defaultValue , props . dateFormat ) . format ( ISO_DATE_FORMAT )
31- : '' ;
28+
3229 this . state = {
33- isExpanded : false ,
34- selectedDate : formattedDate . length === 0 ? null : this . getMomentDateObj ( formattedDate ) ,
35- startAndEndDates : [ ] ,
36- formattedDate,
37- isoFormattedDate
30+ formattedDate : this . props ?. defaultValue || '' ,
31+ isExpanded : false
3832 } ;
3933
4034 this . calendarRef = React . createRef ( ) ;
4135 this . popoverRef = React . createRef ( ) ;
4236 }
4337
38+
39+ toISOFormat = ( dateStr ) => {
40+ if ( ! dateStr || ! dateStr ?. trim ( ) . length ) return '' ;
41+ return moment ( dateStr , this . resolveFormat ( ) ) . format ( ISO_DATE_FORMAT ) ;
42+ }
43+
4444 /**
4545 * Function tries to format any date string into the format specified by dateFormat.
4646 * It will use format derived from locale if dateFormat is not specified.
@@ -122,22 +122,20 @@ class DatePicker extends Component {
122122 this . setState ( { formattedDate : e . target . value } ) ;
123123 }
124124
125+ componentDidMount ( ) {
126+ this . validateDates ( ) ;
127+ }
128+
125129 componentDidUpdate ( prevProps ) {
126130 if ( prevProps . defaultValue !== this . props . defaultValue ) {
127131 this . handleNewDefault ( ) ;
128132 }
129133 }
130134
131135 handleNewDefault = ( ) => {
132- const { dateFormat, defaultValue } = this . props ;
133- const formattedNewDefault = defaultValue && defaultValue . length > 0 ? this . getFormattedDateStr ( defaultValue ) : '' ;
136+ const { defaultValue } = this . props ;
134137 this . setState ( {
135- selectedDate : formattedNewDefault . length === 0 ? null : this . getMomentDateObj ( formattedNewDefault ) ,
136- isoFormattedDate : defaultValue && defaultValue . length > 0
137- ? moment ( defaultValue , dateFormat ) . format ( ISO_DATE_FORMAT )
138- : '' ,
139- formattedDate : formattedNewDefault ,
140- startAndEndDates : [ ]
138+ formattedDate : defaultValue
141139 } , ( ) => {
142140 this . validateDates ( ) ;
143141 } ) ;
@@ -147,9 +145,7 @@ class DatePicker extends Component {
147145 e . stopPropagation ( ) ;
148146 this . setState ( {
149147 formattedDate : e . target . value ,
150- isoFormattedDate : e . target . value
151- ? moment ( e . target . value , this . props . dateFormat ) . format ( ISO_DATE_FORMAT )
152- : ''
148+ isoFormattedDate : this . toISOFormat ( e . target ?. value )
153149 } , ( ) => {
154150 this . props . onChange ( this . getCallbackData ( ) , 'inputChange' ) ;
155151 } ) ;
@@ -183,7 +179,9 @@ class DatePicker extends Component {
183179 validateDates = ( postValidationCallback ) => {
184180 const { formattedDate } = this . state ;
185181
186- if ( this . props . enableRangeSelection ) {
182+ if ( ! formattedDate || ! formattedDate ?. trim ( ) . length ) {
183+ this . resetState ( postValidationCallback ) ;
184+ } else if ( this . props . enableRangeSelection ) {
187185 const dateRange = formattedDate . split ( dateRangeSeparator ) ;
188186 const firstDate = this . getMomentDateObj ( dateRange [ 0 ] ) ;
189187 const secondDate = this . getMomentDateObj ( dateRange [ 1 ] ) ;
@@ -195,9 +193,10 @@ class DatePicker extends Component {
195193 : ( arrSelected = [ firstDate , secondDate ] ) ;
196194 const newFormattedDateRangeStr = this . getFormattedDateRangeStr ( arrSelected ) ;
197195 this . setState ( {
196+ formattedDate : newFormattedDateRangeStr ,
197+ isoFormatDate : arrSelected [ 0 ] . format ( ISO_DATE_FORMAT ) + dateRangeSeparator + arrSelected [ 1 ] . format ( ISO_DATE_FORMAT ) ,
198198 selectedDate : null ,
199- startAndEndDates : arrSelected ,
200- formattedDate : newFormattedDateRangeStr
199+ startAndEndDates : arrSelected
201200 } , ( ) => {
202201 if ( formattedDate !== newFormattedDateRangeStr ) {
203202 this . executeCallback ( this . props . onChange , 'autoFormatDateRange' ) ;
@@ -214,9 +213,7 @@ class DatePicker extends Component {
214213 this . setState ( {
215214 selectedDate : newDate ,
216215 formattedDate : newFormattedDateStr ,
217- isoFormattedDate : formattedDate
218- ? moment ( formattedDate , this . props . dateFormat ) . format ( ISO_DATE_FORMAT )
219- : '' ,
216+ isoFormattedDate : newDate . format ( ISO_DATE_FORMAT ) ,
220217 startAndEndDates : [ ]
221218 } , ( ) => {
222219 if ( formattedDate !== newFormattedDateStr ) {
@@ -267,16 +264,17 @@ class DatePicker extends Component {
267264 const { formattedDate } = this . state ;
268265
269266 if ( this . props . enableRangeSelection ) {
270- let isoFormatDate = date [ 0 ] . format ( ISO_DATE_FORMAT ) ;
267+ let isoFormatDateRange = date [ 0 ] . format ( ISO_DATE_FORMAT ) ;
271268 if ( ! ! date [ 1 ] ) {
272- isoFormatDate += dateRangeSeparator + date [ 1 ] . format ( ISO_DATE_FORMAT ) ;
269+ isoFormatDateRange += dateRangeSeparator + date [ 1 ] . format ( ISO_DATE_FORMAT ) ;
273270 closeCalendar = true ;
274271 }
275272 const newFormattedDateRangeStr = this . getFormattedDateRangeStr ( date ) ;
276273 this . setState ( {
277- startAndEndDates : date ,
278274 formattedDate : newFormattedDateRangeStr ,
279- isoFormattedDate : isoFormatDate
275+ isoFormattedDate : isoFormatDateRange ,
276+ selectedDate : null ,
277+ startAndEndDates : date
280278 } , ( ) => {
281279 if ( formattedDate !== newFormattedDateRangeStr ) {
282280 this . props . onChange ( this . getCallbackData ( ) , reason ) ;
@@ -286,9 +284,9 @@ class DatePicker extends Component {
286284 closeCalendar = true ;
287285 const newFormattedDate = this . getFormattedDateStr ( date ) ;
288286 this . setState ( {
289- selectedDate : date ,
290287 formattedDate : newFormattedDate ,
291- isoFormattedDate : date . format ( ISO_DATE_FORMAT ) ,
288+ isoFormattedDate : this . toISOFormat ( newFormattedDate ) ,
289+ selectedDate : date ,
292290 startAndEndDates : [ ]
293291 } , ( ) => {
294292 if ( formattedDate !== newFormattedDate ) {
@@ -341,6 +339,7 @@ class DatePicker extends Component {
341339
342340 render ( ) {
343341 const {
342+ addonProps,
344343 blockedDates,
345344 buttonLabel,
346345 buttonProps,
@@ -356,6 +355,8 @@ class DatePicker extends Component {
356355 disableWeekday,
357356 disableWeekends,
358357 enableRangeSelection,
358+ footerButtonProps,
359+ footerClasses,
359360 inputProps,
360361 inputGroupProps,
361362 locale,
@@ -380,7 +381,8 @@ class DatePicker extends Component {
380381 'fd-input-group--control' ,
381382 {
382383 [ `is-${ validationState ?. state } ` ] : validationState ?. state
383- }
384+ } ,
385+ inputGroupProps ?. className
384386 ) ;
385387
386388 const datepickerFooterClassName = classnames (
@@ -390,7 +392,13 @@ class DatePicker extends Component {
390392 {
391393 'fd-bar--cozy' : ! compact ,
392394 'fd-bar--compact' : compact
393- }
395+ } ,
396+ footerClasses
397+ ) ;
398+
399+ const footerButtonClassnames = classnames (
400+ 'fd-dialog__decisive-button' ,
401+ footerButtonProps ?. className
394402 ) ;
395403
396404 const disableButton = disabled || readOnly ;
@@ -414,7 +422,9 @@ class DatePicker extends Component {
414422 placeholder = { this . getPlaceHolder ( dateFormat ) }
415423 readOnly = { readOnly }
416424 value = { this . state . formattedDate } />
417- < InputGroup . Addon isButton >
425+ < InputGroup . Addon
426+ { ...addonProps }
427+ isButton >
418428 < Button { ...buttonProps }
419429 aria-label = { buttonLabel }
420430 disabled = { disableButton }
@@ -471,8 +481,8 @@ class DatePicker extends Component {
471481 ...localizedText ,
472482 todayLabel : todayAction . label
473483 } }
474- onChange = { ( e , todayNavigated ) => {
475- this . updateDate ( e , todayNavigated , todayNavigated ? 'todayNavigated' : 'calendarDateClicked' ) ;
484+ onChange = { ( date , todayNavigated ) => {
485+ this . updateDate ( date , todayNavigated , todayNavigated ? 'todayNavigated' : 'calendarDateClicked' ) ;
476486 } }
477487 openToDate = { openToDate }
478488 ref = { this . calendarRef }
@@ -484,7 +494,8 @@ class DatePicker extends Component {
484494 < div className = 'fd-bar__right' >
485495 < div className = 'fd-bar__element' >
486496 < Button
487- className = 'fd-dialog__decisive-button'
497+ { ...footerButtonProps }
498+ className = { footerButtonClassnames }
488499 compact = { compact }
489500 onClick = { this . setTodayDate } >
490501 { todayAction . label }
@@ -513,6 +524,8 @@ DatePicker.displayName = 'DatePicker';
513524
514525DatePicker . propTypes = {
515526 ...Calendar . PropTypes ,
527+ /** Additional props to be spread to the input group addon button container i.e. `<InputGroup.Addon {...addonProps} >` */
528+ addonProps : PropTypes . object ,
516529 /** aria-label for datepicker button */
517530 buttonLabel : PropTypes . string ,
518531 /** Additional props to be spread to the `<button>` element */
@@ -529,12 +542,20 @@ DatePicker.propTypes = {
529542 /** Format to use for displaying the inputted or selected date. E.g. "YYYY.M.D", "DD-MM-YYYY", "MM/DD/YYYY" etc.
530543 * This overrides the date format derived from any set locale. */
531544 dateFormat : PropTypes . string ,
532- /** Default value to be shown in the Datepicker */
545+ /**
546+ * Default value to be shown in the Datepicker
547+ * for example, `defaultValue='12/04/1993'`
548+ * or when range selection is enabled `defaultValue='12/04/1993 - 12/30/1992'` (will auto sort chronologically)
549+ * */
533550 defaultValue : PropTypes . string ,
534551 /** Set to **true** to mark component as disabled and make it non-interactive */
535552 disabled : PropTypes . bool ,
536553 /** Set to **true** to enable the selection of a date range (begin and end) */
537554 enableRangeSelection : PropTypes . bool ,
555+ /** Additional props to to apply to calendar footer button*/
556+ footerButtonProps : PropTypes . string ,
557+ /** Classnames to apply to calendar footer that will contain the 'Today' action */
558+ footerClasses : PropTypes . string ,
538559 /** Additional props to be spread to the `InputGroup` component */
539560 inputGroupProps : PropTypes . object ,
540561 /** Additional props to be spread to the `<input>` element */
0 commit comments