"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

exports.__esModule = true;
exports.default = void 0;

var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));

var _react = _interopRequireWildcard(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _mapValues = _interopRequireDefault(require("lodash/mapValues"));

var _pick = _interopRequireDefault(require("lodash/pick"));

var _omit = _interopRequireDefault(require("lodash/omit"));

var _Calendar = _interopRequireDefault(require("@rsuite/icons/legacy/Calendar"));

var _ClockO = _interopRequireDefault(require("@rsuite/icons/legacy/ClockO"));

var _Calendar2 = require("../Calendar");

var _Toolbar = _interopRequireDefault(require("./Toolbar"));

var _utils = require("../utils");

var _Picker = require("../Picker");

var _utils2 = require("./utils");

var defaultProps = (0, _extends2.default)({}, _Picker.pickerDefaultProps, {
  as: 'div',
  classPrefix: 'picker',
  format: 'yyyy-MM-dd',
  limitEndYear: 1000,
  placeholder: ''
});

var DatePicker = /*#__PURE__*/_react.default.forwardRef(function (props, ref) {
  var _ref;

  var Component = props.as,
      className = props.className,
      classPrefix = props.classPrefix,
      calendarDefaultDate = props.calendarDefaultDate,
      cleanable = props.cleanable,
      defaultValue = props.defaultValue,
      disabled = props.disabled,
      formatStr = props.format,
      inline = props.inline,
      isoWeek = props.isoWeek,
      limitEndYear = props.limitEndYear,
      overrideLocale = props.locale,
      menuClassName = props.menuClassName,
      placement = props.placement,
      oneTap = props.oneTap,
      placeholder = props.placeholder,
      ranges = props.ranges,
      valueProp = props.value,
      showMeridian = props.showMeridian,
      showWeekNumbers = props.showWeekNumbers,
      style = props.style,
      timeZone = props.timeZone,
      toggleAs = props.toggleAs,
      disabledDateProp = props.disabledDate,
      renderValue = props.renderValue,
      onChange = props.onChange,
      onChangeCalendarDate = props.onChangeCalendarDate,
      onClean = props.onClean,
      onClose = props.onClose,
      onEntered = props.onEntered,
      onExited = props.onExited,
      onNextMonth = props.onNextMonth,
      onOk = props.onOk,
      onOpen = props.onOpen,
      onPrevMonth = props.onPrevMonth,
      onSelect = props.onSelect,
      onToggleMonthDropdown = props.onToggleMonthDropdown,
      onToggleTimeDropdown = props.onToggleTimeDropdown,
      rest = (0, _objectWithoutPropertiesLoose2.default)(props, ["as", "className", "classPrefix", "calendarDefaultDate", "cleanable", "defaultValue", "disabled", "format", "inline", "isoWeek", "limitEndYear", "locale", "menuClassName", "placement", "oneTap", "placeholder", "ranges", "value", "showMeridian", "showWeekNumbers", "style", "timeZone", "toggleAs", "disabledDate", "renderValue", "onChange", "onChangeCalendarDate", "onClean", "onClose", "onEntered", "onExited", "onNextMonth", "onOk", "onOpen", "onPrevMonth", "onSelect", "onToggleMonthDropdown", "onToggleTimeDropdown"]);

  var _useCustom = (0, _utils.useCustom)('DatePicker', overrideLocale),
      locale = _useCustom.locale,
      formatDate = _useCustom.formatDate,
      parseDate = _useCustom.parseDate;

  var _useClassNames = (0, _utils.useClassNames)(classPrefix),
      merge = _useClassNames.merge,
      prefix = _useClassNames.prefix,
      withClassPrefix = _useClassNames.withClassPrefix; // Format the value according to the time zone.


  var formatValue = (0, _react.useCallback)(function (v) {
    return _utils.TimeZone.toTimeZone(v, timeZone);
  }, [timeZone]);

  var _useControlled = (0, _utils.useControlled)(valueProp, defaultValue, formatValue),
      value = _useControlled[0],
      setValue = _useControlled[1];

  var _useState = (0, _react.useState)(_utils.TimeZone.toTimeZone((_ref = value !== null && value !== void 0 ? value : calendarDefaultDate) !== null && _ref !== void 0 ? _ref : new Date(), timeZone)),
      pageDate = _useState[0],
      setPageDate = _useState[1];

  var _useState2 = (0, _react.useState)(),
      inputState = _useState2[0],
      setInputState = _useState2[1];

  var _useCalendarState = (0, _utils2.useCalendarState)(),
      calendarState = _useCalendarState.calendarState,
      reset = _useCalendarState.reset,
      openMonth = _useCalendarState.openMonth,
      openTime = _useCalendarState.openTime;

  var _useState3 = (0, _react.useState)(false),
      active = _useState3[0],
      setActive = _useState3[1];

  var triggerRef = (0, _react.useRef)();
  var rootRef = (0, _react.useRef)();
  var targetRef = (0, _react.useRef)();
  var overlayRef = (0, _react.useRef)();
  (0, _Picker.usePublicMethods)(ref, {
    rootRef: rootRef,
    triggerRef: triggerRef,
    overlayRef: overlayRef,
    targetRef: targetRef
  });
  var getLocalPageDate = (0, _react.useCallback)(function (date) {
    if (date === void 0) {
      date = pageDate;
    }

    return _utils.TimeZone.toLocalTimeZone(date, timeZone);
  }, [pageDate, timeZone]);
  /**
   * Switch to the callback triggered after the next month.
   */

  var handleMoveForward = (0, _react.useCallback)(function (nextPageDate) {
    setPageDate(nextPageDate);
    nextPageDate = getLocalPageDate(nextPageDate);
    onNextMonth === null || onNextMonth === void 0 ? void 0 : onNextMonth(nextPageDate);
    onChangeCalendarDate === null || onChangeCalendarDate === void 0 ? void 0 : onChangeCalendarDate(nextPageDate);
  }, [getLocalPageDate, onChangeCalendarDate, onNextMonth]);
  /**
   * Switch to the callback triggered after the previous month.
   */

  var handleMoveBackward = (0, _react.useCallback)(function (nextPageDate) {
    setPageDate(nextPageDate);
    nextPageDate = getLocalPageDate(nextPageDate);
    onPrevMonth === null || onPrevMonth === void 0 ? void 0 : onPrevMonth(nextPageDate);
    onChangeCalendarDate === null || onChangeCalendarDate === void 0 ? void 0 : onChangeCalendarDate(nextPageDate);
  }, [getLocalPageDate, onChangeCalendarDate, onPrevMonth]);
  /**
   * The callback triggered when the date changes.
   */

  var handleDateChange = (0, _react.useCallback)(function (nextValue, event) {
    nextValue = _utils.TimeZone.toLocalTimeZone(nextValue, timeZone);
    onSelect === null || onSelect === void 0 ? void 0 : onSelect(nextValue, event);
    onChangeCalendarDate === null || onChangeCalendarDate === void 0 ? void 0 : onChangeCalendarDate(nextValue, event);
  }, [onChangeCalendarDate, onSelect, timeZone]);
  /**
   *  A callback triggered when the date on the calendar changes.
   */

  var handleChangePageDate = (0, _react.useCallback)(function (nextPageDate) {
    setPageDate(nextPageDate);
    reset();
    handleDateChange(nextPageDate);
  }, [handleDateChange, reset]);
  /**
   *  A callback triggered when the time on the calendar changes.
   */

  var handleChangePageTime = (0, _react.useCallback)(function (nextPageTime) {
    setPageDate(nextPageTime);
    handleDateChange(nextPageTime);
  }, [handleDateChange]);
  var handleClose = (0, _react.useCallback)(function () {
    var _triggerRef$current, _triggerRef$current$c;

    (_triggerRef$current = triggerRef.current) === null || _triggerRef$current === void 0 ? void 0 : (_triggerRef$current$c = _triggerRef$current.close) === null || _triggerRef$current$c === void 0 ? void 0 : _triggerRef$current$c.call(_triggerRef$current);
  }, []);
  /**
   * The callback triggered when PM/AM is switched.
   */

  var handleToggleMeridian = (0, _react.useCallback)(function () {
    var hours = _utils.DateUtils.getHours(pageDate);

    var nextHours = hours >= 12 ? hours - 12 : hours + 12;

    var nextDate = _utils.DateUtils.setHours(pageDate, nextHours);

    setPageDate(nextDate);
  }, [pageDate]);
  var updateValue = (0, _react.useCallback)(function (event, nextPageDate, closeOverlay) {
    if (closeOverlay === void 0) {
      closeOverlay = true;
    }

    var nextValue = typeof nextPageDate !== 'undefined' ? nextPageDate : pageDate;
    setPageDate(nextValue || new Date());
    setValue(nextValue);

    if (nextValue !== value || !_utils.DateUtils.isSameDay(nextValue, value)) {
      onChange === null || onChange === void 0 ? void 0 : onChange(getLocalPageDate(nextValue), event);
    } // `closeOverlay` default value is `true`


    if (closeOverlay !== false) {
      handleClose();
    }
  }, [getLocalPageDate, handleClose, onChange, pageDate, setValue, value]);
  /**
   * The callback triggered after the date in the shortcut area is clicked.
   */

  var handleShortcutPageDate = (0, _react.useCallback)(function (value, closeOverlay, event) {
    updateValue(event, value, closeOverlay);
    handleDateChange(value, event);
  }, [handleDateChange, updateValue]);
  /**
   * The callback triggered after clicking the OK button.
   */

  var handleOK = (0, _react.useCallback)(function (event) {
    updateValue(event);
    onOk === null || onOk === void 0 ? void 0 : onOk(getLocalPageDate(), event);
  }, [getLocalPageDate, updateValue, onOk]);
  /**
   * Toggle month selection panel
   */

  var handleMonthDropdown = (0, _react.useCallback)(function () {
    if (calendarState === _Calendar2.CalendarState.DROP_MONTH) {
      reset();
    } else {
      openMonth();
    }

    onToggleMonthDropdown === null || onToggleMonthDropdown === void 0 ? void 0 : onToggleMonthDropdown(calendarState !== _Calendar2.CalendarState.DROP_MONTH);
  }, [calendarState, onToggleMonthDropdown, openMonth, reset]);
  /**
   * Switch time selection panel
   */

  var handleTimeDropdown = (0, _react.useCallback)(function () {
    if (calendarState === _Calendar2.CalendarState.DROP_TIME) {
      reset();
    } else {
      openTime();
    }

    onToggleTimeDropdown === null || onToggleTimeDropdown === void 0 ? void 0 : onToggleTimeDropdown(calendarState !== _Calendar2.CalendarState.DROP_TIME);
  }, [calendarState, onToggleTimeDropdown, openTime, reset]);
  /**
   * Callback after clicking the clear button.
   */

  var handleClean = (0, _react.useCallback)(function (event) {
    setPageDate(_utils.TimeZone.toTimeZone(new Date(), timeZone));
    updateValue(event, null);
  }, [updateValue, timeZone]);
  /**
   * Handle keyboard events.
   */

  var onPickerKeyDown = (0, _Picker.useToggleKeyDownEvent)((0, _extends2.default)({
    triggerRef: triggerRef,
    targetRef: targetRef,
    active: active,
    onExit: handleClean
  }, rest));
  /**
   * Callback after the date is selected.
   */

  var handleSelect = (0, _react.useCallback)(function (nextValue, event, updatableValue) {
    if (updatableValue === void 0) {
      updatableValue = true;
    }

    setPageDate( // Determine whether the current value contains time, if not, use pageDate.
    _utils.DateUtils.shouldTime(formatStr) ? nextValue : (0, _utils.composeFunctions)(function (d) {
      return _utils.DateUtils.setHours(d, _utils.DateUtils.getHours(pageDate));
    }, function (d) {
      return _utils.DateUtils.setMinutes(d, _utils.DateUtils.getMinutes(pageDate));
    }, function (d) {
      return _utils.DateUtils.setSeconds(d, _utils.DateUtils.getSeconds(pageDate));
    })(nextValue));
    handleDateChange(nextValue);

    if (oneTap && updatableValue) {
      updateValue(event, nextValue);
    }
  }, [formatStr, handleDateChange, oneTap, pageDate, updateValue]);
  var disabledDate = (0, _react.useCallback)(function (date) {
    return disabledDateProp === null || disabledDateProp === void 0 ? void 0 : disabledDateProp(_utils.TimeZone.toLocalTimeZone(date, timeZone));
  }, [disabledDateProp, timeZone]);
  /**
   * Callback after the input box value is changed.
   */

  var handleInputChange = (0, _react.useCallback)(function (value, event) {
    setInputState('Typing'); // isMatch('01/11/2020', 'MM/dd/yyyy') ==> true
    // isMatch('2020-11-01', 'MM/dd/yyyy') ==> false

    if (!_utils.DateUtils.isMatch(value, formatStr, {
      locale: locale.dateLocale
    })) {
      setInputState('Error');
      return;
    }

    var date = parseDate(value, formatStr); // If only the time is included in the characters, it will default to today.

    if (_utils.DateUtils.shouldOnlyTime(formatStr)) {
      date = new Date(_utils.DateUtils.format(new Date(), 'yyyy-MM-dd') + " " + value);
    }

    if (!_utils.DateUtils.isValid(date)) {
      setInputState('Error');
      return;
    }

    if (disabledDate(date)) {
      setInputState('Error');
      return;
    }

    handleSelect(date, event, false);
  }, [formatStr, locale, parseDate, disabledDate, handleSelect]);
  /**
   * The callback after the enter key is triggered on the input
   */

  var handleInputBlur = (0, _react.useCallback)(function (event) {
    if (inputState === 'Typing') {
      updateValue(event, pageDate);
    }

    setInputState('Initial');
  }, [inputState, pageDate, updateValue]);
  var handleEntered = (0, _react.useCallback)(function () {
    onOpen === null || onOpen === void 0 ? void 0 : onOpen();
    setActive(true);
  }, [onOpen]);
  var handleExited = (0, _react.useCallback)(function () {
    onClose === null || onClose === void 0 ? void 0 : onClose();
    reset();
    setActive(false);
  }, [onClose, reset]); // Check whether the time is within the time range of the shortcut option in the toolbar.

  var disabledToolbarHandle = (0, _react.useCallback)(function (date) {
    var _disabledDateProp;

    var localTimeZoneDate = _utils.TimeZone.toLocalTimeZone(date, timeZone);

    var allowDate = (_disabledDateProp = disabledDateProp === null || disabledDateProp === void 0 ? void 0 : disabledDateProp(localTimeZoneDate)) !== null && _disabledDateProp !== void 0 ? _disabledDateProp : false;

    var allowTime = _utils.DateUtils.disabledTime(props, localTimeZoneDate);

    return allowDate || allowTime;
  }, [disabledDateProp, props, timeZone]);
  var calendarProps = (0, _react.useMemo)(function () {
    return (0, _mapValues.default)((0, _pick.default)(props, _utils.DateUtils.calendarOnlyProps), function (disabledOrHiddenTimeFunc) {
      return function (next, date) {
        return disabledOrHiddenTimeFunc(next, _utils.TimeZone.toLocalTimeZone(date, timeZone));
      };
    });
  }, [props, timeZone]);

  var calendar = /*#__PURE__*/_react.default.createElement(_Calendar2.Calendar, (0, _extends2.default)({}, calendarProps, {
    locale: locale,
    showWeekNumbers: showWeekNumbers,
    showMeridian: showMeridian,
    disabledDate: disabledDate,
    limitEndYear: limitEndYear,
    format: formatStr,
    timeZone: timeZone,
    isoWeek: isoWeek,
    calendarState: calendarState,
    pageDate: pageDate,
    onMoveForward: handleMoveForward,
    onMoveBackward: handleMoveBackward,
    onSelect: handleSelect,
    onToggleMonthDropdown: handleMonthDropdown,
    onToggleTimeDropdown: handleTimeDropdown,
    onChangePageDate: handleChangePageDate,
    onChangePageTime: handleChangePageTime,
    onToggleMeridian: handleToggleMeridian
  }));

  var renderDropdownMenu = function renderDropdownMenu(positionProps, speakerRef) {
    var left = positionProps.left,
        top = positionProps.top,
        className = positionProps.className;
    var classes = merge(menuClassName, className, prefix('date-menu'));
    var styles = {
      left: left,
      top: top
    };
    return /*#__PURE__*/_react.default.createElement(_Picker.PickerOverlay, {
      className: classes,
      ref: (0, _utils.mergeRefs)(overlayRef, speakerRef),
      style: styles,
      target: triggerRef
    }, calendar, /*#__PURE__*/_react.default.createElement(_Toolbar.default, {
      locale: locale,
      timeZone: timeZone,
      ranges: ranges,
      pageDate: pageDate,
      disabledOkBtn: disabledToolbarHandle,
      disabledShortcut: disabledToolbarHandle,
      onClickShortcut: handleShortcutPageDate,
      onOk: handleOK,
      hideOkBtn: oneTap
    }));
  };

  var hasValue = !!value;

  var _usePickerClassName = (0, _Picker.usePickerClassName)((0, _extends2.default)({}, props, {
    name: 'date',
    hasValue: hasValue
  })),
      classes = _usePickerClassName[0],
      usedClassNamePropKeys = _usePickerClassName[1];

  var renderDate = (0, _react.useCallback)(function () {
    var _renderValue;

    if (!value) {
      return placeholder || formatStr;
    }

    return (_renderValue = renderValue === null || renderValue === void 0 ? void 0 : renderValue(value, formatStr)) !== null && _renderValue !== void 0 ? _renderValue : formatDate(value, formatStr);
  }, [formatStr, formatDate, placeholder, renderValue, value]);
  var caretComponent = (0, _react.useMemo)(function () {
    return _utils.DateUtils.shouldOnlyTime(formatStr) ? _ClockO.default : _Calendar.default;
  }, [formatStr]);

  if (inline) {
    return /*#__PURE__*/_react.default.createElement(Component, {
      ref: rootRef,
      className: merge(className, withClassPrefix('date-inline'))
    }, calendar);
  }

  return /*#__PURE__*/_react.default.createElement(_Picker.PickerToggleTrigger, {
    trigger: "active",
    pickerProps: (0, _pick.default)(props, _Picker.pickTriggerPropKeys),
    ref: triggerRef,
    placement: placement,
    onEntered: (0, _utils.createChainedFunction)(handleEntered, onEntered),
    onExited: (0, _utils.createChainedFunction)(handleExited, onExited),
    speaker: renderDropdownMenu
  }, /*#__PURE__*/_react.default.createElement(Component, {
    className: merge(className, classes),
    style: style,
    ref: rootRef
  }, /*#__PURE__*/_react.default.createElement(_Picker.PickerToggle, (0, _extends2.default)({}, (0, _omit.default)(rest, [].concat(_Picker.omitTriggerPropKeys, usedClassNamePropKeys, _utils.DateUtils.calendarOnlyProps)), {
    className: prefix({
      error: inputState === 'Error'
    }),
    as: toggleAs,
    ref: targetRef,
    input: true,
    inputValue: value ? formatDate(value, formatStr) : '',
    inputPlaceholder: typeof placeholder === 'string' && placeholder ? placeholder : formatStr,
    inputMask: _utils.DateUtils.getDateMask(formatStr),
    onInputChange: handleInputChange,
    onInputBlur: handleInputBlur,
    onKeyDown: onPickerKeyDown,
    onClean: (0, _utils.createChainedFunction)(handleClean, onClean),
    cleanable: cleanable && !disabled,
    hasValue: hasValue,
    active: active,
    placement: placement,
    disabled: disabled,
    caretComponent: caretComponent
  }), renderDate())));
});

DatePicker.displayName = 'DatePicker';
DatePicker.defaultProps = defaultProps;
DatePicker.propTypes = (0, _extends2.default)({}, _Picker.pickerPropTypes, {
  calendarDefaultDate: _propTypes.default.instanceOf(Date),
  defaultValue: _propTypes.default.instanceOf(Date),
  disabledDate: _propTypes.default.func,
  disabledHours: _propTypes.default.func,
  disabledMinutes: _propTypes.default.func,
  disabledSeconds: _propTypes.default.func,
  format: _propTypes.default.string,
  hideHours: _propTypes.default.func,
  hideMinutes: _propTypes.default.func,
  hideSeconds: _propTypes.default.func,
  inline: _propTypes.default.bool,
  isoWeek: _propTypes.default.bool,
  limitEndYear: _propTypes.default.number,
  onChange: _propTypes.default.func,
  onChangeCalendarDate: _propTypes.default.func,
  onNextMonth: _propTypes.default.func,
  onOk: _propTypes.default.func,
  onPrevMonth: _propTypes.default.func,
  onSelect: _propTypes.default.func,
  onToggleMonthDropdown: _propTypes.default.func,
  onToggleTimeDropdown: _propTypes.default.func,
  oneTap: _propTypes.default.bool,
  panelContainerRef: _propTypes.default.any,
  ranges: _propTypes.default.array,
  showMeridian: _propTypes.default.bool,
  showWeekNumbers: _propTypes.default.bool,
  timeZone: _propTypes.default.string,
  value: _propTypes.default.instanceOf(Date)
});
var _default = DatePicker;
exports.default = _default;