UNPKG

react-datetime-picker

Version:
547 lines (546 loc) 25.5 kB
"use strict"; 'use client'; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var jsx_runtime_1 = require("react/jsx-runtime"); var react_1 = require("react"); var date_utils_1 = require("@wojtekmaj/date-utils"); var Divider_js_1 = __importDefault(require("./Divider.js")); var DayInput_1 = __importDefault(require("react-date-picker/dist/cjs/DateInput/DayInput")); var MonthInput_1 = __importDefault(require("react-date-picker/dist/cjs/DateInput/MonthInput")); var MonthSelect_1 = __importDefault(require("react-date-picker/dist/cjs/DateInput/MonthSelect")); var YearInput_1 = __importDefault(require("react-date-picker/dist/cjs/DateInput/YearInput")); var Hour12Input_1 = __importDefault(require("react-time-picker/dist/cjs/TimeInput/Hour12Input")); var Hour24Input_1 = __importDefault(require("react-time-picker/dist/cjs/TimeInput/Hour24Input")); var MinuteInput_1 = __importDefault(require("react-time-picker/dist/cjs/TimeInput/MinuteInput")); var SecondInput_1 = __importDefault(require("react-time-picker/dist/cjs/TimeInput/SecondInput")); var AmPm_1 = __importDefault(require("react-time-picker/dist/cjs/TimeInput/AmPm")); var NativeInput_js_1 = __importDefault(require("./DateTimeInput/NativeInput.js")); var dateFormatter_js_1 = require("./shared/dateFormatter.js"); var dates_js_1 = require("./shared/dates.js"); var utils_js_1 = require("./shared/utils.js"); var getFormatterOptionsCache = {}; var defaultMinDate = new Date(); defaultMinDate.setFullYear(1, 0, 1); defaultMinDate.setHours(0, 0, 0, 0); var defaultMaxDate = new Date(8.64e15); var allViews = ['hour', 'minute', 'second']; function toDate(value) { if (value instanceof Date) { return value; } return new Date(value); } function isSameDate(date, year, month, day) { return (year === (0, date_utils_1.getYear)(date).toString() && month === (0, date_utils_1.getMonthHuman)(date).toString() && day === (0, date_utils_1.getDate)(date).toString()); } function getValue(value, index) { var rawValue = Array.isArray(value) ? value[index] : value; if (!rawValue) { return null; } var valueDate = toDate(rawValue); if (isNaN(valueDate.getTime())) { throw new Error("Invalid date: ".concat(value)); } return valueDate; } function getDetailValue(_a, index) { var value = _a.value, minDate = _a.minDate, maxDate = _a.maxDate; var valuePiece = getValue(value, index); if (!valuePiece) { return null; } return (0, utils_js_1.between)(valuePiece, minDate, maxDate); } var getDetailValueFrom = function (args) { return getDetailValue(args, 0); }; function isInternalInput(element) { return element.dataset.input === 'true'; } function findInput(element, property) { var nextElement = element; do { nextElement = nextElement[property]; } while (nextElement && !isInternalInput(nextElement)); return nextElement; } function focus(element) { if (element) { element.focus(); } } function renderCustomInputs(placeholder, elementFunctions, allowMultipleInstances) { var usedFunctions = []; var pattern = new RegExp(Object.keys(elementFunctions) .map(function (el) { return "".concat(el, "+"); }) .join('|'), 'g'); var matches = placeholder.match(pattern); return placeholder.split(pattern).reduce(function (arr, element, index) { var divider = element && ( // eslint-disable-next-line react/no-array-index-key (0, jsx_runtime_1.jsx)(Divider_js_1.default, { children: element }, "separator_".concat(index))); arr.push(divider); var currentMatch = matches && matches[index]; if (currentMatch) { var renderFunction = elementFunctions[currentMatch] || elementFunctions[Object.keys(elementFunctions).find(function (elementFunction) { return currentMatch.match(elementFunction); })]; if (!renderFunction) { return arr; } if (!allowMultipleInstances && usedFunctions.includes(renderFunction)) { arr.push(currentMatch); } else { arr.push(renderFunction(currentMatch, index)); usedFunctions.push(renderFunction); } } return arr; }, []); } var formatNumber = (0, dateFormatter_js_1.getNumberFormatter)({ useGrouping: false }); function DateTimeInput(_a) { var amPmAriaLabel = _a.amPmAriaLabel, autoFocus = _a.autoFocus, className = _a.className, dayAriaLabel = _a.dayAriaLabel, dayPlaceholder = _a.dayPlaceholder, disabled = _a.disabled, format = _a.format, hourAriaLabel = _a.hourAriaLabel, hourPlaceholder = _a.hourPlaceholder, isWidgetOpenProps = _a.isWidgetOpen, locale = _a.locale, maxDate = _a.maxDate, _b = _a.maxDetail, maxDetail = _b === void 0 ? 'minute' : _b, minDate = _a.minDate, minuteAriaLabel = _a.minuteAriaLabel, minutePlaceholder = _a.minutePlaceholder, monthAriaLabel = _a.monthAriaLabel, monthPlaceholder = _a.monthPlaceholder, _c = _a.name, name = _c === void 0 ? 'datetime' : _c, nativeInputAriaLabel = _a.nativeInputAriaLabel, onChangeProps = _a.onChange, onInvalidChange = _a.onInvalidChange, required = _a.required, secondAriaLabel = _a.secondAriaLabel, secondPlaceholder = _a.secondPlaceholder, showLeadingZeros = _a.showLeadingZeros, valueProps = _a.value, yearAriaLabel = _a.yearAriaLabel, yearPlaceholder = _a.yearPlaceholder; var _d = (0, react_1.useState)(null), amPm = _d[0], setAmPm = _d[1]; var _e = (0, react_1.useState)(null), year = _e[0], setYear = _e[1]; var _f = (0, react_1.useState)(null), month = _f[0], setMonth = _f[1]; var _g = (0, react_1.useState)(null), day = _g[0], setDay = _g[1]; var _h = (0, react_1.useState)(null), hour = _h[0], setHour = _h[1]; var _j = (0, react_1.useState)(null), minute = _j[0], setMinute = _j[1]; var _k = (0, react_1.useState)(null), second = _k[0], setSecond = _k[1]; var _l = (0, react_1.useState)(null), value = _l[0], setValue = _l[1]; var amPmInput = (0, react_1.useRef)(null); var yearInput = (0, react_1.useRef)(null); var monthInput = (0, react_1.useRef)(null); var monthSelect = (0, react_1.useRef)(null); var dayInput = (0, react_1.useRef)(null); var hour12Input = (0, react_1.useRef)(null); var hour24Input = (0, react_1.useRef)(null); var minuteInput = (0, react_1.useRef)(null); var secondInput = (0, react_1.useRef)(null); var _m = (0, react_1.useState)(isWidgetOpenProps), isWidgetOpen = _m[0], setIsWidgetOpenOpen = _m[1]; var lastPressedKey = (0, react_1.useRef)(undefined); (0, react_1.useEffect)(function () { setIsWidgetOpenOpen(isWidgetOpenProps); }, [isWidgetOpenProps]); (0, react_1.useEffect)(function () { var nextValue = getDetailValueFrom({ value: valueProps, minDate: minDate, maxDate: maxDate, }); if (nextValue) { setAmPm((0, dates_js_1.convert24to12)((0, date_utils_1.getHours)(nextValue))[1]); setYear((0, date_utils_1.getYear)(nextValue).toString()); setMonth((0, date_utils_1.getMonthHuman)(nextValue).toString()); setDay((0, date_utils_1.getDate)(nextValue).toString()); setHour((0, date_utils_1.getHours)(nextValue).toString()); setMinute((0, date_utils_1.getMinutes)(nextValue).toString()); setSecond((0, date_utils_1.getSeconds)(nextValue).toString()); setValue(toDate(nextValue)); } else { setAmPm(null); setYear(null); setMonth(null); setDay(null); setHour(null); setMinute(null); setSecond(null); setValue(null); } }, [ valueProps, minDate, maxDate, // Toggling widget visibility resets values isWidgetOpen, ]); var valueType = maxDetail; var formatTime = (function () { var level = allViews.indexOf(maxDetail); var formatterOptions = getFormatterOptionsCache[level] || (function () { var options = { hour: 'numeric' }; if (level >= 1) { options.minute = 'numeric'; } if (level >= 2) { options.second = 'numeric'; } getFormatterOptionsCache[level] = options; return options; })(); return (0, dateFormatter_js_1.getFormatter)(formatterOptions); })(); var datePlaceholder = (function () { var year = 2017; var monthIndex = 11; var day = 11; var date = new Date(year, monthIndex, day); var formattedDate = (0, dateFormatter_js_1.formatDate)(locale, date); var datePieces = ['year', 'month', 'day']; var datePieceReplacements = ['y', 'M', 'd']; function formatDatePiece(name, dateToFormat) { var formatterOptions = getFormatterOptionsCache[name] || (function () { var _a; var options = (_a = {}, _a[name] = 'numeric', _a); getFormatterOptionsCache[name] = options; return options; })(); return (0, dateFormatter_js_1.getFormatter)(formatterOptions)(locale, dateToFormat).match(/\d{1,}/); } var placeholder = formattedDate; datePieces.forEach(function (datePiece, index) { var match = formatDatePiece(datePiece, date); if (match) { var formattedDatePiece = match[0]; var datePieceReplacement = datePieceReplacements[index]; placeholder = placeholder.replace(formattedDatePiece, datePieceReplacement); } }); // See: https://github.com/wojtekmaj/react-date-picker/issues/396 placeholder = placeholder.replace('17', 'y'); return placeholder; })(); var timePlaceholder = (function () { var hour24 = 21; var hour12 = 9; var minute = 13; var second = 14; var date = new Date(2017, 0, 1, hour24, minute, second); return formatTime(locale, date) .replace(formatNumber(locale, hour12), 'h') .replace(formatNumber(locale, hour24), 'H') .replace(formatNumber(locale, minute), 'mm') .replace(formatNumber(locale, second), 'ss') .replace(new RegExp((0, utils_js_1.getAmPmLabels)(locale).join('|')), 'a'); })(); var placeholder = format || "".concat(datePlaceholder, "\u00A0").concat(timePlaceholder); var dateDivider = (function () { var dividers = datePlaceholder.match(/[^0-9a-z]/i); return dividers ? dividers[0] : null; })(); var timeDivider = (function () { var dividers = timePlaceholder.match(/[^0-9a-z]/i); return dividers ? dividers[0] : null; })(); var maxTime = (function () { if (!maxDate) { return undefined; } if (!isSameDate(maxDate, year, month, day)) { return undefined; } return (0, date_utils_1.getHoursMinutesSeconds)(maxDate || defaultMaxDate); })(); var minTime = (function () { if (!minDate) { return undefined; } if (!isSameDate(minDate, year, month, day)) { return undefined; } return (0, date_utils_1.getHoursMinutesSeconds)(minDate || defaultMinDate); })(); function onClick(event) { if (event.target === event.currentTarget) { // Wrapper was directly clicked var firstInput = event.target.children[1]; focus(firstInput); } } function onKeyDown(event) { lastPressedKey.current = event.key; switch (event.key) { case 'ArrowLeft': case 'ArrowRight': case dateDivider: case timeDivider: { event.preventDefault(); var input = event.target; var property = event.key === 'ArrowLeft' ? 'previousElementSibling' : 'nextElementSibling'; var nextInput = findInput(input, property); focus(nextInput); break; } default: } } function onKeyUp(event) { var key = event.key, input = event.target; var isLastPressedKey = lastPressedKey.current === key; if (!isLastPressedKey) { return; } var isNumberKey = !isNaN(Number(key)); if (!isNumberKey) { return; } var max = input.getAttribute('max'); if (!max) { return; } var value = input.value; /** * Given 1, the smallest possible number the user could type by adding another digit is 10. * 10 would be a valid value given max = 12, so we won't jump to the next input. * However, given 2, smallers possible number would be 20, and thus keeping the focus in * this field doesn't make sense. */ if (Number(value) * 10 > Number(max) || value.length >= max.length) { var property = 'nextElementSibling'; var nextInput = findInput(input, property); focus(nextInput); } } /** * Called after internal onChange. Checks input validity. If all fields are valid, * calls props.onChange. */ function onChangeExternal() { if (!onChangeProps) { return; } function filterBoolean(value) { return Boolean(value); } var formElements = [ amPmInput.current, dayInput.current, monthInput.current, monthSelect.current, yearInput.current, hour12Input.current, hour24Input.current, minuteInput.current, secondInput.current, ].filter(filterBoolean); var formElementsWithoutSelect = formElements.slice(1); var values = {}; formElements.forEach(function (formElement) { values[formElement.name] = formElement.type === 'number' ? 'valueAsNumber' in formElement ? formElement.valueAsNumber : Number(formElement.value) : formElement.value; }); var isEveryValueEmpty = formElementsWithoutSelect.every(function (formElement) { return !formElement.value; }); if (isEveryValueEmpty) { onChangeProps(null, false); return; } var isEveryValueFilled = formElements.every(function (formElement) { return formElement.value; }); var isEveryValueValid = formElements.every(function (formElement) { return formElement.validity.valid; }); if (isEveryValueFilled && isEveryValueValid) { var year_1 = Number(values.year || new Date().getFullYear()); var monthIndex = Number(values.month || 1) - 1; var day_1 = Number(values.day || 1); var hour_1 = Number(values.hour24 || (values.hour12 && values.amPm && (0, dates_js_1.convert12to24)(values.hour12, values.amPm)) || 0); var minute_1 = Number(values.minute || 0); var second_1 = Number(values.second || 0); var proposedValue = new Date(); proposedValue.setFullYear(year_1, monthIndex, day_1); proposedValue.setHours(hour_1, minute_1, second_1, 0); onChangeProps(proposedValue, false); return; } if (!onInvalidChange) { return; } onInvalidChange(); } /** * Called when non-native date input is changed. */ function onChange(event) { var _a = event.target, name = _a.name, value = _a.value; switch (name) { case 'amPm': setAmPm(value); break; case 'year': setYear(value); break; case 'month': setMonth(value); break; case 'day': setDay(value); break; case 'hour12': setHour(value ? (0, dates_js_1.convert12to24)(value, amPm || 'am').toString() : ''); break; case 'hour24': setHour(value); break; case 'minute': setMinute(value); break; case 'second': setSecond(value); break; } onChangeExternal(); } /** * Called when native date input is changed. */ function onChangeNative(event) { var value = event.target.value; if (!onChangeProps) { return; } var processedValue = (function () { if (!value) { return null; } var _a = value.split('T'), valueDate = _a[0], valueTime = _a[1]; var _b = valueDate.split('-'), yearString = _b[0], monthString = _b[1], dayString = _b[2]; var year = Number(yearString); var monthIndex = Number(monthString) - 1 || 0; var day = Number(dayString) || 1; var _c = valueTime.split(':'), hourString = _c[0], minuteString = _c[1], secondString = _c[2]; var hour = Number(hourString) || 0; var minute = Number(minuteString) || 0; var second = Number(secondString) || 0; var proposedValue = new Date(); proposedValue.setFullYear(year, monthIndex, day); proposedValue.setHours(hour, minute, second, 0); return proposedValue; })(); onChangeProps(processedValue, false); } var commonInputProps = { className: className, disabled: disabled, maxDate: maxDate || defaultMaxDate, minDate: minDate || defaultMinDate, onChange: onChange, onKeyDown: onKeyDown, onKeyUp: onKeyUp, // This is only for showing validity when editing required: Boolean(required || isWidgetOpen), }; var commonTimeInputProps = { maxTime: maxTime, minTime: minTime, }; function renderDay(currentMatch, index) { if (currentMatch && currentMatch.length > 2) { throw new Error("Unsupported token: ".concat(currentMatch)); } var showLeadingZerosFromFormat = currentMatch && currentMatch.length === 2; return ((0, jsx_runtime_1.jsx)(DayInput_1.default, __assign({}, commonInputProps, { ariaLabel: dayAriaLabel, // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus: index === 0 && autoFocus, inputRef: dayInput, month: month, placeholder: dayPlaceholder, showLeadingZeros: showLeadingZerosFromFormat || showLeadingZeros, value: day, year: year }), "day")); } function renderMonth(currentMatch, index) { if (currentMatch && currentMatch.length > 4) { throw new Error("Unsupported token: ".concat(currentMatch)); } if (currentMatch.length > 2) { return ((0, jsx_runtime_1.jsx)(MonthSelect_1.default, __assign({}, commonInputProps, { ariaLabel: monthAriaLabel, // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus: index === 0 && autoFocus, inputRef: monthSelect, locale: locale, placeholder: monthPlaceholder, short: currentMatch.length === 3, value: month, year: year }), "month")); } var showLeadingZerosFromFormat = currentMatch && currentMatch.length === 2; return ((0, jsx_runtime_1.jsx)(MonthInput_1.default, __assign({}, commonInputProps, { ariaLabel: monthAriaLabel, // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus: index === 0 && autoFocus, inputRef: monthInput, placeholder: monthPlaceholder, showLeadingZeros: showLeadingZerosFromFormat || showLeadingZeros, value: month, year: year }), "month")); } function renderYear(currentMatch, index) { return ((0, jsx_runtime_1.jsx)(YearInput_1.default, __assign({}, commonInputProps, { ariaLabel: yearAriaLabel, // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus: index === 0 && autoFocus, inputRef: yearInput, placeholder: yearPlaceholder, value: year, valueType: "day" }), "year")); } function renderHour12(currentMatch, index) { if (currentMatch && currentMatch.length > 2) { throw new Error("Unsupported token: ".concat(currentMatch)); } var showLeadingZeros = currentMatch ? currentMatch.length === 2 : false; return ((0, jsx_runtime_1.jsx)(Hour12Input_1.default, __assign({}, commonInputProps, commonTimeInputProps, { amPm: amPm, ariaLabel: hourAriaLabel, // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus: index === 0 && autoFocus, inputRef: hour12Input, placeholder: hourPlaceholder, showLeadingZeros: showLeadingZeros, value: hour }), "hour12")); } function renderHour24(currentMatch, index) { if (currentMatch && currentMatch.length > 2) { throw new Error("Unsupported token: ".concat(currentMatch)); } var showLeadingZeros = currentMatch ? currentMatch.length === 2 : false; return ((0, jsx_runtime_1.jsx)(Hour24Input_1.default, __assign({}, commonInputProps, commonTimeInputProps, { ariaLabel: hourAriaLabel, // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus: index === 0 && autoFocus, inputRef: hour24Input, placeholder: hourPlaceholder, showLeadingZeros: showLeadingZeros, value: hour }), "hour24")); } function renderHour(currentMatch, index) { if (/h/.test(currentMatch)) { return renderHour12(currentMatch, index); } return renderHour24(currentMatch, index); } function renderMinute(currentMatch, index) { if (currentMatch && currentMatch.length > 2) { throw new Error("Unsupported token: ".concat(currentMatch)); } var showLeadingZeros = currentMatch ? currentMatch.length === 2 : false; return ((0, jsx_runtime_1.jsx)(MinuteInput_1.default, __assign({}, commonInputProps, commonTimeInputProps, { ariaLabel: minuteAriaLabel, // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus: index === 0 && autoFocus, hour: hour, inputRef: minuteInput, placeholder: minutePlaceholder, showLeadingZeros: showLeadingZeros, value: minute }), "minute")); } function renderSecond(currentMatch, index) { if (currentMatch && currentMatch.length > 2) { throw new Error("Unsupported token: ".concat(currentMatch)); } var showLeadingZeros = currentMatch ? currentMatch.length === 2 : true; return ((0, jsx_runtime_1.jsx)(SecondInput_1.default, __assign({}, commonInputProps, commonTimeInputProps, { ariaLabel: secondAriaLabel, // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus: index === 0 && autoFocus, hour: hour, inputRef: secondInput, minute: minute, placeholder: secondPlaceholder, showLeadingZeros: showLeadingZeros, value: second }), "second")); } function renderAmPm(currentMatch, index) { return ((0, jsx_runtime_1.jsx)(AmPm_1.default, __assign({}, commonInputProps, commonTimeInputProps, { ariaLabel: amPmAriaLabel, // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus: index === 0 && autoFocus, inputRef: amPmInput, locale: locale, onChange: onChange, value: amPm }), "ampm")); } function renderCustomInputsInternal() { var elementFunctions = { d: renderDay, M: renderMonth, y: renderYear, h: renderHour, H: renderHour, m: renderMinute, s: renderSecond, a: renderAmPm, }; var allowMultipleInstances = typeof format !== 'undefined'; return renderCustomInputs(placeholder, elementFunctions, allowMultipleInstances); } function renderNativeInput() { return ((0, jsx_runtime_1.jsx)(NativeInput_js_1.default, { ariaLabel: nativeInputAriaLabel, disabled: disabled, maxDate: maxDate || defaultMaxDate, minDate: minDate || defaultMinDate, name: name, onChange: onChangeNative, required: required, value: value, valueType: valueType }, "datetime")); } return ( // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions (0, jsx_runtime_1.jsxs)("div", { className: className, onClick: onClick, children: [renderNativeInput(), renderCustomInputsInternal()] })); } exports.default = DateTimeInput;