Simon Egersand
2018-02-07 63e0b0b2fc6f361b5ac4751eb05bc5983aea5873
DateTime.js
@@ -1,446 +1,499 @@
'use strict';
var assign = require('object-assign'),
   PropTypes = require('prop-types'),
   createClass = require('create-react-class'),
   moment = require('moment'),
   React = require('react'),
   CalendarContainer = require('./src/CalendarContainer')
   ;
  PropTypes = require('prop-types'),
  createClass = require('create-react-class'),
  moment = require('moment'),
  React = require('react'),
  CalendarContainer = require('./src/CalendarContainer');
var TYPES = PropTypes;
var Datetime = createClass({
   propTypes: {
      // value: TYPES.object | TYPES.string,
      // defaultValue: TYPES.object | TYPES.string,
      onFocus: TYPES.func,
      onBlur: TYPES.func,
      onChange: TYPES.func,
      onViewModeChange: TYPES.func,
      locale: TYPES.string,
      utc: TYPES.bool,
      input: TYPES.bool,
      // dateFormat: TYPES.string | TYPES.bool,
      // timeFormat: TYPES.string | TYPES.bool,
      inputProps: TYPES.object,
      timeConstraints: TYPES.object,
      viewMode: TYPES.oneOf(['years', 'months', 'days', 'time']),
      isValidDate: TYPES.func,
      open: TYPES.bool,
      strictParsing: TYPES.bool,
      closeOnSelect: TYPES.bool,
      closeOnTab: TYPES.bool
   },
  propTypes: {
    // value: TYPES.object | TYPES.string,
    // defaultValue: TYPES.object | TYPES.string,
    onFocus: TYPES.func,
    onBlur: TYPES.func,
    onChange: TYPES.func,
    onViewModeChange: TYPES.func,
    locale: TYPES.string,
    utc: TYPES.bool,
    input: TYPES.bool,
    // dateFormat: TYPES.string | TYPES.bool,
    // timeFormat: TYPES.string | TYPES.bool,
    inputProps: TYPES.object,
    timeConstraints: TYPES.object,
    viewMode: TYPES.oneOf(['years', 'months', 'days', 'time']),
    isValidDate: TYPES.func,
    open: TYPES.bool,
    strictParsing: TYPES.bool,
    closeOnSelect: TYPES.bool,
    closeOnTab: TYPES.bool
  },
   getDefaultProps: function() {
      var nof = function() {};
      return {
         className: '',
         defaultValue: '',
         inputProps: {},
         input: true,
         onFocus: nof,
         onBlur: nof,
         onChange: nof,
         onViewModeChange: nof,
         timeFormat: true,
         timeConstraints: {},
         dateFormat: true,
         strictParsing: true,
         closeOnSelect: false,
         closeOnTab: true,
         utc: false
      };
   },
  getInitialState: function() {
    var state = this.getStateFromProps(this.props);
   getInitialState: function() {
      var state = this.getStateFromProps( this.props );
    if (state.open === undefined) state.open = !this.props.input;
      if ( state.open === undefined )
         state.open = !this.props.input;
    state.currentView = this.props.dateFormat
      ? this.props.viewMode || state.updateOn || 'days'
      : 'time';
      state.currentView = this.props.dateFormat ? (this.props.viewMode || state.updateOn || 'days') : 'time';
    return state;
  },
      return state;
   },
  getStateFromProps: function(props) {
    var formats = this.getFormats(props),
      date = props.value || props.defaultValue,
      selectedDate,
      viewDate,
      updateOn,
      inputValue;
   getStateFromProps: function( props ) {
      var formats = this.getFormats( props ),
         date = props.value || props.defaultValue,
         selectedDate, viewDate, updateOn, inputValue
         ;
    if (date && typeof date === 'string')
      selectedDate = this.localMoment(date, formats.datetime);
    else if (date) selectedDate = this.localMoment(date);
      if ( date && typeof date === 'string' )
         selectedDate = this.localMoment( date, formats.datetime );
      else if ( date )
         selectedDate = this.localMoment( date );
    if (selectedDate && !selectedDate.isValid()) selectedDate = null;
      if ( selectedDate && !selectedDate.isValid() )
         selectedDate = null;
    viewDate = selectedDate
      ? selectedDate.clone().startOf('month')
      : this.localMoment().startOf('month');
      viewDate = selectedDate ?
         selectedDate.clone().startOf('month') :
         this.localMoment().startOf('month')
      ;
    updateOn = this.getUpdateOn(formats);
      updateOn = this.getUpdateOn(formats);
    if (selectedDate) inputValue = selectedDate.format(formats.datetime);
    else if (date.isValid && !date.isValid()) inputValue = '';
    else inputValue = date || '';
      if ( selectedDate )
         inputValue = selectedDate.format(formats.datetime);
      else if ( date.isValid && !date.isValid() )
         inputValue = '';
      else
         inputValue = date || '';
    return {
      updateOn: updateOn,
      inputFormat: formats.datetime,
      viewDate: viewDate,
      selectedDate: selectedDate,
      inputValue: inputValue,
      open: props.open
    };
  },
      return {
         updateOn: updateOn,
         inputFormat: formats.datetime,
         viewDate: viewDate,
         selectedDate: selectedDate,
         inputValue: inputValue,
         open: props.open
      };
   },
  getUpdateOn: function(formats) {
    if (formats.date.match(/[lLD]/)) {
      return 'days';
    } else if (formats.date.indexOf('M') !== -1) {
      return 'months';
    } else if (formats.date.indexOf('Y') !== -1) {
      return 'years';
    }
   getUpdateOn: function( formats ) {
      if ( formats.date.match(/[lLD]/) ) {
         return 'days';
      } else if ( formats.date.indexOf('M') !== -1 ) {
         return 'months';
      } else if ( formats.date.indexOf('Y') !== -1 ) {
         return 'years';
      }
    return 'days';
  },
      return 'days';
   },
  getFormats: function(props) {
    var formats = {
        date: props.dateFormat || '',
        time: props.timeFormat || ''
      },
      locale = this.localMoment(props.date, null, props).localeData();
   getFormats: function( props ) {
      var formats = {
            date: props.dateFormat || '',
            time: props.timeFormat || ''
         },
         locale = this.localMoment( props.date, null, props ).localeData()
         ;
    if (formats.date === true) {
      formats.date = locale.longDateFormat('L');
    } else if (this.getUpdateOn(formats) !== 'days') {
      formats.time = '';
    }
      if ( formats.date === true ) {
         formats.date = locale.longDateFormat('L');
      }
      else if ( this.getUpdateOn(formats) !== 'days' ) {
         formats.time = '';
      }
    if (formats.time === true) {
      formats.time = locale.longDateFormat('LT');
    }
      if ( formats.time === true ) {
         formats.time = locale.longDateFormat('LT');
      }
    formats.datetime =
      formats.date && formats.time
        ? formats.date + ' ' + formats.time
        : formats.date || formats.time;
      formats.datetime = formats.date && formats.time ?
         formats.date + ' ' + formats.time :
         formats.date || formats.time
      ;
    return formats;
  },
      return formats;
   },
  componentWillReceiveProps: function(nextProps) {
    var formats = this.getFormats(nextProps),
      updatedState = {};
   componentWillReceiveProps: function( nextProps ) {
      var formats = this.getFormats( nextProps ),
         updatedState = {}
      ;
    if (
      nextProps.value !== this.props.value ||
      formats.datetime !== this.getFormats(this.props).datetime
    ) {
      updatedState = this.getStateFromProps(nextProps);
    }
      if ( nextProps.value !== this.props.value ||
         formats.datetime !== this.getFormats( this.props ).datetime ) {
         updatedState = this.getStateFromProps( nextProps );
      }
    if (updatedState.open === undefined) {
      if (typeof nextProps.open !== 'undefined') {
        updatedState.open = nextProps.open;
      } else if (
        this.props.closeOnSelect &&
        this.state.currentView !== 'time'
      ) {
        updatedState.open = false;
      } else {
        updatedState.open = this.state.open;
      }
    }
      if ( updatedState.open === undefined ) {
         if ( this.props.closeOnSelect && this.state.currentView !== 'time' ) {
            updatedState.open = false;
         } else {
            updatedState.open = this.state.open;
         }
      }
    if (nextProps.viewMode !== this.props.viewMode) {
      updatedState.currentView = nextProps.viewMode;
    }
      if ( nextProps.viewMode !== this.props.viewMode ) {
         updatedState.currentView = nextProps.viewMode;
      }
    if (nextProps.locale !== this.props.locale) {
      if (this.state.viewDate) {
        var updatedViewDate = this.state.viewDate
          .clone()
          .locale(nextProps.locale);
        updatedState.viewDate = updatedViewDate;
      }
      if (this.state.selectedDate) {
        var updatedSelectedDate = this.state.selectedDate
          .clone()
          .locale(nextProps.locale);
        updatedState.selectedDate = updatedSelectedDate;
        updatedState.inputValue = updatedSelectedDate.format(formats.datetime);
      }
    }
      if ( nextProps.locale !== this.props.locale ) {
         if ( this.state.viewDate ) {
            var updatedViewDate = this.state.viewDate.clone().locale( nextProps.locale );
            updatedState.viewDate = updatedViewDate;
         }
         if ( this.state.selectedDate ) {
            var updatedSelectedDate = this.state.selectedDate.clone().locale( nextProps.locale );
            updatedState.selectedDate = updatedSelectedDate;
            updatedState.inputValue = updatedSelectedDate.format( formats.datetime );
         }
      }
      if ( nextProps.utc !== this.props.utc ) {
         if ( nextProps.utc ) {
            if ( this.state.viewDate )
               updatedState.viewDate = this.state.viewDate.clone().utc();
            if ( this.state.selectedDate ) {
               updatedState.selectedDate = this.state.selectedDate.clone().utc();
               updatedState.inputValue = updatedState.selectedDate.format( formats.datetime );
            }
         } else {
            if ( this.state.viewDate )
               updatedState.viewDate = this.state.viewDate.clone().local();
            if ( this.state.selectedDate ) {
               updatedState.selectedDate = this.state.selectedDate.clone().local();
               updatedState.inputValue = updatedState.selectedDate.format(formats.datetime);
            }
         }
      }
      //we should only show a valid date if we are provided a isValidDate function. Removed in 2.10.3
      /*if (this.props.isValidDate) {
    if (nextProps.utc !== this.props.utc) {
      if (nextProps.utc) {
        if (this.state.viewDate)
          updatedState.viewDate = this.state.viewDate.clone().utc();
        if (this.state.selectedDate) {
          updatedState.selectedDate = this.state.selectedDate.clone().utc();
          updatedState.inputValue = updatedState.selectedDate.format(
            formats.datetime
          );
        }
      } else {
        if (this.state.viewDate)
          updatedState.viewDate = this.state.viewDate.clone().local();
        if (this.state.selectedDate) {
          updatedState.selectedDate = this.state.selectedDate.clone().local();
          updatedState.inputValue = updatedState.selectedDate.format(
            formats.datetime
          );
        }
      }
    }
    //we should only show a valid date if we are provided a isValidDate function. Removed in 2.10.3
    /*if (this.props.isValidDate) {
         updatedState.viewDate = updatedState.viewDate || this.state.viewDate;
         while (!this.props.isValidDate(updatedState.viewDate)) {
            updatedState.viewDate = updatedState.viewDate.add(1, 'day');
         }
      }*/
      this.setState( updatedState );
   },
    this.setState(updatedState);
  },
   onInputChange: function( e ) {
      var value = e.target === null ? e : e.target.value,
         localMoment = this.localMoment( value, this.state.inputFormat ),
         update = { inputValue: value }
         ;
  onInputChange: function(e) {
    var value = e.target === null ? e : e.target.value,
      localMoment = this.localMoment(value, this.state.inputFormat),
      update = { inputValue: value };
      if ( localMoment.isValid() && !this.props.value ) {
         update.selectedDate = localMoment;
         update.viewDate = localMoment.clone().startOf('month');
      } else {
         update.selectedDate = null;
      }
    if (localMoment.isValid() && !this.props.value) {
      update.selectedDate = localMoment;
      update.viewDate = localMoment.clone().startOf('month');
    } else {
      update.selectedDate = null;
    }
      return this.setState( update, function() {
         return this.props.onChange( localMoment.isValid() ? localMoment : this.state.inputValue );
      });
   },
    return this.setState(update, function() {
      return this.props.onChange(
        localMoment.isValid() ? localMoment : this.state.inputValue
      );
    });
  },
   onInputKey: function( e ) {
      if ( e.which === 9 && this.props.closeOnTab ) {
         this.closeCalendar();
      }
   },
  onInputKey: function(e) {
    if (e.which === 9 && this.props.closeOnTab) {
      this.closeCalendar();
    }
  },
   showView: function( view ) {
      var me = this;
      return function() {
         me.state.currentView !== view && me.props.onViewModeChange( view );
         me.setState({ currentView: view });
      };
   },
  showView: function(view) {
    var me = this;
    return function() {
      me.state.currentView !== view && me.props.onViewModeChange(view);
      me.setState({ currentView: view });
    };
  },
   setDate: function( type ) {
      var me = this,
         nextViews = {
            month: 'days',
            year: 'months'
         }
      ;
      return function( e ) {
         me.setState({
            viewDate: me.state.viewDate.clone()[ type ]( parseInt(e.target.getAttribute('data-value'), 10) ).startOf( type ),
            currentView: nextViews[ type ]
         });
         me.props.onViewModeChange( nextViews[ type ] );
      };
   },
  setDate: function(type) {
    var me = this,
      nextViews = {
        month: 'days',
        year: 'months'
      };
    return function(e) {
      me.setState({
        viewDate: me.state.viewDate
          .clone()
          [type](parseInt(e.target.getAttribute('data-value'), 10))
          .startOf(type),
        currentView: nextViews[type]
      });
      me.props.onViewModeChange(nextViews[type]);
    };
  },
   addTime: function( amount, type, toSelected ) {
      return this.updateTime( 'add', amount, type, toSelected );
   },
  addTime: function(amount, type, toSelected) {
    return this.updateTime('add', amount, type, toSelected);
  },
   subtractTime: function( amount, type, toSelected ) {
      return this.updateTime( 'subtract', amount, type, toSelected );
   },
  subtractTime: function(amount, type, toSelected) {
    return this.updateTime('subtract', amount, type, toSelected);
  },
   updateTime: function( op, amount, type, toSelected ) {
      var me = this;
  updateTime: function(op, amount, type, toSelected) {
    var me = this;
      return function() {
         var update = {},
            date = toSelected ? 'selectedDate' : 'viewDate'
         ;
    return function() {
      var update = {},
        date = toSelected ? 'selectedDate' : 'viewDate';
         update[ date ] = me.state[ date ].clone()[ op ]( amount, type );
      update[date] = me.state[date].clone()[op](amount, type);
         me.setState( update );
      };
   },
      me.setState(update);
    };
  },
   allowedSetTime: ['hours', 'minutes', 'seconds', 'milliseconds'],
   setTime: function( type, value ) {
      var index = this.allowedSetTime.indexOf( type ) + 1,
         state = this.state,
         date = (state.selectedDate || state.viewDate).clone(),
         nextType
         ;
  allowedSetTime: ['hours', 'minutes', 'seconds', 'milliseconds'],
  setTime: function(type, value) {
    var index = this.allowedSetTime.indexOf(type) + 1,
      state = this.state,
      date = (state.selectedDate || state.viewDate).clone(),
      nextType;
      // It is needed to set all the time properties
      // to not to reset the time
      date[ type ]( value );
      for (; index < this.allowedSetTime.length; index++) {
         nextType = this.allowedSetTime[index];
         date[ nextType ]( date[nextType]() );
      }
    // It is needed to set all the time properties
    // to not to reset the time
    date[type](value);
    for (; index < this.allowedSetTime.length; index++) {
      nextType = this.allowedSetTime[index];
      date[nextType](date[nextType]());
    }
      if ( !this.props.value ) {
         this.setState({
            selectedDate: date,
            inputValue: date.format( state.inputFormat )
         });
      }
      this.props.onChange( date );
   },
    if (!this.props.value) {
      this.setState({
        selectedDate: date,
        inputValue: date.format(state.inputFormat)
      });
    }
    this.props.onChange(date);
  },
   updateSelectedDate: function( e, close ) {
      var target = e.target,
         modifier = 0,
         viewDate = this.state.viewDate,
         currentDate = this.state.selectedDate || viewDate,
         date
         ;
  updateSelectedDate: function(e, close) {
    var target = e.target,
      modifier = 0,
      viewDate = this.state.viewDate,
      currentDate = this.state.selectedDate || viewDate,
      date;
      if (target.className.indexOf('rdtDay') !== -1) {
         if (target.className.indexOf('rdtNew') !== -1)
            modifier = 1;
         else if (target.className.indexOf('rdtOld') !== -1)
            modifier = -1;
    if (target.className.indexOf('rdtDay') !== -1) {
      if (target.className.indexOf('rdtNew') !== -1) modifier = 1;
      else if (target.className.indexOf('rdtOld') !== -1) modifier = -1;
         date = viewDate.clone()
            .month( viewDate.month() + modifier )
            .date( parseInt( target.getAttribute('data-value'), 10 ) );
      } else if (target.className.indexOf('rdtMonth') !== -1) {
         date = viewDate.clone()
            .month( parseInt( target.getAttribute('data-value'), 10 ) )
            .date( currentDate.date() );
      } else if (target.className.indexOf('rdtYear') !== -1) {
         date = viewDate.clone()
            .month( currentDate.month() )
            .date( currentDate.date() )
            .year( parseInt( target.getAttribute('data-value'), 10 ) );
      }
      date = viewDate
        .clone()
        .month(viewDate.month() + modifier)
        .date(parseInt(target.getAttribute('data-value'), 10));
    } else if (target.className.indexOf('rdtMonth') !== -1) {
      date = viewDate
        .clone()
        .month(parseInt(target.getAttribute('data-value'), 10))
        .date(currentDate.date());
    } else if (target.className.indexOf('rdtYear') !== -1) {
      date = viewDate
        .clone()
        .month(currentDate.month())
        .date(currentDate.date())
        .year(parseInt(target.getAttribute('data-value'), 10));
    }
      date.hours( currentDate.hours() )
         .minutes( currentDate.minutes() )
         .seconds( currentDate.seconds() )
         .milliseconds( currentDate.milliseconds() );
    date
      .hours(currentDate.hours())
      .minutes(currentDate.minutes())
      .seconds(currentDate.seconds())
      .milliseconds(currentDate.milliseconds());
      if ( !this.props.value ) {
         var open = !( this.props.closeOnSelect && close );
         if ( !open ) {
            this.props.onBlur( date );
         }
    if (!this.props.value) {
      var open = !(this.props.closeOnSelect && close);
      if (!open) {
        this.props.onBlur(date);
      }
         this.setState({
            selectedDate: date,
            viewDate: date.clone().startOf('month'),
            inputValue: date.format( this.state.inputFormat ),
            open: open
         });
      } else {
         if ( this.props.closeOnSelect && close ) {
            this.closeCalendar();
         }
      }
      this.setState({
        selectedDate: date,
        viewDate: date.clone().startOf('month'),
        inputValue: date.format(this.state.inputFormat),
        open: open
      });
    } else {
      if (this.props.closeOnSelect && close) {
        this.closeCalendar();
      }
    }
      this.props.onChange( date );
   },
    this.props.onChange(date);
  },
   openCalendar: function( e ) {
      if ( !this.state.open ) {
         this.setState({ open: true }, function() {
            this.props.onFocus( e );
         });
      }
   },
  openCalendar: function(e) {
    if (!this.state.open) {
      this.setState({ open: true }, function() {
        this.props.onFocus(e);
      });
    }
  },
   closeCalendar: function() {
      this.setState({ open: false }, function () {
         this.props.onBlur( this.state.selectedDate || this.state.inputValue );
      });
   },
  closeCalendar: function() {
    this.setState({ open: false }, function() {
      this.props.onBlur(this.state.selectedDate || this.state.inputValue);
    });
  },
   handleClickOutside: function() {
      if ( this.props.input && this.state.open && !this.props.open ) {
         this.setState({ open: false }, function() {
            this.props.onBlur( this.state.selectedDate || this.state.inputValue );
         });
      }
   },
  handleClickOutside: function() {
    if (this.props.input && this.state.open && !this.props.open) {
      this.setState({ open: false }, function() {
        this.props.onBlur(this.state.selectedDate || this.state.inputValue);
      });
    }
  },
   localMoment: function( date, format, props ) {
      props = props || this.props;
      var momentFn = props.utc ? moment.utc : moment;
      var m = momentFn( date, format, props.strictParsing );
      if ( props.locale )
         m.locale( props.locale );
      return m;
   },
  localMoment: function(date, format, props) {
    props = props || this.props;
    var momentFn = props.utc ? moment.utc : moment;
    var m = momentFn(date, format, props.strictParsing);
    if (props.locale) m.locale(props.locale);
    return m;
  },
   componentProps: {
      fromProps: ['value', 'isValidDate', 'renderDay', 'renderMonth', 'renderYear', 'timeConstraints'],
      fromState: ['viewDate', 'selectedDate', 'updateOn'],
      fromThis: ['setDate', 'setTime', 'showView', 'addTime', 'subtractTime', 'updateSelectedDate', 'localMoment', 'handleClickOutside']
   },
  componentProps: {
    fromProps: [
      'value',
      'isValidDate',
      'renderDay',
      'renderMonth',
      'renderYear',
      'timeConstraints'
    ],
    fromState: ['viewDate', 'selectedDate', 'updateOn'],
    fromThis: [
      'setDate',
      'setTime',
      'showView',
      'addTime',
      'subtractTime',
      'updateSelectedDate',
      'localMoment',
      'handleClickOutside'
    ]
  },
   getComponentProps: function() {
      var me = this,
         formats = this.getFormats( this.props ),
         props = {dateFormat: formats.date, timeFormat: formats.time}
         ;
  getComponentProps: function() {
    var me = this,
      formats = this.getFormats(this.props),
      props = { dateFormat: formats.date, timeFormat: formats.time };
      this.componentProps.fromProps.forEach( function( name ) {
         props[ name ] = me.props[ name ];
      });
      this.componentProps.fromState.forEach( function( name ) {
         props[ name ] = me.state[ name ];
      });
      this.componentProps.fromThis.forEach( function( name ) {
         props[ name ] = me[ name ];
      });
    this.componentProps.fromProps.forEach(function(name) {
      props[name] = me.props[name];
    });
    this.componentProps.fromState.forEach(function(name) {
      props[name] = me.state[name];
    });
    this.componentProps.fromThis.forEach(function(name) {
      props[name] = me[name];
    });
      return props;
   },
    return props;
  },
   render: function() {
      // TODO: Make a function or clean up this code,
      // logic right now is really hard to follow
      var className = 'rdt' + (this.props.className ?
                  ( Array.isArray( this.props.className ) ?
                  ' ' + this.props.className.join( ' ' ) : ' ' + this.props.className) : ''),
         children = [];
  render: function() {
    // TODO: Make a function or clean up this code,
    // logic right now is really hard to follow
    var className =
        'rdt' +
        (this.props.className
          ? Array.isArray(this.props.className)
            ? ' ' + this.props.className.join(' ')
            : ' ' + this.props.className
          : ''),
      children = [];
      if ( this.props.input ) {
         children = [ React.createElement('input', assign({
            key: 'i',
            type: 'text',
            className: 'form-control',
            onFocus: this.openCalendar,
            onChange: this.onInputChange,
            onKeyDown: this.onInputKey,
            value: this.state.inputValue
         }, this.props.inputProps ))];
      } else {
         className += ' rdtStatic';
      }
    if (this.props.input) {
      var finalInputProps = assign(
        {
          type: 'text',
          className: 'form-control',
          onClick: this.openCalendar,
          onFocus: this.openCalendar,
          onChange: this.onInputChange,
          onKeyDown: this.onInputKey,
          value: this.state.inputValue
        },
        this.props.inputProps
      );
      if (this.props.renderInput) {
        children = [
          React.createElement(
            'div',
            { key: 'i' },
            this.props.renderInput(
              finalInputProps,
              this.openCalendar,
              this.closeCalendar
            )
          )
        ];
      } else {
        children = [
          React.createElement('input', assign({ key: 'i' }, finalInputProps))
        ];
      }
    } else {
      className += ' rdtStatic';
    }
      if ( this.state.open )
         className += ' rdtOpen';
    if (this.state.open) className += ' rdtOpen';
      return React.createElement('div', {className: className}, children.concat(
         React.createElement('div',
            { key: 'dt', className: 'rdtPicker' },
            React.createElement( CalendarContainer, {view: this.state.currentView, viewProps: this.getComponentProps(), onClickOutside: this.handleClickOutside })
         )
      ));
   }
    return React.createElement(
      'div',
      { className: className },
      children.concat(
        React.createElement(
          'div',
          { key: 'dt', className: 'rdtPicker' },
          React.createElement(CalendarContainer, {
            view: this.state.currentView,
            viewProps: this.getComponentProps(),
            onClickOutside: this.handleClickOutside
          })
        )
      )
    );
  }
});
Datetime.defaultProps = {
  className: '',
  defaultValue: '',
  inputProps: {},
  input: true,
  onFocus: function() {},
  onBlur: function() {},
  onChange: function() {},
  onViewModeChange: function() {},
  timeFormat: true,
  timeConstraints: {},
  dateFormat: true,
  strictParsing: true,
  closeOnSelect: false,
  closeOnTab: true,
  utc: false
};
// Make moment accessible through the Datetime class
Datetime.moment = moment;