'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var clsx = require('clsx');
var React = require('react');
var reactIntl = require('react-intl');
var Body = require('../body/Body.js');
var Input = require('../inputs/Input.js');
var SelectInput = require('../inputs/SelectInput/SelectInput.js');
require('@transferwise/icons');
require('../dateLookup/dateTrigger/DateTrigger.messages.js');
var jsxRuntime = require('react/jsx-runtime');
require('@headlessui/react');
var SelectInputOptionContent = require('../inputs/SelectInput/OptionContent/SelectInputOptionContent.js');
require('merge-props');
var contexts = require('../inputs/contexts.js');
require('../header/Header.js');
require('virtua');
require('../common/theme.js');
require('../common/direction.js');
require('@transferwise/neptune-tokens');
require('../common/propsValues/control.js');
var size = require('../common/propsValues/size.js');
var typography = require('../common/propsValues/typography.js');
require('../common/propsValues/width.js');
require('../common/propsValues/type.js');
var dateMode = require('../common/propsValues/dateMode.js');
var monthFormat = require('../common/propsValues/monthFormat.js');
require('../common/propsValues/position.js');
require('../common/propsValues/layouts.js');
require('../common/propsValues/status.js');
require('../common/propsValues/sentiment.js');
require('../common/propsValues/profileType.js');
require('../common/propsValues/variant.js');
require('../common/propsValues/scroll.js');
require('../common/propsValues/markdownNodeType.js');
require('../common/fileType.js');
require('@transferwise/formatting');
require('../common/closeButton/CloseButton.messages.js');
require('../inputs/SelectInput/SelectInput.messages.js');
var getMonthNames = require('../common/dateUtils/getMonthNames/getMonthNames.js');
var isDateValid = require('../common/dateUtils/isDateValid/isDateValid.js');
var isMonthAndYearFormat = require('../common/dateUtils/isMonthAndYearFormat/isMonthAndYearFormat.js');
var getFormatForLocale = require('../common/dateUtils/getFormatForLocale/getFormatForLocale.js');
var DateInput_messages = require('./DateInput.messages.js');
var convertToLocalMidnight = require('./utils/convertToLocalMidnight/convertToLocalMidnight.js');

