@cbinsights/fds
Version:
Form: A design system by CB Insights
229 lines (180 loc) • 9.58 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 = exports.DATE_FORMAT_MAP = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _react = _interopRequireWildcard(require("react"));
var _dayjs = _interopRequireDefault(require("dayjs"));
var _customParseFormat = _interopRequireDefault(require("dayjs/plugin/customParseFormat"));
var _localizedFormat = _interopRequireDefault(require("dayjs/plugin/localizedFormat"));
var _utc = _interopRequireDefault(require("dayjs/plugin/utc"));
var _reactDayPicker = _interopRequireDefault(require("react-day-picker"));
var _DatePickerIcon = _interopRequireDefault(require("../../icons/react/DatePickerIcon"));
var _TextInput = _interopRequireDefault(require("../TextInput"));
var _YearAndMonthSelector = _interopRequireDefault(require("./YearAndMonthSelector"));
var _NavArrows = _interopRequireDefault(require("./NavArrows"));
var _util = require("./util");
var _Popover = _interopRequireDefault(require("../Popover"));
var _excluded = ["futureYears", "pastYears", "dateFormat", "popoverProps", "inputRef", "popoverRef", "defaultDate", "onDateChange", "onInputChange", "label", "labelPosition", "labelWidth", "minDate", "maxDate", "hasError", "errorText"];
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
_dayjs.default.extend(_customParseFormat.default);
_dayjs.default.extend(_localizedFormat.default);
_dayjs.default.extend(_utc.default); // Is this the correct way to localize dates? No, it is not.
// Fortunately, this is display-only.
//
// The I/O of DateInput is always a JS Date object, which ensures this
// hacky formatting is internal to DateInput and will never leak out.
var DATE_FORMAT_MAP = {
MDY: 'MM/DD/YYYY',
DMY: 'DD/MM/YYYY',
YMD: 'YYYY/MM/DD' // ISO-8601, the best but least used standard
};
exports.DATE_FORMAT_MAP = DATE_FORMAT_MAP;
/**
* @param {Object} props react props
* @returns {ReactElement}
*/
var DateInput = function DateInput(_ref) {
var _ref$futureYears = _ref.futureYears,
futureYears = _ref$futureYears === void 0 ? 1 : _ref$futureYears,
_ref$pastYears = _ref.pastYears,
pastYears = _ref$pastYears === void 0 ? 40 : _ref$pastYears,
_ref$dateFormat = _ref.dateFormat,
dateFormat = _ref$dateFormat === void 0 ? 'MDY' : _ref$dateFormat,
popoverProps = _ref.popoverProps,
inputRef = _ref.inputRef,
popoverRef = _ref.popoverRef,
defaultDateInput = _ref.defaultDate,
_ref$onDateChange = _ref.onDateChange,
onDateChange = _ref$onDateChange === void 0 ? function () {} : _ref$onDateChange,
_ref$onInputChange = _ref.onInputChange,
onInputChange = _ref$onInputChange === void 0 ? function () {} : _ref$onInputChange,
_ref$label = _ref.label,
label = _ref$label === void 0 ? '' : _ref$label,
labelPosition = _ref.labelPosition,
labelWidth = _ref.labelWidth,
minDate = _ref.minDate,
maxDate = _ref.maxDate,
hasError = _ref.hasError,
errorText = _ref.errorText,
rest = (0, _objectWithoutProperties2.default)(_ref, _excluded);
var defaultDate = defaultDateInput ? (0, _dayjs.default)(defaultDateInput).utc().toDate() : undefined;
var _useState = (0, _react.useState)(defaultDate),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
selectedDate = _useState2[0],
setSelectedDate = _useState2[1];
var _useState3 = (0, _react.useState)(defaultDate || new Date()),
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
pickerMonth = _useState4[0],
setPickerMonth = _useState4[1];
var _useState5 = (0, _react.useState)(dateFormat),
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
prevDateFormat = _useState6[0],
setPrevDateFormat = _useState6[1];
var _useState7 = (0, _react.useState)(defaultDate ? (0, _dayjs.default)(defaultDate).format(DATE_FORMAT_MAP[dateFormat]) : ''),
_useState8 = (0, _slicedToArray2.default)(_useState7, 2),
inputValue = _useState8[0],
setInputValue = _useState8[1];
var _useState9 = (0, _react.useState)(false),
_useState10 = (0, _slicedToArray2.default)(_useState9, 2),
isOpen = _useState10[0],
setIsOpen = _useState10[1]; // If the dateFormat prop changes while the input has a user-entered value,
// we want the value to change to reflect the new dateFormat
if (dateFormat !== prevDateFormat && inputValue.length > 0) {
// convert input value back into dayjs obj based on previous date format
var parsedInputValue = (0, _dayjs.default)(inputValue, prevDateFormat); // reformat the date in new `dateFormat`; set as new input value
setInputValue(parsedInputValue.format(DATE_FORMAT_MAP[dateFormat])); // store dateFormat for next render
setPrevDateFormat(dateFormat);
}
var _getYearRange = (0, _util.getYearRange)(new Date().getFullYear(), pastYears, futureYears, minDate, maxDate, selectedDate),
startYear = _getYearRange.startYear,
endYear = _getYearRange.endYear;
var openPopover = function openPopover() {
setIsOpen(true);
};
var closePopover = function closePopover() {
setIsOpen(false);
};
var handleYearMonthChange = function handleYearMonthChange(date) {
setPickerMonth(date);
};
var handleDaySelect = function handleDaySelect(date, modifiers) {
if (modifiers !== null && modifiers !== void 0 && modifiers.disabled) return;
setPickerMonth(date);
setSelectedDate(date);
setInputValue((0, _dayjs.default)(date).format(DATE_FORMAT_MAP[dateFormat]));
onDateChange(date);
closePopover();
};
var handleInputChange = function handleInputChange(_ref2) {
var value = _ref2.target.value;
setInputValue(value);
onInputChange(value); // when the user types a date that appears valid based on the given format,
// we attempt to parse the date string with dayjs. If the date is parsed
// as valid, update the selected day.
if ((0, _util.isValidUserDate)(value, dateFormat)) {
var parsedDate = (0, _dayjs.default)(value, DATE_FORMAT_MAP[dateFormat]);
if (parsedDate.isValid()) {
handleDaySelect(parsedDate.toDate());
}
} // if user backspaces to clear the input, clear out the picker
if (value === '') {
setSelectedDate(undefined);
onDateChange(null);
}
};
return /*#__PURE__*/_react.default.createElement(_Popover.default, (0, _extends2.default)({
ref: popoverRef,
interactionMode: "controlled",
isOpen: isOpen,
onUserDismiss: closePopover,
trigger: /*#__PURE__*/_react.default.createElement(_TextInput.default, (0, _extends2.default)({
"aria-label": "Date Input",
ref: inputRef
}, rest, {
hasError: hasError,
errorText: errorText,
label: label,
labelPosition: labelPosition,
labelWidth: labelWidth,
type: "text",
value: inputValue,
onFocus: openPopover,
onChange: handleInputChange,
placeholder: DATE_FORMAT_MAP[dateFormat],
pattern: "[0-9/]*",
IconRight: _DatePickerIcon.default
}))
}, popoverProps), /*#__PURE__*/_react.default.createElement("div", {
className: "elevation--2 rounded--all bgColor--white"
}, /*#__PURE__*/_react.default.createElement(_reactDayPicker.default, {
fromMonth: minDate,
toMonth: maxDate,
disabledDays: (0, _util.getDisabledDays)(minDate, maxDate),
month: pickerMonth,
className: "fdsDateInput",
onDayClick: handleDaySelect,
selectedDays: selectedDate,
showOutsideDays: true,
navbarElement: /*#__PURE__*/_react.default.createElement(_NavArrows.default, null),
captionElement: function captionElement(_ref3) {
var date = _ref3.date,
localeUtils = _ref3.localeUtils;
return /*#__PURE__*/_react.default.createElement(_YearAndMonthSelector.default, {
date: date,
localeUtils: localeUtils,
onChange: handleYearMonthChange,
startYear: startYear,
endYear: endYear
});
}
})));
};
var _default = DateInput;
exports.default = _default;