terra-date-picker
Version:
The terra-date-picker component provides users a way to enter or select a date from the date picker.
913 lines (897 loc) • 40.9 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _react = _interopRequireWildcard(require("react"));
var _keycodeJs = require("keycode-js");
var _reactIntl = require("react-intl");
var _propTypes = _interopRequireDefault(require("prop-types"));
var _bind = _interopRequireDefault(require("classnames/bind"));
var _momentTimezone = _interopRequireDefault(require("moment-timezone"));
var _uuid = require("uuid");
var _terraButton = _interopRequireDefault(require("terra-button"));
var _IconCalendar = _interopRequireDefault(require("terra-icon/lib/icon/IconCalendar"));
var _terraFormInput = _interopRequireDefault(require("terra-form-input"));
var _terraThemeContext = _interopRequireDefault(require("terra-theme-context"));
var _terraVisuallyHiddenText = _interopRequireDefault(require("terra-visually-hidden-text"));
var _DateUtil = _interopRequireDefault(require("./DateUtil"));
var _DateInputLayout = _interopRequireDefault(require("./_DateInputLayout"));
var _date_utils = require("./react-datepicker/date_utils");
var _DatePickerModule = _interopRequireDefault(require("./DatePicker.module.scss"));
var _excluded = ["ariaLabel", "buttonRefCallback", "firstInputRefCallback", "id", "initialTimeZone", "inputAttributes", "intl", "isIncomplete", "isInvalid", "name", "onBlur", "onButtonFocus", "onChange", "onClick", "onFocus", "onKeyDown", "required", "useExternalFormatMask", "value", "excludeDates", "includeDates", "maxDate", "minDate", "filterDate", "errorId"];
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var cx = _bind.default.bind(_DatePickerModule.default);
var propTypes = {
/**
* String that labels the current element. 'aria-label' must be present for accessibility.
*/
ariaLabel: _propTypes.default.string,
/**
* Callback ref to pass into the calendar button dom element.
*/
buttonRefCallback: _propTypes.default.func,
/**
* Callback ref to pass into the first input dom element from Date Input components based on the date format order.
*/
firstInputRefCallback: _propTypes.default.func,
/**
* The id to append to the date input wrapper.
*/
id: _propTypes.default.string,
/**
* @private
* Timezone value to indicate in which timezone the date component is rendered.
* The value provided should be a valid [timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) string, else will default to browser/local timezone.
*/
initialTimeZone: _propTypes.default.string,
/**
* Custom input attributes to apply to the date input.
*/
inputAttributes: _propTypes.default.object,
/**
* @private
* intl object programmatically imported through injectIntl from react-intl.
* */
intl: _propTypes.default.shape({
formatMessage: _propTypes.default.func,
locale: _propTypes.default.string
}).isRequired,
/**
* Whether the input displays as Incomplete. Use when no value has been provided. _(usage note: `required` must also be set)_.
*/
isIncomplete: _propTypes.default.bool,
/**
* Whether the input displays as Invalid. Use when value does not meet validation pattern.
*/
isInvalid: _propTypes.default.bool,
/**
* Name of the date input.
*/
name: _propTypes.default.string,
/**
* A callback function triggered when the input or calendar button loses focus.
*/
onBlur: _propTypes.default.func,
/**
* A callback function triggered when the calendar button receives focus.
*/
onButtonFocus: _propTypes.default.func,
/**
* A callback function to execute when a valid date is selected or entered.
*/
onChange: _propTypes.default.func,
/**
* The onInputClick callback function from react-datepicker to show the picker when clicked.
*/
onClick: _propTypes.default.func,
/**
* A callback function triggered when the date input receives focus.
*/
onFocus: _propTypes.default.func,
/**
* The onInputKeyDown callback function from react-datepicker to handle keyboard navigation.
*/
onKeyDown: _propTypes.default.func,
/**
* Whether or not the date is required.
*/
required: _propTypes.default.bool,
/**
* @private
* Internal prop for showing date picker.
*/
shouldShowPicker: _propTypes.default.bool,
/**
* @private
* NOTICE: Internal prop to be used only by Terra framework. This component provides a built-in format mask that is
* required to be displayed to users for proper accessibility and must not be removed. 'DatePickerField' is permitted to set
* this prop because it provides the same format mask in its 'help' prop.
*/
useExternalFormatMask: _propTypes.default.bool,
/**
* The selected or entered date value to display in the date input.
*/
value: _propTypes.default.string,
/**
* @private
* An array of {@link moment} date objects of the dates to disable in the picker.
*/
excludeDates: _propTypes.default.arrayOf(_propTypes.default.objectOf(_momentTimezone.default)),
/**
* @private
* An array of {@link moment} date objects of the dates to enable in the picker. All Other dates will be disabled.
*/
includeDates: _propTypes.default.arrayOf(_propTypes.default.objectOf(_momentTimezone.default)),
/**
* @private
* An ISO 8601 string representation of the maximum date that can be selected. The value must be in the `YYYY-MM-DD` format. Must be on or before `12/31/2100`.
*/
maxDate: _propTypes.default.string,
/**
* @private
* An ISO 8601 string representation of the minimum date that can be selected. The value must be in the `YYYY-MM-DD` format. Must be on or after `01/01/1900`
*/
minDate: _propTypes.default.string,
/**
* A function that gets called for each date in the picker to evaluate which date should be disabled.
* A return value of true will be enabled and false will be disabled.
*/
filterDate: _propTypes.default.func,
/**
* .
* If invalid error text is used, provide a string containing the IDs for error html element.
* ID must be htmlFor prop value with error text.
*/
errorId: _propTypes.default.string
};
var defaultProps = {
ariaLabel: undefined,
buttonRefCallback: undefined,
id: undefined,
inputAttributes: undefined,
isIncomplete: false,
isInvalid: false,
name: undefined,
onBlur: undefined,
onButtonFocus: undefined,
onChange: undefined,
onClick: undefined,
onFocus: undefined,
onKeyDown: undefined,
required: false,
useExternalFormatMask: false,
value: undefined,
excludeDates: undefined,
includeDates: undefined,
maxDate: '2100-12-31',
minDate: '1900-01-01',
filterDate: undefined,
errorId: ''
};
var DatePickerInput = function DatePickerInput(props) {
var ariaLabel = props.ariaLabel,
buttonRefCallback = props.buttonRefCallback,
firstInputRefCallback = props.firstInputRefCallback,
id = props.id,
initialTimeZone = props.initialTimeZone,
inputAttributes = props.inputAttributes,
intl = props.intl,
isIncomplete = props.isIncomplete,
isInvalid = props.isInvalid,
name = props.name,
onBlur = props.onBlur,
onButtonFocus = props.onButtonFocus,
onChange = props.onChange,
onClick = props.onClick,
onFocus = props.onFocus,
onKeyDown = props.onKeyDown,
required = props.required,
useExternalFormatMask = props.useExternalFormatMask,
value = props.value,
excludeDates = props.excludeDates,
includeDates = props.includeDates,
maxDate = props.maxDate,
minDate = props.minDate,
filterDate = props.filterDate,
errorId = props.errorId,
customProps = (0, _objectWithoutProperties2.default)(props, _excluded);
var _useState = (0, _react.useState)(false),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
isFocused = _useState2[0],
setFocused = _useState2[1];
var _useState3 = (0, _react.useState)(false),
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
dayInitialFocused = _useState4[0],
setDayInitialFocused = _useState4[1];
var _useState5 = (0, _react.useState)(false),
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
monthInitialFocused = _useState6[0],
setMonthInitialFocused = _useState6[1];
var _useState7 = (0, _react.useState)(false),
_useState8 = (0, _slicedToArray2.default)(_useState7, 2),
yearInitialFocused = _useState8[0],
setYearInitialFocused = _useState8[1];
var editOnkeyDown = (0, _react.useRef)(false);
var theme = _react.default.useContext(_terraThemeContext.default);
// variables to store ref's for day, month and year input
var dayInputRef;
var monthInputRef;
var yearInputRef;
var visuallyHiddenComponent = null;
var onCalendarButtonClick = customProps.onCalendarButtonClick,
shouldShowPicker = customProps.shouldShowPicker;
delete customProps.onCalendarButtonClick;
delete customProps.shouldShowPicker;
var idFromInputAttributes;
var monthInputId;
var dayInputId;
var yearInputId;
if (inputAttributes && inputAttributes.id) {
// Get the inputAttributes.id and set it on the outer div and delete inputAttributes.id to prevent from setting the same id on all three inputs.
// Create new ids to set on each input using the inputAttributes.id.
idFromInputAttributes = inputAttributes.id;
monthInputId = idFromInputAttributes.concat('-terra-date-picker-month');
dayInputId = idFromInputAttributes.concat('-terra-date-picker-day');
yearInputId = idFromInputAttributes.concat('-terra-date-picker-year');
delete inputAttributes.id;
}
var additionalInputProps = _objectSpread(_objectSpread({}, customProps), inputAttributes);
var momentDateFormat = (0, _react.useMemo)(function () {
return _DateUtil.default.getFormatByLocale(intl.locale);
}, [intl.locale]);
var dateValue = (0, _react.useMemo)(function () {
return _DateUtil.default.convertToISO8601(value, momentDateFormat);
}, [momentDateFormat, value]);
var dateFormatOrder = _DateUtil.default.getDateFormatOrder(momentDateFormat);
var separator = _DateUtil.default.getDateSeparator(intl.locale);
var previousDateValueRef = (0, _react.useRef)();
var date = (0, _react.useMemo)(function () {
return {
day: '',
month: '',
year: ''
};
}, []);
// Sets the date state based on the passed in value prop, or if it changes via a calendar click.
if (_DateUtil.default.isValidDate(value, momentDateFormat)) {
date = _DateUtil.default.getDateInputValues(_DateUtil.default.dateOrder.YMD, dateValue, '-');
previousDateValueRef.current = date;
editOnkeyDown.current = false;
} else {
date = _DateUtil.default.validdateDateValues(value, dateFormatOrder, editOnkeyDown, previousDateValueRef);
}
// Triggers the onClick callback to launch the dropdown picker for the scenario when the default date is invalid and
// the calendar button is clicked which should clear the value and launch the dropdown picker
(0, _react.useEffect)(function () {
if (shouldShowPicker && onClick) {
onClick();
}
}, [shouldShowPicker, onClick]);
/**
* Moves focus to the correct input depending on date ordering. Focus changing is
* disabled if a complete date has been entered in order to make single input
* corrections easier, and is re-enabled if the whole date is erased.
* @param {string} inputValue - The value from the current input.
* @param {number} type - The input type, based on DateUtil.inputType.
*/
var moveFocusOnChange = function moveFocusOnChange(inputValue, type) {
if (dateFormatOrder === _DateUtil.default.dateOrder.MDY) {
if (inputValue.length === 2) {
if (type === _DateUtil.default.inputType.MONTH) {
dayInputRef.focus();
} else {
yearInputRef.focus();
}
}
} else if (dateFormatOrder === _DateUtil.default.dateOrder.DMY) {
if (inputValue.length === 2) {
if (type === _DateUtil.default.inputType.DAY) {
monthInputRef.focus();
} else {
yearInputRef.focus();
}
}
} else if (dateFormatOrder === _DateUtil.default.dateOrder.YMD) {
if (inputValue.length === 4) {
monthInputRef.focus();
} else if (inputValue.length === 2 && type === _DateUtil.default.inputType.MONTH) {
dayInputRef.focus();
}
}
};
/**
* Sets date value for the day, month, and year.
* @param {object} event - Event object
* @param {string} inputValue - The input value to set in state.
* @param {number} type - The inputType (day, month, or year).
*/
var setDate = function setDate(event, inputValue, type) {
if (type === _DateUtil.default.inputType.DAY) {
date.day = inputValue;
} else if (type === _DateUtil.default.inputType.MONTH) {
date.month = inputValue;
} else {
date.year = inputValue;
}
if (event.type !== 'keydown') {
moveFocusOnChange(inputValue, type);
}
};
var handleInvalidInputChange = function handleInvalidInputChange(inputValue) {
if (visuallyHiddenComponent && inputValue !== '+' && inputValue !== '=' && inputValue !== '-' && inputValue !== '_' && inputValue !== 't' && inputValue !== 'T') {
visuallyHiddenComponent.innerText = intl.formatMessage({
id: 'Terra.datePicker.invalidDate'
});
}
};
var setVisuallyHiddenComponent = function setVisuallyHiddenComponent(node) {
visuallyHiddenComponent = node;
};
/**
* Sets the day, month and year based on input values, formats them
* based on the date format variant, and passes the formatted date to onChange.
*/
var handleDateChange = function handleDateChange(event, inputValue, type) {
var _date = date,
day = _date.day,
month = _date.month,
year = _date.year;
if (type === _DateUtil.default.inputType.DAY) {
day = inputValue;
setDayInitialFocused(false);
} else if (type === _DateUtil.default.inputType.MONTH) {
month = inputValue;
setMonthInitialFocused(false);
} else {
year = inputValue;
setYearInitialFocused(false);
}
var inputDate;
var formattedDate;
if (day.length === 2 && month.length === 2 && year.length === 4) {
inputDate = _DateUtil.default.convertToISO8601("".concat(year, "-").concat(month, "-").concat(day), _DateUtil.default.ISO_EXTENDED_DATE_FORMAT);
formattedDate = _DateUtil.default.strictFormatISODate(inputDate, momentDateFormat);
}
if (onChange) {
if (_DateUtil.default.isValidDate(formattedDate, momentDateFormat)) {
onChange(event, formattedDate);
} else if (day === '' && month === '' && year === '') {
onChange(event, '');
} else {
var dateString;
if (dateFormatOrder === _DateUtil.default.dateOrder.MDY) {
dateString = month + separator + day + separator + year;
} else if (dateFormatOrder === _DateUtil.default.dateOrder.DMY) {
dateString = day + separator + month + separator + year;
} else {
dateString = year + separator + month + separator + day;
}
onChange(event, dateString);
}
}
setDate(event, inputValue, type);
};
var handleDayChange = function handleDayChange(event) {
var inputValue = event.target.value;
if (!_DateUtil.default.validDateInput(inputValue)) {
handleInvalidInputChange(inputValue);
return;
}
// Ignore the entry if the value did not change or it is invalid.
// When 'Predictive text' is enabled on Android the maxLength attribute on the input is ignored so we have to
// check the length of inputValue to make sure that it is less then 2.
if (inputValue === date.day || inputValue.length > 2 || Number(inputValue) > 31 || inputValue === '00') {
handleInvalidInputChange(inputValue);
return;
}
// If the change made was not a deletion of a digit, then prepend '0'
// when the input value is a single digit value between 4 and 9
if (inputValue.length >= date.day.length) {
var digitsToPrependZero = ['4', '5', '6', '7', '8', '9'];
if (digitsToPrependZero.indexOf(inputValue) > -1) {
inputValue = "0".concat(inputValue);
}
}
handleDateChange(event, inputValue, _DateUtil.default.inputType.DAY);
};
var handleMonthChange = function handleMonthChange(event) {
var inputValue = event.target.value;
if (!_DateUtil.default.validDateInput(inputValue)) {
handleInvalidInputChange(inputValue);
return;
}
// Ignore the entry if the value did not change or it is invalid.
// When 'Predictive text' is enabled on Android the maxLength attribute on the input is ignored so we have to
// check the length of inputValue to make sure that it is less then 2.
if (inputValue === date.month || inputValue.length > 2 || Number(inputValue) > 12 || inputValue === '00') {
handleInvalidInputChange(inputValue);
return;
}
// If the change made was not a deletion of a digit, then prepend '0'
// when the input value is a single digit value between 2 and 9
if (inputValue.length >= date.month.length) {
var digitsToPrependZero = ['2', '3', '4', '5', '6', '7', '8', '9'];
if (digitsToPrependZero.indexOf(inputValue) > -1) {
inputValue = "0".concat(inputValue);
}
}
handleDateChange(event, inputValue, _DateUtil.default.inputType.MONTH);
};
var handleYearChange = function handleYearChange(event) {
var inputValue = event.target.value;
if (!_DateUtil.default.validDateInput(inputValue)) {
handleInvalidInputChange(inputValue);
return;
}
// Ignore the entry if the value did not change or it is invalid.
// When 'Predictive text' is enabled on Android the maxLength attribute on the input is ignored so we have to
// check the length of inputValue to make sure that it is less then 4.
if (inputValue === date.year || inputValue.length > 4) {
handleInvalidInputChange(inputValue);
return;
}
// Ignore the 3rd entry if the first two digits are not 19, 20 or 21
if (inputValue.length === 3 && (Number(inputValue) < 190 || Number(inputValue) > 210)) {
handleInvalidInputChange(inputValue);
return;
}
// Ignore the 4th entry if the year value is not between MIN_YEAR and MAX_YEAR
if (inputValue.length === 4 && (Number(inputValue) < Number(_DateUtil.default.MIN_YEAR) || Number(inputValue) > Number(_DateUtil.default.MAX_YEAR))) {
handleInvalidInputChange(inputValue);
return;
}
handleDateChange(event, inputValue, _DateUtil.default.inputType.YEAR);
};
var setInputFocus = function setInputFocus(event, inputRef) {
inputRef.focus();
event.preventDefault();
};
var handleDayInputKeydown = function handleDayInputKeydown(event) {
if (inputAttributes !== null && inputAttributes !== void 0 && inputAttributes.readOnly) {
return;
}
if (dateFormatOrder === _DateUtil.default.dateOrder.MDY) {
if ((event.keyCode === _keycodeJs.KEY_LEFT || event.keyCode === _keycodeJs.KEY_DELETE || event.keyCode === _keycodeJs.KEY_BACK_SPACE) && date.day.length === 0) {
setInputFocus(event, monthInputRef);
} else if (event.keyCode === _keycodeJs.KEY_RIGHT && date.day.length === 0) {
setInputFocus(event, yearInputRef);
}
} else if (dateFormatOrder === _DateUtil.default.dateOrder.DMY) {
if (event.keyCode === _keycodeJs.KEY_RIGHT && date.day.length === 0) {
setInputFocus(event, monthInputRef);
}
} else if (dateFormatOrder === _DateUtil.default.dateOrder.YMD) {
if ((event.keyCode === _keycodeJs.KEY_LEFT || event.keyCode === _keycodeJs.KEY_DELETE || event.keyCode === _keycodeJs.KEY_BACK_SPACE) && date.day.length === 0) {
setInputFocus(event, monthInputRef);
}
}
};
var handleMonthInputKeydown = function handleMonthInputKeydown(event) {
if (inputAttributes !== null && inputAttributes !== void 0 && inputAttributes.readOnly) {
return;
}
if (dateFormatOrder === _DateUtil.default.dateOrder.MDY) {
if (event.keyCode === _keycodeJs.KEY_RIGHT && date.month.length === 0) {
setInputFocus(event, dayInputRef);
}
} else if (dateFormatOrder === _DateUtil.default.dateOrder.DMY) {
if ((event.keyCode === _keycodeJs.KEY_LEFT || event.keyCode === _keycodeJs.KEY_DELETE || event.keyCode === _keycodeJs.KEY_BACK_SPACE) && date.month.length === 0) {
setInputFocus(event, dayInputRef);
} else if (event.keyCode === _keycodeJs.KEY_RIGHT && date.month.length === 0) {
setInputFocus(event, yearInputRef);
}
} else if (dateFormatOrder === _DateUtil.default.dateOrder.YMD) {
if ((event.keyCode === _keycodeJs.KEY_LEFT || event.keyCode === _keycodeJs.KEY_DELETE || event.keyCode === _keycodeJs.KEY_BACK_SPACE) && date.month.length === 0) {
setInputFocus(event, yearInputRef);
} else if (event.keyCode === _keycodeJs.KEY_RIGHT && date.month.length === 0) {
setInputFocus(event, dayInputRef);
}
}
};
var handleYearInputKeydown = function handleYearInputKeydown(event) {
if (inputAttributes !== null && inputAttributes !== void 0 && inputAttributes.readOnly) {
return;
}
if (dateFormatOrder === _DateUtil.default.dateOrder.MDY) {
if ((event.keyCode === _keycodeJs.KEY_LEFT || event.keyCode === _keycodeJs.KEY_DELETE || event.keyCode === _keycodeJs.KEY_BACK_SPACE) && date.year.length === 0) {
setInputFocus(event, dayInputRef);
}
} else if (dateFormatOrder === _DateUtil.default.dateOrder.DMY) {
if ((event.keyCode === _keycodeJs.KEY_LEFT || event.keyCode === _keycodeJs.KEY_DELETE || event.keyCode === _keycodeJs.KEY_BACK_SPACE) && date.year.length === 0) {
setInputFocus(event, monthInputRef);
}
} else if (dateFormatOrder === _DateUtil.default.dateOrder.YMD) {
if (event.keyCode === _keycodeJs.KEY_RIGHT && date.year.length === 0) {
setInputFocus(event, monthInputRef);
}
}
};
var handleInputKeydown = function handleInputKeydown(event, inputType) {
editOnkeyDown.current = true;
var _date2 = date,
day = _date2.day,
month = _date2.month,
year = _date2.year;
var inputDate;
var formattedDate;
var inputTypeValue;
if (inputType === _DateUtil.default.inputType.DAY) {
inputTypeValue = _DateUtil.default.inputTypeString.DAYVALUE;
} else if (inputType === _DateUtil.default.inputType.MONTH) {
inputTypeValue = _DateUtil.default.inputTypeString.MONTHVALUE;
} else {
inputTypeValue = _DateUtil.default.inputTypeString.YEARVALUE;
}
if (day.length === 2 && month.length === 2 && year.length === 4 && event.key.match(/^[0-9]/g)) {
event.currentTarget.value = ''; // eslint-disable-line no-param-reassign
}
if (day.length === 2 && month.length === 2 && year.length === 4) {
inputDate = _DateUtil.default.convertToISO8601("".concat(year, "-").concat(month, "-").concat(day), _DateUtil.default.ISO_EXTENDED_DATE_FORMAT);
formattedDate = _DateUtil.default.strictFormatISODate(inputDate, momentDateFormat);
}
var validDate = _DateUtil.default.isValidDate(formattedDate, momentDateFormat);
// set date to today
if (event.key === 't' || event.key === 'T') {
inputDate = _DateUtil.default.getCurrentDate();
formattedDate = _DateUtil.default.strictFormatISODate(inputDate, momentDateFormat);
if (onChange) {
onChange(event, formattedDate);
}
var nextDayValues = _DateUtil.default.getDateInputValues(_DateUtil.default.dateOrder.YMD, inputDate, '-');
date = {
day: nextDayValues.day,
month: nextDayValues.month,
year: nextDayValues.year
};
event.preventDefault();
return;
}
if (event.key === '-' || event.key === '_' || event.keyCode === _keycodeJs.KEY_DOWN) {
if (validDate) {
inputDate = _DateUtil.default.decrementDate(inputDate, _DateUtil.default.ISO_EXTENDED_DATE_FORMAT, inputTypeValue);
} else {
inputDate = _DateUtil.default.decrementDate(_DateUtil.default.getCurrentDate(), _DateUtil.default.ISO_EXTENDED_DATE_FORMAT, inputTypeValue);
}
formattedDate = _DateUtil.default.strictFormatISODate(inputDate, momentDateFormat);
if (onChange) {
onChange(event, formattedDate);
}
var _nextDayValues = _DateUtil.default.getDateInputValues(_DateUtil.default.dateOrder.YMD, inputDate, '-');
date = {
day: _nextDayValues.day,
month: _nextDayValues.month,
year: _nextDayValues.year
};
event.preventDefault();
return;
}
if (event.key === '=' || event.key === '+' || event.keyCode === _keycodeJs.KEY_UP) {
if (validDate) {
inputDate = _DateUtil.default.incrementDate(inputDate, _DateUtil.default.ISO_EXTENDED_DATE_FORMAT, inputTypeValue);
} else {
inputDate = _DateUtil.default.incrementDate(_DateUtil.default.getCurrentDate(), _DateUtil.default.ISO_EXTENDED_DATE_FORMAT, inputTypeValue);
}
formattedDate = _DateUtil.default.strictFormatISODate(inputDate, momentDateFormat);
if (onChange) {
onChange(event, formattedDate);
}
var _nextDayValues2 = _DateUtil.default.getDateInputValues(_DateUtil.default.dateOrder.YMD, inputDate, '-');
date = {
day: _nextDayValues2.day,
month: _nextDayValues2.month,
year: _nextDayValues2.year
};
event.preventDefault();
return;
}
if (inputType === _DateUtil.default.inputType.YEAR) {
handleYearInputKeydown(event);
} else if (inputType === _DateUtil.default.inputType.MONTH) {
handleMonthInputKeydown(event);
} else if (inputType === _DateUtil.default.inputType.DAY) {
handleDayInputKeydown(event);
}
if (_DateUtil.default.isMac() && !event.key.match(/^[0-9]/g) && !(event.keyCode === _keycodeJs.KEY_BACK_SPACE || event.keyCode === _keycodeJs.KEY_DELETE || event.keyCode === _keycodeJs.KEY_TAB || event.keyCode === _keycodeJs.KEY_RIGHT || event.keyCode === _keycodeJs.KEY_LEFT)) {
event.preventDefault();
}
};
var handleOnInputFocus = function handleOnInputFocus(event, type) {
if (onFocus) {
onFocus(event);
}
setFocused(true);
if (type === _DateUtil.default.inputType.DAY) {
setDayInitialFocused(true);
} else if (type === _DateUtil.default.inputType.MONTH) {
setMonthInitialFocused(true);
} else {
setYearInitialFocused(true);
}
};
var handleOnInputBlur = function handleOnInputBlur(event, type) {
if (onBlur) {
onBlur(event);
}
setFocused(false);
if (type === _DateUtil.default.inputType.DAY) {
setDayInitialFocused(false);
} else if (type === _DateUtil.default.inputType.MONTH) {
setMonthInitialFocused(false);
} else {
setYearInitialFocused(false);
}
if (type === _DateUtil.default.inputType.DAY || type === _DateUtil.default.inputType.MONTH) {
var inputValue = event.target.value;
// Prepend a 0 to the value when losing focus and the value is single digit except 0.
// Append a 1 to the value when the single digit is 0
if (inputValue.length === 1) {
inputValue = inputValue === '0' ? '01' : '0'.concat(inputValue);
handleDateChange(event, inputValue, type);
}
} else if (type === _DateUtil.default.inputType.YEAR) {
var _inputValue = event.target.value;
if (_inputValue.length === 1) {
// Prepend a 200 to the value when losing focus and the value is single digit.
_inputValue = '200'.concat(_inputValue);
handleDateChange(event, _inputValue, type);
} else if (_inputValue.length === 2) {
// Prepend a 20 to the value when losing focus and the value is two digits.
_inputValue = '20'.concat(_inputValue);
handleDateChange(event, _inputValue, type);
} else if (_inputValue.length === 3 && (Number(_inputValue) >= 190 || Number(_inputValue) <= 210)) {
// Append a 0 to the value when losing focus and the value is three digits between 190 to 210.
_inputValue = _inputValue.concat('0');
handleDateChange(event, _inputValue, type);
}
}
};
var handleOnButtonClick = function handleOnButtonClick(event) {
var readOnly = inputAttributes === null || inputAttributes === void 0 ? void 0 : inputAttributes.readOnly;
if (!readOnly && onCalendarButtonClick && onClick) {
onCalendarButtonClick(event, onClick);
}
};
var handleOnButtonKeyDown = function handleOnButtonKeyDown(event) {
if (onKeyDown) {
onKeyDown(event);
}
};
var formatDescriptionId = "terra-date-picker-description-format-".concat((0, _uuid.v4)());
var ariaDescriptionIds;
if (useExternalFormatMask === false) {
if (inputAttributes && inputAttributes['aria-describedby']) {
ariaDescriptionIds = "".concat(formatDescriptionId, " ").concat(inputAttributes['aria-describedby']);
} else {
ariaDescriptionIds = formatDescriptionId;
}
} else if (inputAttributes && inputAttributes['aria-describedby']) {
ariaDescriptionIds = inputAttributes['aria-describedby'];
}
var dayInputClasses = cx(['date-input-day', {
'initial-focus': dayInitialFocused
}]);
var dateDayInput = /*#__PURE__*/_react.default.createElement(_terraFormInput.default, (0, _extends2.default)({}, additionalInputProps, {
// Both 'ref' and 'refCallback' are required here because:
// 'refCallback' returns the DOM element of the HTML input element
// 'ref' when used on a class component returns the mounted instance of the component
refCallback: function refCallback(node) {
dayInputRef = node;
},
ref: dateFormatOrder === _DateUtil.default.dateOrder.DMY ? firstInputRefCallback : undefined,
className: dayInputClasses,
type: "number",
name: "terra-date-day-".concat(name),
value: date.day,
onChange: handleDayChange,
onFocus: function onFocus(e) {
return handleOnInputFocus(e, _DateUtil.default.inputType.DAY);
},
onBlur: function onBlur(e) {
return handleOnInputBlur(e, _DateUtil.default.inputType.DAY);
},
onKeyDown: function onKeyDown(e) {
return handleInputKeydown(e, _DateUtil.default.inputType.DAY);
},
maxLength: "2",
size: "2",
pattern: "\\d*",
"aria-invalid": isInvalid,
"aria-required": required,
"aria-label": "".concat(ariaLabel ? "".concat(ariaLabel, " ").concat(intl.formatMessage({
id: 'Terra.datePicker.dayLabel'
})) : intl.formatMessage({
id: 'Terra.datePicker.dayLabel'
})),
"aria-describedby": "".concat(ariaDescriptionIds, " ").concat(errorId),
id: dayInputId
}));
var monthInputClasses = cx(['date-input-month', {
'initial-focus': monthInitialFocused
}]);
var dateMonthInput = /*#__PURE__*/_react.default.createElement(_terraFormInput.default, (0, _extends2.default)({}, additionalInputProps, {
// Both 'ref' and 'refCallback' are required here because:
// 'refCallback' returns the DOM element of the HTML input element
// 'ref' when used on a class component returns the mounted instance of the component
refCallback: function refCallback(node) {
monthInputRef = node;
},
ref: dateFormatOrder === _DateUtil.default.dateOrder.MDY ? firstInputRefCallback : undefined,
className: monthInputClasses,
type: "number",
name: "terra-date-month-".concat(name),
value: date.month,
onChange: handleMonthChange,
onFocus: function onFocus(e) {
return handleOnInputFocus(e, _DateUtil.default.inputType.MONTH);
},
onBlur: function onBlur(e) {
return handleOnInputBlur(e, _DateUtil.default.inputType.MONTH);
},
onKeyDown: function onKeyDown(e) {
return handleInputKeydown(e, _DateUtil.default.inputType.MONTH);
},
maxLength: "2",
size: "2",
pattern: "\\d*",
"aria-invalid": isInvalid,
"aria-required": required,
"aria-label": "".concat(ariaLabel ? "".concat(ariaLabel, " ").concat(intl.formatMessage({
id: 'Terra.datePicker.monthLabel'
})) : intl.formatMessage({
id: 'Terra.datePicker.monthLabel'
})),
"aria-describedby": "".concat(ariaDescriptionIds, " ").concat(errorId),
id: monthInputId
}));
var yearInputClasses = cx(['date-input-year', {
'initial-focus': yearInitialFocused
}]);
var dateYearInput = /*#__PURE__*/_react.default.createElement(_terraFormInput.default, (0, _extends2.default)({}, additionalInputProps, {
// Both 'ref' and 'refCallback' are required here because:
// 'refCallback' returns the DOM element of the HTML input element
// 'ref' when used on a class component returns the mounted instance of the component
refCallback: function refCallback(node) {
yearInputRef = node;
},
ref: dateFormatOrder === _DateUtil.default.dateOrder.YMD ? firstInputRefCallback : undefined,
className: yearInputClasses,
type: "number",
name: "terra-date-year-".concat(name),
value: date.year,
onChange: handleYearChange,
onFocus: function onFocus(e) {
return handleOnInputFocus(e, _DateUtil.default.inputType.YEAR);
},
onBlur: function onBlur(e) {
return handleOnInputBlur(e, _DateUtil.default.inputType.YEAR);
},
onKeyDown: function onKeyDown(e) {
return handleInputKeydown(e, _DateUtil.default.inputType.YEAR);
},
maxLength: "4",
size: "4",
pattern: "\\d*",
"aria-invalid": isInvalid,
"aria-required": required,
"aria-label": "".concat(ariaLabel ? "".concat(ariaLabel, " ").concat(intl.formatMessage({
id: 'Terra.datePicker.yearLabel'
})) : intl.formatMessage({
id: 'Terra.datePicker.yearLabel'
})),
"aria-describedby": "".concat(ariaDescriptionIds, " ").concat(errorId),
id: yearInputId
}));
var dateSpacer = /*#__PURE__*/_react.default.createElement("span", {
className: cx('date-spacer')
}, separator);
var dateInputClasses = cx(['date-input', {
'is-focused': isFocused
}, {
'is-invalid': isInvalid
}, {
'is-incomplete': isIncomplete && required && !isInvalid
}]);
var label = ariaLabel || intl.formatMessage({
id: 'Terra.datePicker.date'
});
var format = intl.formatMessage({
id: 'Terra.datePicker.dateFormat'
});
var buttonClasses = cx(['button', {
'is-invalid': isInvalid
}]);
// Indicates selected date from calendar popup for SR
var inputDate;
if (_DateUtil.default.isValidDate(value, momentDateFormat)) {
inputDate = "".concat((0, _date_utils.getLocalizedDateForScreenReader)(_DateUtil.default.createSafeDate(dateValue, initialTimeZone), {
intl: intl,
locale: intl.locale
}));
}
var calendarDate = inputDate ? "".concat(inputDate, " ").concat(intl.formatMessage({
id: 'Terra.datePicker.selected'
})) : '';
// Check if date is excluded or out of range or not included or filtered
var invalidEntry = '';
if (_DateUtil.default.isDateExcluded(_DateUtil.default.createSafeDate(dateValue, initialTimeZone), props.excludeDates) || _DateUtil.default.isDateOutOfRange(_DateUtil.default.createSafeDate(dateValue, initialTimeZone), _DateUtil.default.createSafeDate(_DateUtil.default.getMinDate(props.minDate), initialTimeZone), _DateUtil.default.createSafeDate(_DateUtil.default.getMaxDate(props.maxDate), initialTimeZone)) || _DateUtil.default.isDateNotIncluded(_DateUtil.default.createSafeDate(dateValue, initialTimeZone), props.includeDates) || props.filterDate && !props.filterDate(_DateUtil.default.createSafeDate(dateValue, initialTimeZone))) {
invalidEntry = "".concat(intl.formatMessage({
id: 'Terra.datePicker.invalidDate'
}), ".");
calendarDate = '';
}
return /*#__PURE__*/_react.default.createElement("div", {
className: cx(theme.className)
}, /*#__PURE__*/_react.default.createElement("div", {
className: cx('date-input-container')
}, /*#__PURE__*/_react.default.createElement("div", {
className: dateInputClasses,
id: id || idFromInputAttributes,
disabled: additionalInputProps.disabled
}, /*#__PURE__*/_react.default.createElement("input", {
// Create a hidden input for storing the name and value attributes to use when submitting the form.
// The data stored in the value attribute will be the visible date in the date input but in ISO 8601 format.
"data-terra-date-input-hidden": true,
type: "hidden",
name: name,
value: dateValue
}), /*#__PURE__*/_react.default.createElement(_terraVisuallyHiddenText.default, {
text: value ? "".concat(label, ", ").concat((0, _date_utils.getLocalizedDateForScreenReader)(_DateUtil.default.createSafeDate(dateValue, initialTimeZone), {
intl: intl,
locale: intl.locale
})) : label
}), /*#__PURE__*/_react.default.createElement(_terraVisuallyHiddenText.default, {
refCallback: setVisuallyHiddenComponent,
"aria-atomic": "true",
"aria-relevant": "all",
"aria-live": "assertive"
}), /*#__PURE__*/_react.default.createElement(_DateInputLayout.default, {
dateFormatOrder: dateFormatOrder,
separator: dateSpacer,
day: dateDayInput,
month: dateMonthInput,
year: dateYearInput
})), /*#__PURE__*/_react.default.createElement(_terraButton.default, {
"data-terra-open-calendar-button": true,
className: buttonClasses,
text: intl.formatMessage({
id: 'Terra.datePicker.openCalendar'
}),
onClick: handleOnButtonClick,
onKeyDown: handleOnButtonKeyDown,
icon: /*#__PURE__*/_react.default.createElement(_IconCalendar.default, null),
isIconOnly: true,
isCompact: true,
isDisabled: additionalInputProps.disabled,
onBlur: onBlur,
onFocus: onButtonFocus,
refCallback: buttonRefCallback,
"aria-label": "".concat(calendarDate, " ").concat(intl.formatMessage({
id: 'Terra.datePicker.openCalendar'
}))
})), !useExternalFormatMask && /*#__PURE__*/_react.default.createElement("div", {
id: formatDescriptionId,
className: cx('format-text')
}, /*#__PURE__*/_react.default.createElement(_terraVisuallyHiddenText.default, {
"aria-live": _DateUtil.default.isMac() ? 'polite' : 'off',
text: "".concat(invalidEntry, "\n ").concat(intl.formatMessage({
id: 'Terra.datePicker.dateFormatLabel'
}), "\n ").concat(format, ". ").concat(inputDate ? "".concat(inputDate, ",") : '', " ").concat(intl.formatMessage({
id: 'Terra.datePicker.hotKey'
}), ", ")
}), /*#__PURE__*/_react.default.createElement("div", {
"aria-hidden": "true"
}, "(".concat(format, ")"))));
};
DatePickerInput.propTypes = propTypes;
DatePickerInput.defaultProps = defaultProps;
var _default = exports.default = (0, _reactIntl.injectIntl)(DatePickerInput);