UNPKG

reactstrap-date-picker

Version:

Reactstrap based, zero dependencies, date picker

1,330 lines (1,280 loc) 46.7 kB
/** * reactstrap-date-picker v2.0.0-beta.2 * * https://reactstrap-date-picker.afialapis.com/ * * Copyright (c) Donato Lorenzo <donato@afialapis.com> * * This source code is licensed under the MIT license found in the * LICENSE.md file in the root directory of this source tree. * * @license MIT */ 'use strict'; var React = require('react'); var reactstrap = require('reactstrap'); var useCheckProps = function useCheckProps(value, defaultValue) { if (value && defaultValue) { return 'Conflicting DatePicker properties \'value\' and \'defaultValue\''; } return undefined; }; var InputGroup = function InputGroup(_ref) { var children = _ref.children, customInputGroup = _ref.customInputGroup, size = _ref.size, inputId = _ref.inputId; if (customInputGroup != undefined) { return /*#__PURE__*/React.cloneElement(customInputGroup, { children: children }); } return /*#__PURE__*/React.createElement(reactstrap.InputGroup, { size: size, id: inputId, className: "rdp-input-group" }, children); }; var InputOverlay = function InputOverlay(_ref) { var oid = _ref.oid, overlayContainerRef = _ref.overlayContainerRef, children = _ref.children; return /*#__PURE__*/React.createElement("div", { ref: overlayContainerRef, id: oid, className: "rdp-overlay" }, children); }; var InputHidden = function InputHidden(_ref) { var inputId = _ref.inputId, name = _ref.name, value = _ref.value, formattedValue = _ref.formattedValue, hiddenInputRef = _ref.hiddenInputRef; return /*#__PURE__*/React.createElement("input", { ref: hiddenInputRef, type: "hidden", className: "rdp-hidden", id: inputId, name: name, value: value || '', "data-formattedvalue": formattedValue }); }; var InputClearButton = function InputClearButton(_ref) { var inputValue = _ref.inputValue, disabled = _ref.disabled, clearButtonElement = _ref.clearButtonElement, _onClick = _ref.onClick; return /*#__PURE__*/React.createElement("div", { className: "rdp-addon input-group-append" }, /*#__PURE__*/React.createElement(reactstrap.InputGroupText, { onClick: function onClick() { return disabled ? null : _onClick(); }, style: { opacity: inputValue && !disabled ? 1 : 0.5, cursor: inputValue && !disabled ? 'pointer' : 'not-allowed' } }, clearButtonElement)); }; function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } var InputControlInput = function InputControlInput(_ref) { var customControl = _ref.customControl, controlId = _ref.controlId, value = _ref.value, required = _ref.required, placeholder = _ref.placeholder, inputRef = _ref.inputRef, disabled = _ref.disabled, className = _ref.className, style = _ref.style, autoFocus = _ref.autoFocus, autoComplete = _ref.autoComplete, valid = _ref.valid, invalid = _ref.invalid, onInvalid = _ref.onInvalid, noValidate = _ref.noValidate, onKeyDown = _ref.onKeyDown, onFocus = _ref.onFocus, onBlur = _ref.onBlur, onChange = _ref.onChange; var validityClassNames = (invalid === true ? 'is-invalid' : '') + " " + (valid === true ? 'is-valid' : ''); if (customControl != undefined) { return /*#__PURE__*/React.cloneElement(customControl, { id: controlId, value: value || '', required: required, placeholder: placeholder, ref: inputRef, disabled: disabled, className: "rdp-form-control " + (className || '') + " " + (customControl.props.className || '') + " " + validityClassNames, style: _extends({}, customControl.props.style || {}, style || {}), autoComplete: autoComplete, onInvalid: onInvalid, noValidate: noValidate, onKeyDown: onKeyDown, onFocus: onFocus, onBlur: onBlur, onChange: onChange, valid: valid, invalid: invalid }); } return /*#__PURE__*/React.createElement(reactstrap.Input, { id: controlId, name: controlId, value: value || '', required: required, placeholder: placeholder, innerRef: inputRef, disabled: disabled, type: "text", className: "rdp-form-control " + (className || '') + " " + validityClassNames, style: style, autoFocus: autoFocus, autoComplete: autoComplete, onInvalid: onInvalid, noValidate: noValidate, onKeyDown: onKeyDown, onFocus: onFocus, onBlur: onBlur, onChange: onChange, valid: valid, invalid: invalid }); }; var setTimeToNoon = function setTimeToNoon(date) { if (!date) { return null; } date.setHours(12 - date.getTimezoneOffset() / 60); date.setMinutes(0); date.setSeconds(0); date.setMilliseconds(0); return date; }; var getDateFromIsoString = function getDateFromIsoString(isoString) { return isoString ? setTimeToNoon(new Date(isoString)) : null; }; var getIsoStringFromDate = function getIsoStringFromDate(date) { return date ? setTimeToNoon(date).toISOString() : null; }; var _makeInputValueString = function _makeInputValueString(date, separator, dateFormat) { var month = date.getMonth() + 1; var day = date.getDate(); if (dateFormat.match(/MM.DD.YYYY/)) { return (month > 9 ? month : "0" + month) + separator + (day > 9 ? day : "0" + day) + separator + date.getFullYear(); } else if (dateFormat.match(/DD.MM.YYYY/)) { return (day > 9 ? day : "0" + day) + separator + (month > 9 ? month : "0" + month) + separator + date.getFullYear(); } else { return date.getFullYear() + separator + (month > 9 ? month : "0" + month) + separator + (day > 9 ? day : "0" + day); } }; var useInputValues = function useInputValues(controlInputRef, value, defaultValue, minDate, maxDate, dateFormat, onClear, onChange) { var _useState = React.useState(dateFormat.match(/[^A-Z]/)[0]), separator = _useState[0], setSeparator = _useState[1]; var _useState2 = React.useState(null), innerValue = _useState2[0], setInnerValue = _useState2[1]; var _useState3 = React.useState(null), inputValue = _useState3[0], setInputValue = _useState3[1]; var _useState4 = React.useState(null), displayDate = _useState4[0], setDisplayDate = _useState4[1]; var _useState5 = React.useState(null), selectedDate = _useState5[0], setSelectedDate = _useState5[1]; // handle props changes React.useEffect(function () { setSeparator(dateFormat.match(/[^A-Z]/)[0]); }, [dateFormat]); // handle input values React.useEffect(function () { var isoString = value || defaultValue; var minDate = getDateFromIsoString(minDate); var maxDate = getDateFromIsoString(maxDate); var nSelectedDate = getDateFromIsoString(isoString); var nInnerValue = getIsoStringFromDate(nSelectedDate); var nInputValue = isoString ? _makeInputValueString(nSelectedDate, separator, dateFormat) : null; var nDisplayDate; if (nSelectedDate) { //nDisplayDate = new Date(nSelectedDate) nDisplayDate = nSelectedDate; } else { var today = getDateFromIsoString(new Date().toISOString()); if (minDate && Date.parse(minDate) >= Date.parse(today)) { nDisplayDate = minDate; } else if (maxDate && Date.parse(maxDate) <= Date.parse(today)) { nDisplayDate = maxDate; } else { nDisplayDate = today; } } setInnerValue(nInnerValue); setInputValue(nInputValue); setSelectedDate(nSelectedDate); setDisplayDate(nDisplayDate); }, [value, defaultValue, minDate, maxDate, separator, dateFormat]); // var handleClear = /*useCallback(*/function handleClear() { if (onClear) { onClear(); } else { setInnerValue(null); setInputValue(null); setSelectedDate(null); setDisplayDate(null); if (onChange) { onChange(null, null); } } }; /*, [onClear, onChange])*/ var handleBadInput = /*useCallback(*/function handleBadInput(originalValue, tail) { if (tail === void 0) { tail = false; } var parts = originalValue.replace(new RegExp("[^0-9" + separator + "]"), '').split(separator); if (dateFormat.match(/MM.DD.YYYY/) || dateFormat.match(/DD.MM.YYYY/)) { if (parts[0] && parts[0].length > 2) { parts[1] = parts[0].slice(2) + (parts[1] || ''); parts[0] = parts[0].slice(0, 2); } if (parts[1] && parts[1].length > 2) { parts[2] = parts[1].slice(2) + (parts[2] || ''); parts[1] = parts[1].slice(0, 2); } if (parts[2]) { parts[2] = parts[2].slice(0, 4); if (tail) { if (parts[2].length < 4) { parts[2] = parts[2].padEnd(4, '0'); } } } } else { if (parts[0] && parts[0].length > 4) { parts[1] = parts[0].slice(4) + (parts[1] || ''); parts[0] = parts[0].slice(0, 4); } if (parts[1] && parts[1].length > 2) { parts[2] = parts[1].slice(2) + (parts[2] || ''); parts[1] = parts[1].slice(0, 2); } if (parts[2]) { parts[2] = parts[2].slice(0, 2); } } var nInputValue = parts.join(separator); setInputValue(nInputValue); }; /*, [dateFormat, separator])*/ var handleBadInputOnBlur = function handleBadInputOnBlur() { var _controlInputRef$curr; var originalValue = (controlInputRef == null || (_controlInputRef$curr = controlInputRef.current) == null ? void 0 : _controlInputRef$curr.value) || ''; if (originalValue) { handleBadInput(originalValue, true); } }; var handleInputChange = /*useCallback(*/function handleInputChange() { var _controlInputRef$curr2; var originalValue = (controlInputRef == null || (_controlInputRef$curr2 = controlInputRef.current) == null ? void 0 : _controlInputRef$curr2.value) || ''; var nInputValue = originalValue.replace(/(-|\/\/)/g, separator).slice(0, 10); if (!nInputValue) { handleClear(); return; } var month, day, year; if (dateFormat.match(/MM.DD.YYYY/)) { if (!nInputValue.match(/[0-1][0-9].[0-3][0-9].[1-2][0-9][0-9][0-9]/)) { return handleBadInput(originalValue); } month = nInputValue.slice(0, 2).replace(/[^0-9]/g, ''); day = nInputValue.slice(3, 5).replace(/[^0-9]/g, ''); year = nInputValue.slice(6, 10).replace(/[^0-9]/g, ''); } else if (dateFormat.match(/DD.MM.YYYY/)) { if (!nInputValue.match(/[0-3][0-9].[0-1][0-9].[1-2][0-9][0-9][0-9]/)) { return handleBadInput(originalValue); } day = nInputValue.slice(0, 2).replace(/[^0-9]/g, ''); month = nInputValue.slice(3, 5).replace(/[^0-9]/g, ''); year = nInputValue.slice(6, 10).replace(/[^0-9]/g, ''); } else { if (!nInputValue.match(/[1-2][0-9][0-9][0-9].[0-1][0-9].[0-3][0-9]/)) { return handleBadInput(originalValue); } year = nInputValue.slice(0, 4).replace(/[^0-9]/g, ''); month = nInputValue.slice(5, 7).replace(/[^0-9]/g, ''); day = nInputValue.slice(8, 10).replace(/[^0-9]/g, ''); } var monthInteger = parseInt(month, 10); var dayInteger = parseInt(day, 10); var yearInteger = parseInt(year, 10); if (monthInteger > 12 || dayInteger > 31) { return handleBadInput(originalValue); } var beforeMinDate = minDate && Date.parse(originalValue) < Date.parse(minDate); var afterMaxDate = maxDate && Date.parse(originalValue) > Date.parse(maxDate); if (beforeMinDate || afterMaxDate) { return handleBadInput(originalValue); } if (!isNaN(monthInteger) && !isNaN(dayInteger) && !isNaN(yearInteger) && monthInteger <= 12 && dayInteger <= 31 && yearInteger > 999) { var nSelectedDate = getDateFromIsoString(new Date(yearInteger, monthInteger - 1, dayInteger, 12, 0, 0, 0).toISOString()); var nInnerValue = getIsoStringFromDate(nSelectedDate); setSelectedDate(nSelectedDate); setDisplayDate(nSelectedDate); setInnerValue(nInnerValue); if (onChange) { onChange(nInnerValue, nInputValue); } } setInputValue(nInputValue); }; /*, [controlInputRef, separator, onChange, minDate, maxDate])*/ var handleChangeMonth = function handleChangeMonth(nDisplayDate) { setDisplayDate(nDisplayDate); }; var handleChangeDate = /*useCallback(*/function handleChangeDate(nSelectedDate) { var nInnerValue = getIsoStringFromDate(nSelectedDate); var nInputValue = _makeInputValueString(nSelectedDate, separator, dateFormat); setInputValue(nInputValue); setSelectedDate(nSelectedDate); setDisplayDate(nSelectedDate); setInnerValue(nInnerValue); if (onChange) { onChange(nInnerValue, nInputValue); } }; /*, [separator, dateFormat, onChange])*/ return [innerValue, inputValue, displayDate, selectedDate, handleClear, handleInputChange, handleChangeMonth, handleChangeDate, handleBadInputOnBlur]; }; var getInstanceCount = function getInstanceCount() { if (typeof window === 'object') { if (window._reactstrapDatePickerInstance == undefined) { window._reactstrapDatePickerInstance = 0; } var next = window._reactstrapDatePickerInstance + 1; window._reactstrapDatePickerInstance = next; return next; } else if (typeof process === 'object') { if (process._reactstrapDatePickerInstance == undefined) { process._reactstrapDatePickerInstance = 0; } var _next = process._reactstrapDatePickerInstance + 1; process._reactstrapDatePickerInstance = _next; return _next; } else { console.error("Reactstrap Date Picker cannot determine environment (it is neither browser's <window> nor Node's <process>)."); return 1; } }; var _getIdSuffix = function _getIdSuffix(id, name) { // Try <id> or <name> props to determine elements' id suffix if (id != undefined && id != '') return id; if (name != undefined && name != '') return name; // If none was passed, use global vars var iCount = getInstanceCount(); return iCount.toString(); }; var _getInputIds = function _getInputIds(id, name, customControl) { var _customControl$props; var idSuffix = _getIdSuffix(id, name); var group = "rdp-input-group-" + idSuffix; var hidden = id != undefined ? id : "rdp-hidden-" + idSuffix; var control = "rdp-form-control-" + idSuffix; if (customControl != undefined && customControl != null && (_customControl$props = customControl.props) != null && _customControl$props.id) { control = customControl.props.id; } var overlay = "rdp-overlay-" + idSuffix; return [group, hidden, control, overlay]; }; var useInputIds = function useInputIds(id, name, customControl) { var _useState = React.useState(_getInputIds(id, name, customControl)), inputIds = _useState[0], setInputIds = _useState[1]; React.useEffect(function () { setInputIds(_getInputIds(id, name, customControl)); }, [id, name, customControl]); return inputIds; }; var _getFixedDayLabels = function _getFixedDayLabels(dayLabels, weekStartsOn) { if (weekStartsOn > 1) { return dayLabels.slice(weekStartsOn).concat(dayLabels.slice(0, weekStartsOn)); } if (weekStartsOn === 1) { return dayLabels.slice(1).concat(dayLabels.slice(0, 1)); } return dayLabels; }; var useFixedDayLabels = function useFixedDayLabels(dayLabels, weekStartsOn) { var _useState = React.useState(_getFixedDayLabels(dayLabels, weekStartsOn)), fixedDayLabels = _useState[0], setFixedDayLabels = _useState[1]; React.useEffect(function () { setFixedDayLabels(_getFixedDayLabels(dayLabels, weekStartsOn)); }, [dayLabels, weekStartsOn]); return fixedDayLabels; }; var compareMonths = function compareMonths(a, b) { try { var da = new Date(a); var db = new Date(b); var sameYear = da.getFullYear() == db.getFullYear(); var sameMonth = da.getMonth() == db.getMonth(); return sameMonth && sameYear; } catch (e) { console.error(e); return true; } }; var _getYearList = function _getYearList(minDate, maxDate) { var minYear = minDate ? new Date(minDate).getFullYear() : 1970; var maxYear = maxDate ? new Date(maxDate).getFullYear() : 2045; var yList = []; for (var y = minYear; y <= maxYear; y++) { yList.push(y); } return yList; }; var PickMonthDefault = function PickMonthDefault(_ref) { var displayDate = _ref.displayDate, minDate = _ref.minDate, maxDate = _ref.maxDate, monthLabels = _ref.monthLabels, onChangeMonth = _ref.onChangeMonth, onChangeYear = _ref.onChangeYear; var _useState = React.useState(new Date(displayDate).getMonth()), month = _useState[0], setMonth = _useState[1]; var _useState2 = React.useState(new Date(displayDate).getFullYear()), year = _useState2[0], setYear = _useState2[1]; var _useState3 = React.useState(_getYearList(minDate, maxDate)), yearList = _useState3[0], setYearList = _useState3[1]; React.useEffect(function () { setMonth(new Date(displayDate).getMonth()); setYear(new Date(displayDate).getFullYear()); }, [displayDate]); React.useEffect(function () { setYearList(_getYearList(minDate, maxDate)); }, [minDate, maxDate]); var handleChangeMonth = function handleChangeMonth(ev) { var m = ev.target.value; setMonth(m); onChangeMonth(m); }; var handleChangeYear = function handleChangeYear(ev) { var y = ev.target.value; setYear(y); onChangeYear(y); }; return /*#__PURE__*/React.createElement("div", { className: "rdp-header-pick-month-default", style: { display: 'flex', flexFlow: 'row', flexWrap: 'nowrap' } }, /*#__PURE__*/React.createElement("div", { className: "rdp-header-pick-month-default-month", style: { flex: '2 1 auto' } }, /*#__PURE__*/React.createElement(reactstrap.Input, { type: "select", name: "rdp-header-pick-month-default-month", style: { lineHeight: "1.5", fontSize: "0.875rem", padding: "0.2rem" }, value: month, onChange: handleChangeMonth }, monthLabels.map(function (lmonth, lidx) { return /*#__PURE__*/React.createElement("option", { key: "month_" + lidx, value: lidx }, lmonth); }))), /*#__PURE__*/React.createElement("div", { className: "rdp-header-pick-month-default-year", style: { flex: '1 1 67px' } }, /*#__PURE__*/React.createElement(reactstrap.Input, { type: "select", name: "rdp-header-pick-month-default-year", style: { lineHeight: "1.5", fontSize: "0.875rem", padding: "0.2rem" }, value: year, onChange: handleChangeYear }, yearList.map(function (lyear) { return /*#__PURE__*/React.createElement("option", { key: "year" + lyear, value: lyear }, lyear); })))); }; function CalendarHeader(_ref) { var previousButtonElement = _ref.previousButtonElement, nextButtonElement = _ref.nextButtonElement, pickMonthElement = _ref.pickMonthElement, displayDate = _ref.displayDate, minDate = _ref.minDate, maxDate = _ref.maxDate, onChange = _ref.onChange, monthLabels = _ref.monthLabels; var _useState = React.useState(false), displayingMinMonth = _useState[0], setDisplayingMinMonth = _useState[1]; var _useState2 = React.useState(false), displayingMaxMonth = _useState2[0], setDisplayingMaxMonth = _useState2[1]; var _useState3 = React.useState(''), title = _useState3[0], setTitle = _useState3[1]; var PickMonthElement = pickMonthElement; React.useEffect(function () { if (displayDate == undefined) { return; } if (!minDate) { setDisplayingMinMonth(false); } else { setDisplayingMinMonth(compareMonths(displayDate, minDate)); } if (!maxDate) { setDisplayingMaxMonth(false); } else { setDisplayingMaxMonth(compareMonths(displayDate, maxDate)); } try { if (monthLabels) { setTitle(monthLabels[displayDate.getMonth()] + " " + displayDate.getFullYear()); } } catch (e) { console.error(e); } }, [displayDate, minDate, maxDate, monthLabels]); var handleChangeMonthIncr = function handleChangeMonthIncr(inc) { var newDisplayDate = new Date(displayDate); newDisplayDate.setMonth(newDisplayDate.getMonth() + inc, 1); onChange(newDisplayDate); }; var handleChangeMonth = function handleChangeMonth(m) { var newDisplayDate = new Date(displayDate); newDisplayDate.setMonth(m); onChange(newDisplayDate); }; var handleChangeYear = function handleChangeYear(y) { var newDisplayDate = new Date(displayDate); newDisplayDate.setFullYear(y); onChange(newDisplayDate); }; return /*#__PURE__*/React.createElement("div", { className: "rdp-header text-center", style: { display: 'flex', flexFlow: 'row', flexWrap: 'nowrap' } }, /*#__PURE__*/React.createElement("div", { className: "text-muted rdp-header-previous-wrapper", onClick: function onClick() { return handleChangeMonthIncr(-1); }, style: { cursor: 'pointer', userSelect: 'none', flexBasis: '1.25em', alignSelf: 'center' } }, displayingMinMonth ? null : previousButtonElement), /*#__PURE__*/React.createElement("div", { className: "rdp-header-pick-month-wrapper", style: { flex: '1 1 auto' } }, PickMonthElement == null || PickMonthElement === 'none' ? /*#__PURE__*/React.createElement("div", null, title) : PickMonthElement === 'default' ? /*#__PURE__*/React.createElement(PickMonthDefault, { displayDate: displayDate, monthLabels: monthLabels, minDate: minDate, maxDate: maxDate, onChangeMonth: function onChangeMonth(m) { return handleChangeMonth(m); }, onChangeYear: function onChangeYear(y) { return handleChangeYear(y); } }) : /*#__PURE__*/React.createElement(PickMonthElement, { displayDate: displayDate, minDate: minDate, maxDate: maxDate, onChangeMonth: function onChangeMonth(m) { return handleChangeMonth(m); }, onChangeYear: function onChangeYear(y) { return handleChangeYear(y); } })), /*#__PURE__*/React.createElement("div", { className: "text-muted rdp-header-next-wrapper", onClick: function onClick() { return handleChangeMonthIncr(1); }, style: { cursor: 'pointer', userSelect: 'none', flexBasis: '1.25em', alignSelf: 'center' } }, displayingMaxMonth ? null : nextButtonElement)); } var CalendarSubHeader = function CalendarSubHeader(_ref) { var dayLabels = _ref.dayLabels, showWeeks = _ref.showWeeks, cellPadding = _ref.cellPadding; return /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, showWeeks ? /*#__PURE__*/React.createElement("td", { className: "text-muted current-week", style: { padding: cellPadding } }) : null, dayLabels.map(function (label, index) { return /*#__PURE__*/React.createElement("td", { key: index, className: "text-muted", style: { padding: cellPadding } }, /*#__PURE__*/React.createElement("small", null, label)); }))); }; var CalendarDayOutOfMonth = function CalendarDayOutOfMonth() { return /*#__PURE__*/React.createElement("td", null); }; var CAL_DAY_CLASSNAME_BY_MODE = { 'normal': '', 'muted': 'text-muted', 'selected': 'bg-primary', 'current': 'text-primary' }; var CalendarDayInMonth = function CalendarDayInMonth(_ref) { var day = _ref.day, mode = _ref.mode, onDayClick = _ref.onDayClick, cellPadding = _ref.cellPadding, roundedCorners = _ref.roundedCorners; var handleClick = function handleClick(ev) { if (mode != 'muted') { onDayClick(ev); } }; return /*#__PURE__*/React.createElement("td", { "data-day": day, onClick: handleClick, style: { cursor: mode == 'muted' ? 'default' : 'pointer', padding: cellPadding, borderRadius: roundedCorners ? '5px' : '0px' }, className: CAL_DAY_CLASSNAME_BY_MODE[mode] }, day); }; var CalendarWeekNum = function CalendarWeekNum(_ref) { var weekNum = _ref.weekNum, cellPadding = _ref.cellPadding; return /*#__PURE__*/React.createElement("td", { style: { padding: cellPadding, fontSize: '0.8em', color: 'darkgrey' }, className: "text-muted" }, weekNum); }; var CalendarBody = function CalendarBody(_ref) { var calendarDays = _ref.calendarDays, showWeeks = _ref.showWeeks, onDayClick = _ref.onDayClick, cellPadding = _ref.cellPadding, roundedCorners = _ref.roundedCorners; if (!calendarDays) { return /*#__PURE__*/React.createElement("tbody", null); } return /*#__PURE__*/React.createElement("tbody", null, calendarDays.map(function (week, weekIndex) { return /*#__PURE__*/React.createElement("tr", { key: "rdp_calendar_week_" + weekIndex }, showWeeks ? /*#__PURE__*/React.createElement(CalendarWeekNum, { key: "rdp_calendar_week_" + weekIndex + "_weeknum", weekNum: week.weekNum, cellPadding: cellPadding }) : null, week.weekDays.map(function (weekDay, weekDayIndex) { return weekDay.inMonth ? /*#__PURE__*/React.createElement(CalendarDayInMonth, { key: "rdp_calendar_week_" + weekIndex + "_day_" + weekDayIndex, day: weekDay.day, mode: weekDay.mode, onDayClick: onDayClick, cellPadding: cellPadding, roundedCorners: roundedCorners }) : /*#__PURE__*/React.createElement(CalendarDayOutOfMonth, { key: "rdp_calendar_week_" + weekIndex + "_day_" + weekDayIndex }); })); })); }; var CalendarFooter = function CalendarFooter(_ref) { var dayLabels = _ref.dayLabels, showWeeks = _ref.showWeeks, handleTodayClick = _ref.handleTodayClick, showTodayButton = _ref.showTodayButton, todayButtonLabel = _ref.todayButtonLabel; if (!showTodayButton) { return null; } return /*#__PURE__*/React.createElement("tfoot", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", { colSpan: dayLabels.length + (showWeeks ? 1 : 0), style: { paddingTop: '9px' } }, /*#__PURE__*/React.createElement(reactstrap.Button, { block: true, size: "sm", className: "u-today-button", onClick: function onClick() { return handleTodayClick(); } }, todayButtonLabel)))); }; var DAYS_BY_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; /** groupByWeeks: { year, month, weeks: [ {weekNum: N, wekDays: [ {inMonth: true, day: N, mode: ''} or {inMonth: false} ] },... ] } */ function _groupByWeeks(year, month, weekStartsOn) { if (year == undefined || month == undefined) { return undefined; } var firstDay = new Date(year, month, 1); var startingDay = weekStartsOn > 1 ? firstDay.getDay() - weekStartsOn + 7 : weekStartsOn === 1 ? firstDay.getDay() === 0 ? 6 : firstDay.getDay() - 1 : firstDay.getDay(); var monthLength = DAYS_BY_MONTH[month]; if (month == 1) { if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { monthLength = 29; } } var isInMonth = function isInMonth(monthDay, weekIndex, weekDay) { if (monthDay <= monthLength && (weekIndex > 0 || weekDay >= startingDay)) { return true; } return false; }; var getWeekNumber = function getWeekNumber(monthDay) { var date = new Date(year, month, monthDay - 1, 12, 0, 0, 0); var target = new Date(date.valueOf()); var dayNr = (date.getDay() + 6) % 7; target.setDate(target.getDate() - dayNr + 3); var firstThursday = target.valueOf(); target.setMonth(0, 1); if (target.getDay() !== 4) { target.setMonth(0, 1 + (4 - target.getDay() + 7) % 7); } return 1 + Math.ceil((firstThursday - target) / 604800000); }; var allWeeks = []; var monthDay = 1; for (var weekIndex = 0; weekIndex < 9; weekIndex++) { var weekDays = []; for (var weekDay = 0; weekDay <= 6; weekDay++) { if (isInMonth(monthDay, weekIndex, weekDay)) { weekDays.push({ inMonth: true, day: monthDay }); monthDay += 1; } else { weekDays.push({ inMonth: false }); } } var weekNum = getWeekNumber(monthDay); allWeeks.push({ weekDays: weekDays, weekNum: weekNum }); if (monthDay > monthLength) { break; } } return { year: year, month: month, weeks: allWeeks }; } /** calendarDays: [ {weekNum: N, wekDays: [ {inMonth: true, day: N, mode: ''} or {inMonth: false} ] },... ] */ function _makeCalendarDays(groupByWeeks, selectedDate, minDate, maxDate) { if (groupByWeeks == undefined) { return []; } var getDayMode = function getDayMode(day) { var date = setTimeToNoon(new Date(groupByWeeks.year, groupByWeeks.month, day, 12, 0, 0, 0)).toISOString(); var beforeMinDate = minDate != undefined ? Date.parse(date) < Date.parse(setTimeToNoon(new Date(minDate))) : false; var afterMaxDate = maxDate != undefined ? Date.parse(date) > Date.parse(setTimeToNoon(new Date(maxDate))) : false; var currentDate = setTimeToNoon(new Date()); var nSelectedDate = setTimeToNoon(new Date(selectedDate)); if (beforeMinDate || afterMaxDate) { return 'muted'; } else if (Date.parse(date) === Date.parse(nSelectedDate)) { return 'selected'; } else if (Date.parse(date) === Date.parse(currentDate)) { return 'current'; } else { return 'normal'; } }; var calendarDays = []; groupByWeeks.weeks.map(function (week) { var weekNum = week.weekNum; var weekDays = week.weekDays.map(function (weekDay) { return _extends({}, weekDay, { mode: weekDay.inMonth ? getDayMode(weekDay.day) : undefined }); }); calendarDays.push({ weekNum: weekNum, weekDays: weekDays }); }); return calendarDays; } function useCalendarDays(displayDate, selectedDate, minDate, maxDate, weekStartsOn) { var _useState = React.useState(undefined), year = _useState[0], setYear = _useState[1]; var _useState2 = React.useState(undefined), month = _useState2[0], setMonth = _useState2[1]; var _useState3 = React.useState(undefined), groupByWeeks = _useState3[0], setGroupByWeeks = _useState3[1]; var _useState4 = React.useState([]), calendarDays = _useState4[0], setCalendarDays = _useState4[1]; React.useEffect(function () { if (displayDate) { setYear(displayDate.getFullYear()); setMonth(displayDate.getMonth()); } }, [displayDate]); React.useEffect(function () { setGroupByWeeks(_groupByWeeks(year, month, weekStartsOn)); }, [year, month, weekStartsOn]); React.useEffect(function () { setCalendarDays(_makeCalendarDays(groupByWeeks, selectedDate, minDate, maxDate)); }, [groupByWeeks, selectedDate, minDate, maxDate]); return calendarDays; } var Calendar = function Calendar(_ref) { var popoverRef = _ref.popoverRef, selectedDate = _ref.selectedDate, displayDate = _ref.displayDate, minDate = _ref.minDate, maxDate = _ref.maxDate, onChange = _ref.onChange, dayLabels = _ref.dayLabels, cellPadding = _ref.cellPadding, weekStartsOn = _ref.weekStartsOn, showTodayButton = _ref.showTodayButton, todayButtonLabel = _ref.todayButtonLabel, roundedCorners = _ref.roundedCorners, showWeeks = _ref.showWeeks, monthLabels = _ref.monthLabels, previousButtonElement = _ref.previousButtonElement, nextButtonElement = _ref.nextButtonElement, pickMonthElement = _ref.pickMonthElement, placement = _ref.placement, open = _ref.open, container = _ref.container, target = _ref.target, onChangeMonth = _ref.onChangeMonth; var calendarDays = useCalendarDays(displayDate, selectedDate, minDate, maxDate, weekStartsOn); var handleDayClick = function handleDayClick(e) { var day = e.currentTarget.getAttribute('data-day'); var newSelectedDate = setTimeToNoon(new Date(displayDate)); newSelectedDate.setDate(day); onChange(newSelectedDate); }; var handleTodayClick = function handleTodayClick() { var newSelectedDate = setTimeToNoon(new Date()); onChange(newSelectedDate); }; return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(reactstrap.Popover, { innerRef: popoverRef, className: "rdp-popover " + placement //toggle = {() => handleHide()} , isOpen: open, container: container, target: target, placement: placement // delay = {200} // does not apply for us (manual triggering) }, /*#__PURE__*/React.createElement(reactstrap.PopoverHeader, { tag: "div" }, /*#__PURE__*/React.createElement(CalendarHeader, { previousButtonElement: previousButtonElement, nextButtonElement: nextButtonElement, pickMonthElement: pickMonthElement, displayDate: displayDate, minDate: minDate, maxDate: maxDate, onChange: function onChange(newDisplayDate) { return onChangeMonth(newDisplayDate); }, monthLabels: monthLabels })), /*#__PURE__*/React.createElement(reactstrap.PopoverBody, null, /*#__PURE__*/React.createElement("table", { className: "rdp-calendar text-center" }, /*#__PURE__*/React.createElement(CalendarSubHeader, { dayLabels: dayLabels, showWeeks: showWeeks, cellPadding: cellPadding }), /*#__PURE__*/React.createElement(CalendarBody, { calendarDays: calendarDays, showWeeks: showWeeks, onDayClick: handleDayClick, cellPadding: cellPadding, roundedCorners: roundedCorners }), /*#__PURE__*/React.createElement(CalendarFooter, { dayLabels: dayLabels, showWeeks: showWeeks, handleTodayClick: handleTodayClick, showTodayButton: showTodayButton, todayButtonLabel: todayButtonLabel }))))); }; // NOTE: do we want to use the controlInput or the hiddenInput here? // We were previously using the hidden one, but I see no reasons. // 'change' events would make sense on the hidden input, but focus // control seems to be more on the control input. // Anyway, this is not decided here, but when calling useCustomEvents() var useCustomEvents = function useCustomEvents(inputRef, onBlur, onFocus) { var customOnBlur = React.useCallback(function () { if (onBlur) { var event = document.createEvent('CustomEvent'); event.initEvent('Change Date', true, false); inputRef.current.dispatchEvent(event); onBlur(event); } }, [inputRef, onBlur]); var customOnFocus = React.useCallback(function () { if (onFocus) { var event = document.createEvent('CustomEvent'); event.initEvent('Change Date', true, false); inputRef.current.dispatchEvent(event); onFocus(event); } }, [inputRef, onFocus]); return [customOnBlur, customOnFocus]; }; var getMaybeFuncValue = function getMaybeFuncValue(value) { var tag = Object.prototype.toString.call(value); var isFunction = tag === '[object AsyncFunction]' || tag === '[object Function]' || tag === '[object GeneratorFunction]' || tag === '[object Proxy]'; if (isFunction) { return value(); } else { return value; } }; // About autoFocus // We could handle by our own through ref callbacks // (https://blog.maisie.ink/react-ref-autofocus/) // But let's just use react's autoFocus attribute by now var useCalendarProps = function useCalendarProps(calendarPlacement, inputRef, autoFocus, onBlur, onFocus) { var _useState = React.useState(false), open = _useState[0], setOpen = _useState[1]; var _useState2 = React.useState(getMaybeFuncValue(calendarPlacement)), placement = _useState2[0], setPlacement = _useState2[1]; var hiddenInputRef = React.useRef(); var overlayContainerRef = React.useRef(); var popoverRef = React.useRef(); var controlInputRef = typeof inputRef == 'object' ? inputRef : React.useRef(inputRef); // eslint-disable-line react-hooks/rules-of-hooks // NOTE: do we want to use the controlInput or the hiddenInput here? var _useCustomEvents = useCustomEvents(/*hiddenInputRef*/controlInputRef, onBlur, onFocus), customOnBlur = _useCustomEvents[0], customOnFocus = _useCustomEvents[1]; var isOutside = React.useCallback(function (event) { var outOfCalendar = (popoverRef == null ? void 0 : popoverRef.current) == undefined || !(popoverRef != null && popoverRef.current.contains(event.target)); var outOfControlInput = (controlInputRef == null ? void 0 : controlInputRef.current) == undefined || !controlInputRef.current.contains(event.target); var isOut = outOfCalendar && outOfControlInput; return isOut; }, [popoverRef, controlInputRef]); // Control the click outside React.useEffect(function () { function handleClickOutside(event) { event.stopPropagation(); if (open) { if (isOutside(event)) { setOpen(false); customOnBlur(); } } } document.addEventListener("mousedown", handleClickOutside); return function () { document.removeEventListener("mousedown", handleClickOutside); }; }, [open, isOutside, customOnBlur]); // // This callback is bound to Calendar.Popover's toggle() method, // but seems it's unneccesary // Leaving, by now, this testimonial comments // // const handleHide = () => { // let inputFocused = false // try { // inputFocused= controlInputRef.current==document.activeElement // } catch(e) {} // // if (inputFocused) { // return // } // setOpen(false) // customOnBlur() // } var handleFocus = React.useCallback(function () { var nPlacement = getMaybeFuncValue(calendarPlacement); setPlacement(nPlacement); setOpen(true); customOnFocus(); }, [calendarPlacement, customOnFocus]); var handleBlur = React.useCallback(function (event) { if (isOutside(event)) { setOpen(false); customOnBlur(); } }, [isOutside, customOnBlur]); return [hiddenInputRef, overlayContainerRef, popoverRef, controlInputRef, open, placement, handleFocus, handleBlur]; }; var _defaultDateFormat = function _defaultDateFormat() { var language = typeof window !== 'undefined' && window.navigator ? (window.navigator.userLanguage || window.navigator.language || '').toLowerCase() : ''; var dateFormat = !language || language === 'en-us' ? 'MM/DD/YYYY' : 'DD/MM/YYYY'; return dateFormat; }; var DEFAULT_DAY_LABELS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; var DEFAULT_MONTH_LABELS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; var DatePickerBase = function DatePickerBase(props, ref) { var value = props.value, defaultValue = props.defaultValue, id = props.id, name = props.name, _props$dateFormat = props.dateFormat, dateFormat = _props$dateFormat === void 0 ? _defaultDateFormat() : _props$dateFormat, minDate = props.minDate, maxDate = props.maxDate, _props$clearButtonEle = props.clearButtonElement, clearButtonElement = _props$clearButtonEle === void 0 ? '×' : _props$clearButtonEle, _props$showClearButto = props.showClearButton, showClearButton = _props$showClearButto === void 0 ? true : _props$showClearButto, onInvalid = props.onInvalid, onChange = props.onChange, onClear = props.onClear, onBlur = props.onBlur, onFocus = props.onFocus, size = props.size, valid = props.valid, invalid = props.invalid, customInputGroup = props.customInputGroup, _props$autoComplete = props.autoComplete, autoComplete = _props$autoComplete === void 0 ? 'on' : _props$autoComplete, _props$autoFocus = props.autoFocus, autoFocus = _props$autoFocus === void 0 ? false : _props$autoFocus, _props$disabled = props.disabled, disabled = _props$disabled === void 0 ? false : _props$disabled, _props$noValidate = props.noValidate, noValidate = _props$noValidate === void 0 ? false : _props$noValidate, placeholder = props.placeholder, required = props.required, className = props.className, _props$style = props.style, style = _props$style === void 0 ? undefined : _props$style, inputRef = props.inputRef, customControl = props.customControl, children = props.children, calendarContainer = props.calendarContainer, _props$dayLabels = props.dayLabels, dayLabels = _props$dayLabels === void 0 ? DEFAULT_DAY_LABELS : _props$dayLabels, _props$monthLabels = props.monthLabels, monthLabels = _props$monthLabels === void 0 ? DEFAULT_MONTH_LABELS : _props$monthLabels, weekStartsOn = props.weekStartsOn, _props$showWeeks = props.showWeeks, showWeeks = _props$showWeeks === void 0 ? false : _props$showWeeks, _props$previousButton = props.previousButtonElement, previousButtonElement = _props$previousButton === void 0 ? '<' : _props$previousButton, _props$nextButtonElem = props.nextButtonElement, nextButtonElement = _props$nextButtonElem === void 0 ? '>' : _props$nextButtonElem, _props$pickMonthEleme = props.pickMonthElement, pickMonthElement = _props$pickMonthEleme === void 0 ? undefined : _props$pickMonthEleme, _props$showTodayButto = props.showTodayButton, showTodayButton = _props$showTodayButto === void 0 ? false : _props$showTodayButto, _props$todayButtonLab = props.todayButtonLabel, todayButtonLabel = _props$todayButtonLab === void 0 ? 'Today' : _props$todayButtonLab, _props$roundedCorners = props.roundedCorners, roundedCorners = _props$roundedCorners === void 0 ? false : _props$roundedCorners, _props$cellPadding = props.cellPadding, cellPadding = _props$cellPadding === void 0 ? '5px' : _props$cellPadding, _props$calendarPlacem = props.calendarPlacement, calendarPlacement = _props$calendarPlacem === void 0 ? 'bottom' : _props$calendarPlacem; var propError = useCheckProps(value, defaultValue); if (propError != undefined) { throw new Error(propError); } var _useCalendarProps = useCalendarProps(calendarPlacement, inputRef, autoFocus, onBlur, onFocus), hiddenInputRef = _useCalendarProps[0], overlayContainerRef = _useCalendarProps[1], popoverRef = _useCalendarProps[2], controlInputRef = _useCalendarProps[3], open = _useCalendarProps[4], placement = _useCalendarProps[5], handleFocus = _useCalendarProps[6], handleBlur = _useCalendarProps[7]; var _useInputValues = useInputValues(controlInputRef, value, defaultValue, minDate, maxDate, dateFormat, onClear, onChange), innerValue = _useInputValues[0], inputValue = _useInputValues[1], displayDate = _useInputValues[2], selectedDate = _useInputValues[3], handleClear = _useInputValues[4], handleInputChange = _useInputValues[5], handleChangeMonth = _useInputValues[6], handleChangeDate = _useInputValues[7], handleBadInputOnBlur = _useInputValues[8]; var _useInputIds = useInputIds(id, name, customControl), groupInputId = _useInputIds[0], hiddenInputId = _useInputIds[1], controlInputId = _useInputIds[2], overlayId = _useInputIds[3]; React.useImperativeHandle(ref, function () { return { getValue: function getValue() { return selectedDate ? selectedDate.toISOString() : null; }, getFormattedValue: function getFormattedValue() { return displayDate ? inputValue : null; }, getNode: function getNode() { return controlInputRef == null ? void 0 : controlInputRef.current; } }; }); //, [controlInputRef, displayDate, inputValue, selectedDate])) var fixedDayLabels = useFixedDayLabels(dayLabels, weekStartsOn); var handleChangeDateAndBlur = function handleChangeDateAndBlur(nSelectedDate) { handleChangeDate(nSelectedDate); handleBlur(true); }; return /*#__PURE__*/React.createElement(InputGroup, { customInputGroup: customInputGroup, size: size, inputId: groupInputId }, /*#__PURE__*/React.createElement(InputControlInput, { controlId: controlInputId, customControl: customControl, value: inputValue || '', required: required, placeholder: placeholder || '', inputRef: controlInputRef, disabled: disabled, className: className, style: style, autoFocus: autoFocus, autoComplete: autoComplete, onInvalid: onInvalid, noValidate: noValidate, valid: valid, invalid: invalid, onFocus: function onFocus() { return handleFocus(); }, onBlur: function onBlur(event) { handleBadInputOnBlur(); handleBlur(event); }, onChange: function onChange() { return handleInputChange(); } }), /*#__PURE__*/React.createElement(InputOverlay, { overlayContainerRef: overlayContainerRef, oid: overlayId }, overlayContainerRef.current == undefined ? null : /*#__PURE__*/React.createElement(Calendar, { popoverRef: popoverRef, placement: placement, open: open, container: calendarContainer || overlayContainerRef, target: controlInputId, previousButtonElement: previousButtonElement, nextButtonElement: nextButtonElement, pickMonthElement: pickMonthElement, displayDate: displayDate, minDate: minDate, maxDate: maxDate, onChangeMonth: function onChangeMonth(newDisplayDate) { return handleChangeMonth(newDisplayDate); }, monthLabels: monthLabels, cellPadding: cellPadding, selectedDate: selectedDate, onChange: function onChange(newSelectedDate) { return handleChangeDateAndBlur(newSelectedDate); }, dayLabels: fixedDayLabels, weekStartsOn: weekStartsOn, showTodayButton: showTodayButton, todayButtonLabel: todayButtonLabel, roundedCorners: roundedCorners, showWeeks: showWeeks })), /*#__PURE__*/React.createElement(InputHidden, { inputId: hiddenInputId, name: name, value: innerValue || '', formattedValue: innerValue ? inputValue : '', hiddenInputRef: hiddenInputRef }), showClearButton && !customControl ? /*#__PURE__*/React.createElement(InputClearButton, { inputValue: inputValue, disabled: disabled, clearButtonElement: clearButtonElement, onClick: function onClick() { return handleClear(); } }) : null, children); }; var DatePicker = /*#__PURE__*/React.forwardRef(DatePickerBase); exports.DatePicker = DatePicker;