text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.Datepicker = exports.datepickerClassName = void 0;
  var tslib_1 = require("tslib");
  var accessibility_1 = require("@fluentui/accessibility");
  var date_time_utilities_1 = require("../../utils/date-time-utilities");
  var react_bindings_1 = require("@fluentui/react-bindings");
  var react_icons_northstar_1 = require("@fluentui/react-icons-northstar");
  var customPropTypes = require("@fluentui/react-proptypes");
  var react_component_ref_1 = require("@fluentui/react-component-ref");
  var _ = require("lodash");
  var PropTypes = require("prop-types");
  var React = require("react");
  var utils_1 = require("../../utils");
  var Button_1 = require("../Button/Button");
  var Input_1 = require("../Input/Input");
  var Popup_1 = require("../Popup/Popup");
  var DatepickerCalendar_1 = require("./DatepickerCalendar");
  var DatepickerCalendarCell_1 = require("./DatepickerCalendarCell");
  var DatepickerCalendarCellButton_1 = require("./DatepickerCalendarCellButton");
  var DatepickerCalendarHeader_1 = require("./DatepickerCalendarHeader");
  var DatepickerCalendarHeaderAction_1 = require("./DatepickerCalendarHeaderAction");
  var DatepickerCalendarHeaderCell_1 = require("./DatepickerCalendarHeaderCell");
  var DatepickerCalendarGrid_1 = require("./DatepickerCalendarGrid");
  var DatepickerCalendarGridRow_1 = require("./DatepickerCalendarGridRow");
  var validateDate_1 = require("./validateDate");
  var utilities_1 = require("@uifabric/utilities");
  exports.datepickerClassName = 'ui-datepicker';
  var formatRestrictedInput = function (restrictedOptions, localizationStrings) {
      var formattedString = '';
      if (!!restrictedOptions.minDate && !!restrictedOptions.maxDate) {
          formattedString = utilities_1.format(localizationStrings.inputBoundedFormatString, localizationStrings.formatMonthDayYear(restrictedOptions.minDate, localizationStrings), localizationStrings.formatMonthDayYear(restrictedOptions.maxDate, localizationStrings));
      }
      else if (!!restrictedOptions.minDate) {
          formattedString = utilities_1.format(localizationStrings.inputMinBoundedFormatString, localizationStrings.formatMonthDayYear(restrictedOptions.minDate, localizationStrings));
      }
      else if (!!restrictedOptions.maxDate) {
          formattedString = utilities_1.format(localizationStrings.inputMaxBoundedFormatString, localizationStrings.formatMonthDayYear(restrictedOptions.maxDate, localizationStrings));
      }
      else {
          formattedString = localizationStrings.inputAriaLabel;
      }
      return formattedString;
  };
  /**
   * A Datepicker is a control which is used to display dates grid and allow user to select them.
   *
   * @accessibilityIssues
   * [NVDA - Aria-selected is not narrated for the gridcell](https://github.com/nvaccess/nvda/issues/11986)
   */
  var Datepicker = function (props) {
      var _a;
      var context = react_bindings_1.useFluentContext();
      var _b = react_bindings_1.useTelemetry(exports.Datepicker.displayName, context.telemetry), setStart = _b.setStart, setEnd = _b.setEnd;
      setStart();
      var inputRef = React.useRef();
      // FIXME: This object is created every render, causing a cascade of useCallback/useEffect re-runs.
      // Needs to be reworked by someone who understands the intent for when various updates ought to happen.
      // eslint-disable-next-line react-hooks/exhaustive-deps
      var dateFormatting = {
          formatDay: props.formatDay,
          formatYear: props.formatYear,
          formatMonthDayYear: props.formatMonthDayYear,
          formatMonthYear: props.formatMonthYear,
          parseDate: props.parseDate,
          months: props.months,
          shortMonths: props.shortMonths,
          days: props.days,
          shortDays: props.shortDays,
          isRequiredErrorMessage: props.isRequiredErrorMessage,
          invalidInputErrorMessage: props.invalidInputErrorMessage,
          isOutOfBoundsErrorMessage: props.isOutOfBoundsErrorMessage,
          goToToday: props.goToToday,
          openCalendarTitle: props.openCalendarTitle,
          inputPlaceholder: props.inputPlaceholder,
          prevMonthAriaLabel: props.prevMonthAriaLabel,
          nextMonthAriaLabel: props.nextMonthAriaLabel,
          prevYearAriaLabel: props.prevYearAriaLabel,
          nextYearAriaLabel: props.nextYearAriaLabel,
          prevYearRangeAriaLabel: props.prevYearRangeAriaLabel,
          nextYearRangeAriaLabel: props.nextYearRangeAriaLabel,
          monthPickerHeaderAriaLabel: props.monthPickerHeaderAriaLabel,
          yearPickerHeaderAriaLabel: props.yearPickerHeaderAriaLabel,
          closeButtonAriaLabel: props.closeButtonAriaLabel,
          weekNumberFormatString: props.weekNumberFormatString,
          selectedDateFormatString: props.selectedDateFormatString,
          todayDateFormatString: props.todayDateFormatString,
          inputAriaLabel: props.inputAriaLabel,
          inputBoundedFormatString: props.inputBoundedFormatString,
          inputMinBoundedFormatString: props.inputMinBoundedFormatString,
          inputMaxBoundedFormatString: props.inputMaxBoundedFormatString,
      };
      var calendar = props.calendar, popup = props.popup, input = props.input, className = props.className, design = props.design, styles = props.styles, variables = props.variables, formatMonthDayYear = props.formatMonthDayYear, allowManualInput = props.allowManualInput, ariaLabelledby = props["aria-labelledby"], ariaInvalid = props["aria-invalid"];
      var valueFormatter = React.useCallback(function (date) { return (date ? formatMonthDayYear(date, dateFormatting) : ''); }, [
          dateFormatting,
          formatMonthDayYear,
      ]);
      var _c = react_bindings_1.useAutoControlled({
          defaultValue: props.defaultCalendarOpenState,
          value: props.calendarOpenState,
          initialValue: false,
      }), openState = _c[0], setOpenState = _c[1];
      var _d = react_bindings_1.useAutoControlled({
          defaultValue: props.defaultSelectedDate,
          value: props.selectedDate,
          initialValue: undefined,
      }), selectedDate = _d[0], setSelectedDate = _d[1];
      var _e = React.useState(valueFormatter(selectedDate)), formattedDate = _e[0], setFormattedDate = _e[1];
      React.useEffect(function () {
          setFormattedDate(valueFormatter(selectedDate));
      }, [selectedDate, valueFormatter]);
      var restrictedDatesOptions = {
          minDate: props.minDate,
          maxDate: props.maxDate,
          restrictedDates: props.restrictedDates,
      };
      var _f = React.useState(function () {
          return !!props.selectedDate || !!props.defaultSelectedDate
              ? validateDate_1.validateDate(selectedDate, formattedDate, restrictedDatesOptions, dateFormatting, props.required)
              : '';
      }), error = _f[0], setError = _f[1];
      var calendarOptions = tslib_1.__assign({ selectedDate: selectedDate, navigatedDate: !!selectedDate && !error ? selectedDate : (_a = props.today) !== null && _a !== void 0 ? _a : new Date(), firstDayOfWeek: props.firstDayOfWeek, firstWeekOfYear: props.firstWeekOfYear, dateRangeType: props.dateRangeType, daysToSelectInDayView: props.daysToSelectInDayView, today: props.today, showWeekNumbers: props.showWeekNumbers, workWeekDays: props.workWeekDays }, restrictedDatesOptions);
      var ElementType = react_bindings_1.getElementType(props);
      var unhandledProps = react_bindings_1.useUnhandledProps(exports.Datepicker.handledProps, props);
      var getA11yProps = react_bindings_1.useAccessibility(props.accessibility, {
          debugName: exports.Datepicker.displayName,
          actionHandlers: {
              open: function (e) {
                  if (allowManualInput) {
                      setOpenState(!openState);
                  }
                  else {
                      // Keep popup open in case we can only enter the date through calendar.
                      setOpenState(true);
                  }
                  e.preventDefault();
              },
          },
          mapPropsToBehavior: function () { return ({
              'aria-invalid': ariaInvalid,
              'aria-labelledby': ariaLabelledby,
          }); },
          rtl: context.rtl,
      });
      var classes = react_bindings_1.useStyles(exports.Datepicker.displayName, {
          className: exports.datepickerClassName,
          mapPropsToStyles: function () { return ({
              allowManualInput: allowManualInput,
          }); },
          mapPropsToInlineStyles: function () { return ({
              className: className,
              design: design,
              styles: styles,
              variables: variables,
          }); },
          rtl: context.rtl,
      }).classes;
      var overrideDatepickerCalendarProps = function (predefinedProps) { return ({
          onDateChange: function (e, itemProps) {
              var targetDay = itemProps.value;
              setSelectedDate(targetDay.originalDate);
              setOpenState(false);
              setError('');
              setFormattedDate(valueFormatter(targetDay.originalDate));
              _.invoke(props, 'onDateChange', e, { itemProps: itemProps, value: targetDay.originalDate });
          },
      }); };
      var calendarElement = utils_1.createShorthand(DatepickerCalendar_1.DatepickerCalendar, calendar, {
          defaultProps: function () { return getA11yProps('calendar', tslib_1.__assign(tslib_1.__assign({}, calendarOptions), dateFormatting)); },
          overrideProps: overrideDatepickerCalendarProps,
      });
      var overrideInputProps = function (predefinedProps) { return ({
          onClick: function (e) {
              if (allowManualInput) {
                  setOpenState(!openState);
              }
              else {
                  // Keep popup open in case we can only enter the date through calendar.
                  setOpenState(true);
              }
              _.invoke(predefinedProps, 'onClick', e, predefinedProps);
          },
          onChange: function (e, target) {
              var parsedDate = props.parseDate(target.value);
              var validationError = validateDate_1.validateDate(parsedDate, target.value, calendarOptions, dateFormatting, props.required);
              setError(validationError);
              setFormattedDate(target.value);
              if (!!validationError) {
                  _.invoke(props, 'onDateChangeError', e, tslib_1.__assign(tslib_1.__assign({}, props), { error: validationError }));
              }
              else {
                  setSelectedDate(parsedDate);
                  _.invoke(props, 'onDateChange', e, tslib_1.__assign(tslib_1.__assign({}, props), { value: parsedDate }));
              }
              _.invoke(predefinedProps, 'onChange', e, predefinedProps);
          },
          onBlur: function (e) {
              if (props.fallbackToLastCorrectDateOnBlur && !!error) {
                  var futureFormattedDate = valueFormatter(selectedDate);
                  var validationError = validateDate_1.validateDate(selectedDate, futureFormattedDate, calendarOptions, dateFormatting, props.required);
                  setError(validationError);
                  setFormattedDate(futureFormattedDate);
                  if (!!validationError) {
                      _.invoke(props, 'onDateChangeError', e, tslib_1.__assign(tslib_1.__assign({}, props), { error: validationError }));
                  }
              }
              _.invoke(predefinedProps, 'onBlur', e, predefinedProps);
          },
          inputRef: function (node) {
              react_component_ref_1.handleRef(predefinedProps.inputRef, node);
              inputRef.current = node;
          },
      }); };
      var triggerButtonElement = props.inputOnly ? null : (React.createElement(Button_1.Button, { icon: React.createElement(react_icons_northstar_1.CalendarIcon, null), title: props.openCalendarTitle, iconOnly: true, disabled: props.disabled, type: "button" }));
      var element = getA11yProps.unstable_wrapWithFocusZone(React.createElement(ElementType, tslib_1.__assign({}, getA11yProps('root', tslib_1.__assign({ className: classes.root }, unhandledProps))),
          !props.buttonOnly &&
              utils_1.createShorthand(Input_1.Input, input, {
                  defaultProps: function () {
                      return getA11yProps('input', {
                          placeholder: props.inputPlaceholder,
                          disabled: props.disabled,
                          error: !!error,
                          value: formattedDate,
                          readOnly: !allowManualInput,
                          required: props.required,
                          'aria-label': formatRestrictedInput(restrictedDatesOptions, dateFormatting),
                      });
                  },
                  overrideProps: overrideInputProps,
              }),
          utils_1.createShorthand(Popup_1.Popup, popup, {
              defaultProps: function () { return ({
                  open: openState && !props.disabled,
                  trapFocus: {
                      disableFirstFocus: true,
                  },
                  position: 'below',
                  align: 'start',
              }); },
              overrideProps: function (predefinedProps) {
                  var _a;
                  return ({
                      trigger: (_a = predefinedProps.trigger) !== null && _a !== void 0 ? _a : triggerButtonElement,
                      target: props.buttonOnly ? null : inputRef.current,
                      content: calendarElement,
                      onOpenChange: function (e, _a) {
                          var open = _a.open;
                          // In case the event is a click on input, we ignore such events as it should be directly handled by input.
                          if (!(e.type === 'click' && e.target === (inputRef === null || inputRef === void 0 ? void 0 : inputRef.current))) {
                              setOpenState(open);
                              _.invoke(predefinedProps, 'onOpenChange', e, { open: open });
                          }
                      },
                  });
              },
          })));
      setEnd();
      return element;
  };
  exports.Datepicker = Datepicker;
  exports.Datepicker.displayName = 'Datepicker';
  exports.Datepicker.propTypes = tslib_1.__assign(tslib_1.__assign({}, utils_1.commonPropTypes.createCommon()), { calendar: customPropTypes.itemShorthand, popup: customPropTypes.itemShorthand, input: customPropTypes.itemShorthand, disabled: PropTypes.bool, required: PropTypes.bool, onDateChange: PropTypes.func, onDateChangeError: PropTypes.func, allowManualInput: PropTypes.bool, fallbackToLastCorrectDateOnBlur: PropTypes.bool, defaultCalendarOpenState: PropTypes.bool, calendarOpenState: PropTypes.bool, selectedDate: PropTypes.instanceOf(Date), defaultSelectedDate: PropTypes.instanceOf(Date), inputOnly: PropTypes.bool, buttonOnly: PropTypes.bool, minDate: PropTypes.instanceOf(Date), maxDate: PropTypes.instanceOf(Date), restrictedDates: PropTypes.arrayOf(PropTypes.instanceOf(Date)), firstDayOfWeek: PropTypes.oneOf(Object.keys(date_time_utilities_1.DayOfWeek).map(function (name) { return date_time_utilities_1.DayOfWeek[name]; })), firstWeekOfYear: PropTypes.oneOf(Object.keys(date_time_utilities_1.FirstWeekOfYear).map(function (name) { return date_time_utilities_1.FirstWeekOfYear[name]; })), dateRangeType: PropTypes.oneOf(Object.keys(date_time_utilities_1.DateRangeType).map(function (name) { return date_time_utilities_1.DateRangeType[name]; })), daysToSelectInDayView: PropTypes.number, today: PropTypes.instanceOf(Date), showWeekNumbers: PropTypes.bool, workWeekDays: PropTypes.arrayOf(PropTypes.oneOf(Object.keys(date_time_utilities_1.DayOfWeek).map(function (name) { return date_time_utilities_1.DayOfWeek[name]; }))), formatDay: PropTypes.func, formatYear: PropTypes.func, formatMonthDayYear: PropTypes.func, formatMonthYear: PropTypes.func, parseDate: PropTypes.func, months: PropTypes.arrayOf(PropTypes.string), shortMonths: PropTypes.arrayOf(PropTypes.string), days: PropTypes.arrayOf(PropTypes.string), shortDays: PropTypes.arrayOf(PropTypes.string), isRequiredErrorMessage: PropTypes.string, invalidInputErrorMessage: PropTypes.string, isOutOfBoundsErrorMessage: PropTypes.string, goToToday: PropTypes.string, openCalendarTitle: PropTypes.string, inputPlaceholder: PropTypes.string, prevMonthAriaLabel: PropTypes.string, nextMonthAriaLabel: PropTypes.string, prevYearAriaLabel: PropTypes.string, nextYearAriaLabel: PropTypes.string, prevYearRangeAriaLabel: PropTypes.string, nextYearRangeAriaLabel: PropTypes.string, monthPickerHeaderAriaLabel: PropTypes.string, yearPickerHeaderAriaLabel: PropTypes.string, closeButtonAriaLabel: PropTypes.string, weekNumberFormatString: PropTypes.string, selectedDateFormatString: PropTypes.string, todayDateFormatString: PropTypes.string, inputAriaLabel: PropTypes.string, inputBoundedFormatString: PropTypes.string, inputMinBoundedFormatString: PropTypes.string, inputMaxBoundedFormatString: PropTypes.string, 'aria-labelledby': PropTypes.string, 'aria-invalid': PropTypes.bool });
  exports.Datepicker.defaultProps = tslib_1.__assign({ accessibility: accessibility_1.datepickerBehavior, inputOnly: false, buttonOnly: false, calendar: {}, popup: {}, input: {}, firstDayOfWeek: date_time_utilities_1.DayOfWeek.Monday, firstWeekOfYear: date_time_utilities_1.FirstWeekOfYear.FirstDay, dateRangeType: date_time_utilities_1.DateRangeType.Day, fallbackToLastCorrectDateOnBlur: true, allowManualInput: true, required: false }, date_time_utilities_1.DEFAULT_CALENDAR_STRINGS);
  exports.Datepicker.handledProps = Object.keys(exports.Datepicker.propTypes);
  exports.Datepicker.create = utils_1.createShorthandFactory({ Component: exports.Datepicker });
  exports.Datepicker.Calendar = DatepickerCalendar_1.DatepickerCalendar;
  exports.Datepicker.CalendarHeader = DatepickerCalendarHeader_1.DatepickerCalendarHeader;
  exports.Datepicker.CalendarHeaderAction = DatepickerCalendarHeaderAction_1.DatepickerCalendarHeaderAction;
  exports.Datepicker.CalendarHeaderCell = DatepickerCalendarHeaderCell_1.DatepickerCalendarHeaderCell;
  exports.Datepicker.CalendarCell = DatepickerCalendarCell_1.DatepickerCalendarCell;
  exports.Datepicker.CalendarCellButton = DatepickerCalendarCellButton_1.DatepickerCalendarCellButton;
  exports.Datepicker.CalendarGrid = DatepickerCalendarGrid_1.DatepickerCalendarGrid;
  exports.Datepicker.CalendarGridRow = DatepickerCalendarGridRow_1.DatepickerCalendarGridRow;
  exports.Datepicker.Input = Input_1.Input;
  