const DATE_INPUT_PARENT_ID = 'dateInput';
const DateInput = ({
  'aria-labelledby': ariaLabelledByProp,
  'aria-label': ariaLabel,
  disabled = false,
  size: size$1 = size.Size.MEDIUM,
  value,
  dayLabel,
  dayAutoComplete,
  monthLabel,
  yearLabel,
  yearAutoComplete,
  monthFormat: monthFormat$1 = monthFormat.MonthFormat.LONG,
  mode = dateMode.DateMode.DAY_MONTH_YEAR,
  onChange,
  onFocus,
  onBlur,
  placeholders,
  id: idProp,
  selectProps = {}
}) => {
  const inputAttributes = contexts.useInputAttributes({
    nonLabelable: true
  });
  const fieldLabelRef = contexts.useFieldLabelRef();
  const dayRef = React.useRef(null);
  const monthRef = React.useRef(null);
  const yearRef = React.useRef(null);
  const id = idProp ?? inputAttributes.id;
  const ariaLabelledBy = ariaLabelledByProp ?? inputAttributes['aria-labelledby'];
  const {
    locale,
    formatMessage
  } = reactIntl.useIntl();
  const getDateObject = () => {
    if (value && isDateValid.isDateValid(value)) {
      return typeof value === 'string' ? convertToLocalMidnight.convertToLocalMidnight(value) : value;
    }
    return undefined;
  };
  const getInitialDate = unit => {
    if (value && isDateValid.isDateValid(value)) {
      const dateObject = getDateObject();
      if (typeof value === 'string' && isMonthAndYearFormat.isMonthAndYearFormat(value) && unit === 'day') {
        return null;
      }
      if (dateObject !== undefined) {
        switch (unit) {
          case 'year':
            return dateObject.getFullYear();
          case 'month':
            return dateObject.getMonth();
          case 'day':
            return dateObject.getDate();
          default:
            return null;
        }
      }
    }
    return null;
  };
  const [day, setDay] = React.useState(() => getInitialDate('day'));
  const [displayDay, setDisplayDay] = React.useState(day?.toString());
  const [month, setMonth] = React.useState(() => getInitialDate('month'));
  const [year, setYear] = React.useState(() => getInitialDate('year'));
  const [displayYear, setDisplayYear] = React.useState(year?.toString());
  const [lastBroadcastedValue, setLastBroadcastedValue] = React.useState(getDateObject);
  const monthNames = getMonthNames.getMonthNames(locale, monthFormat$1);
  const monthYearOnly = mode === dateMode.DateMode.MONTH_YEAR;
  const monthBeforeDay = getFormatForLocale.MDY.has(locale);
  const yearFirst = getFormatForLocale.YMD.has(locale);
  const resolvedDayLabel = dayLabel || formatMessage(DateInput_messages.default.dayLabel);
  const resolvedMonthLabel = monthLabel || formatMessage(DateInput_messages.default.monthLabel);
  const resolvedYearLabel = yearLabel || formatMessage(DateInput_messages.default.yearLabel);
  const resolvedPlaceholders = {
    day: placeholders?.day || formatMessage(DateInput_messages.default.dayPlaceholder),
    month: placeholders?.month || formatMessage(DateInput_messages.default.monthLabel),
    year: placeholders?.year || formatMessage(DateInput_messages.default.yearPlaceholder)
  };
  React.useEffect(() => {
    const labelRef = fieldLabelRef?.current;
    if (labelRef) {
      const handleLabelClick = () => {
        // Not the best way to do this, but we're forced to recreate the native Label-click behavior
        if (monthYearOnly || monthBeforeDay) {
          monthRef.current?.click();
        } else if (yearFirst) {
          yearRef.current?.focus();
        } else {
          dayRef.current?.focus();
        }
      };
      labelRef.addEventListener('click', handleLabelClick);
      return () => {
        labelRef?.removeEventListener('click', handleLabelClick);
      };
    }
  }, [fieldLabelRef, id, monthBeforeDay, monthYearOnly, yearFirst]);
  const getDateAsString = date => {
    if (!isDateValid.isDateValid(date)) {
      return '';
    }
    switch (mode) {
      case dateMode.DateMode.MONTH_YEAR:
        return [date.getFullYear(), `0${date.getMonth() + 1}`.slice(-2)].join('-');
      case dateMode.DateMode.DAY_MONTH_YEAR:
      default:
        return [date.getFullYear(), `0${date.getMonth() + 1}`.slice(-2), `0${date.getDate()}`.slice(-2)].join('-');
    }
  };
  const getSelectElement = () => {
    return /*#__PURE__*/jsxRuntime.jsxs("label", {
      className: "d-flex flex-column",
      children: [/*#__PURE__*/jsxRuntime.jsx(Body.default, {
        type: typography.Typography.BODY_DEFAULT,
        children: resolvedMonthLabel
      }), /*#__PURE__*/jsxRuntime.jsx(SelectInput.SelectInput, {
        triggerRef: monthRef,
        id: `${id}:month`,
        parentId: DATE_INPUT_PARENT_ID,
        name: "month",
        disabled: disabled,
        placeholder: resolvedPlaceholders.month,
        items: Array.from({
          length: 12
        }, (_, index) => ({
          type: 'option',
          value: index
        })),
        size: size$1,
        value: month,
        renderValue: selectedValue => /*#__PURE__*/jsxRuntime.jsx(SelectInputOptionContent.SelectInputOptionContent, {
          title: monthNames[selectedValue]
        }),
        onChange: selectedValue => handleMonthChange(selectedValue),
        ...selectProps
      })]
    });
  };
  const isDayValid = (newDay, newMonth, newYear) => {
    const maxDay = new Date(newYear, newMonth + 1, 0).getDate();
    return newDay <= maxDay;
  };
  const handleInternalValue = (newDay = day, newMonth = month, newYear = year) => {
    if (newDay == null || newDay === 0 || newMonth == null || newYear == null || newYear === 0) {
      broadcastNewValue(null);
      return;
    }
    if (!isDayValid(newDay, newMonth, newYear)) {
      broadcastNewValue(null);
      return;
    }
    const dateValue = new Date(newYear, newMonth, newDay);
    if (newYear < 100) {
      dateValue.setFullYear(newYear);
    }
    if (!isDateValid.isDateValid(dateValue)) {
      broadcastNewValue(null);
      return;
    }
    if (mode === dateMode.DateMode.MONTH_YEAR) {
      if (newMonth !== month || newYear !== year) {
        broadcastNewValue(dateValue);
      }
    } else if (newDay !== day || newMonth !== month || newYear !== year) {
      broadcastNewValue(dateValue);
    }
  };
  const handleDayChange = event => {
    const newDayString = event.target.value.replace(/\D/g, '');
    const newDayNumber = Number.parseInt(newDayString, 10);
    setDay(newDayNumber);
    setDisplayDay(newDayString);
    handleInternalValue(newDayNumber, month, year);
  };
  const handleMonthChange = selectedMonth => {
    if (selectedMonth === null) {
      setMonth(null);
      handleInternalValue(day, null, year);
      return;
    }
    setMonth(selectedMonth);
    handleInternalValue(day, selectedMonth, year);
  };
  const handleYearChange = event => {
    const newYearString = event.target.value.replace(/\D/g, '');
    const newYearNumber = Number.parseInt(newYearString, 10);
    if (newYearString.length >= 4 && newYearString.length <= 6) {
      setYear(newYearNumber);
      setDisplayYear(newYearString);
      handleInternalValue(day, month, newYearNumber);
    } else {
      setYear(null);
      setDisplayYear(newYearString);
      handleInternalValue(day, month, null);
    }
  };
  const broadcastNewValue = newValue => {
    if (newValue !== lastBroadcastedValue) {
      setLastBroadcastedValue(newValue);
      onChange(newValue != null ? getDateAsString(newValue) : null);
    }
  };
  const monthWidth = clsx.clsx({
    'col-sm-8 tw-date--month': monthYearOnly,
    'col-sm-5 tw-date--month': !monthYearOnly
  });
  const getMonth = () => {
    return /*#__PURE__*/jsxRuntime.jsx("div", {
      className: monthWidth,
      children: getSelectElement()
    });
  };
  const getDay = () => {
    return /*#__PURE__*/jsxRuntime.jsx("div", {
      className: "col-sm-3 tw-date--day",
      children: /*#__PURE__*/jsxRuntime.jsxs("label", {
        children: [/*#__PURE__*/jsxRuntime.jsx(Body.default, {
          type: typography.Typography.BODY_DEFAULT,
          children: resolvedDayLabel
        }), /*#__PURE__*/jsxRuntime.jsx("div", {
          className: `input-group input-group-${size$1} ${disabled ? 'disabled' : ''}`,
          children: /*#__PURE__*/jsxRuntime.jsx(Input.Input, {
            ref: dayRef,
            id: `${id}:day`,
            type: "text",
            inputMode: "numeric",
            pattern: "[0-9]*",
            name: "day",
            autoComplete: dayAutoComplete,
            value: displayDay || '',
            placeholder: resolvedPlaceholders.day,
            disabled: disabled,
            min: 1,
            max: 31,
            maxLength: 2,
            onChange: event => handleDayChange(event)
          })
        })]
      })
    });
  };
  const getYear = () => {
    return /*#__PURE__*/jsxRuntime.jsx("div", {
      className: "col-sm-4 tw-date--year",
      children: /*#__PURE__*/jsxRuntime.jsxs("label", {
        children: [/*#__PURE__*/jsxRuntime.jsx(Body.default, {
          type: typography.Typography.BODY_DEFAULT,
          children: resolvedYearLabel
        }), /*#__PURE__*/jsxRuntime.jsx("div", {
          className: `input-group input-group-${size$1} ${disabled ? 'disabled' : ''}`,
          children: /*#__PURE__*/jsxRuntime.jsx(Input.Input, {
            ref: yearRef,
            id: `${id}:year`,
            type: "text",
            inputMode: "numeric",
            pattern: "[0-9]*",
            name: "year",
            autoComplete: yearAutoComplete,
            placeholder: resolvedPlaceholders.year,
            value: displayYear || '',
            disabled: disabled,
            min: 0,
            max: 9999,
            maxLength: 6,
            onChange: event => handleYearChange(event)
          })
        })]
      })
    });
  };
  return /*#__PURE__*/jsxRuntime.jsx("fieldset", {
    id: id,
    className: "tw-date",
    "aria-describedby": inputAttributes['aria-describedby'],
    "aria-invalid": inputAttributes['aria-invalid'],
    "aria-labelledby": ariaLabelledBy,
    "aria-label": ariaLabel,
    "data-wds-dateinput": "",
    onFocus: event => shouldPropagateOnFocus(event) ? onFocus?.(event) : event.stopPropagation(),
    onBlur: event => shouldPropagateOnBlur(event) ? onBlur?.(event) : event.stopPropagation(),
    children: /*#__PURE__*/jsxRuntime.jsx("div", {
      className: "row",
      children: (() => {
        if (monthYearOnly) {
          return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
            children: [!yearFirst && getMonth(), getYear(), yearFirst && getMonth()]
          });
        }
        if (monthBeforeDay) {
          return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
            children: [getMonth(), getDay(), getYear()]
          });
        }
        if (yearFirst) {
          return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
            children: [getYear(), getMonth(), getDay()]
          });
        }
        return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
          children: [getDay(), getMonth(), getYear()]
        });
      })()
    })
  });
};
// Should only propagate if the relatedTarget is not part of this DateInput component.
function shouldPropagateOnFocus({
  target,
  relatedTarget
}) {
  const blurredElementParent = target.closest('[data-wds-dateinput]');
  const focusedElementParent = relatedTarget?.closest('[data-wds-dateinput]');
  return blurredElementParent !== focusedElementParent;
}
// Should only propagate if the focus-gaining element is not part
// of this DateInput component or the (dropdown) of the month select.
function shouldPropagateOnBlur({
  target,
  relatedTarget
}) {
  const blurredElementParent = target.closest('[data-wds-dateinput]');
  const focusedElementParent = relatedTarget?.closest('[data-wds-dateinput]');
  return blurredElementParent !== focusedElementParent && !target?.closest(`[data-wds-parent="${DATE_INPUT_PARENT_ID}"]`) && !relatedTarget?.closest(`[data-wds-parent="${DATE_INPUT_PARENT_ID}"]`);
}

exports.default = DateInput;
//# sourceMappingURL=DateInput.js.map
