reactstrap-date-picker
Version:
Reactstrap based, zero dependencies, date picker
1,273 lines (1,224 loc) • 41 kB
JavaScript
/**
* 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
*/
import React, { useState, useEffect, useCallback, useRef, forwardRef, useImperativeHandle } from 'react';
import { InputGroup as InputGroup$1, InputGroupText, Input, Button, Popover, PopoverHeader, PopoverBody } from 'reactstrap';
var useCheckProps = (value, defaultValue) => {
if (value && defaultValue) {
return 'Conflicting DatePicker properties \'value\' and \'defaultValue\'';
}
return undefined;
};
var InputGroup = _ref => {
var {
children,
customInputGroup,
size,
inputId
} = _ref;
if (customInputGroup != undefined) {
return /*#__PURE__*/React.cloneElement(customInputGroup, {
children: children
});
}
return /*#__PURE__*/React.createElement(InputGroup$1, {
size: size,
id: inputId,
className: "rdp-input-group"
}, children);
};
var InputOverlay = _ref => {
var {
oid,
overlayContainerRef,
children
} = _ref;
return /*#__PURE__*/React.createElement("div", {
ref: overlayContainerRef,
id: oid,
className: "rdp-overlay"
}, children);
};
var InputHidden = _ref => {
var {
inputId,
name,
value,
formattedValue,
hiddenInputRef
} = _ref;
return /*#__PURE__*/React.createElement("input", {
ref: hiddenInputRef,
type: "hidden",
className: "rdp-hidden",
id: inputId,
name: name,
value: value || '',
"data-formattedvalue": formattedValue
});
};
var InputClearButton = _ref => {
var {
inputValue,
disabled,
clearButtonElement,
onClick: _onClick
} = _ref;
return /*#__PURE__*/React.createElement("div", {
className: "rdp-addon input-group-append"
}, /*#__PURE__*/React.createElement(InputGroupText, {
onClick: () => disabled ? null : _onClick(),
style: {
opacity: inputValue && !disabled ? 1 : 0.5,
cursor: inputValue && !disabled ? 'pointer' : 'not-allowed'
}
}, clearButtonElement));
};
function _defineProperty(e, r, t) {
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: true,
configurable: true,
writable: true
}) : e[r] = t, e;
}
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 _objectSpread2(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
_defineProperty(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;
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r);
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
var InputControlInput = _ref => {
var {
customControl,
controlId,
value,
required,
placeholder,
inputRef,
disabled,
className,
style,
autoFocus,
autoComplete,
valid,
invalid,
onInvalid,
noValidate,
onKeyDown,
onFocus,
onBlur,
onChange
} = _ref;
var validityClassNames = "".concat(invalid === true ? 'is-invalid' : '', " ").concat(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 ".concat(className || '', " ").concat(customControl.props.className || '', " ").concat(validityClassNames),
style: _objectSpread2(_objectSpread2({}, 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(Input, {
id: controlId,
name: controlId,
value: value || '',
required: required,
placeholder: placeholder,
innerRef: inputRef,
disabled: disabled,
type: "text",
className: "rdp-form-control ".concat(className || '', " ").concat(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 = date => {
if (!date) {
return null;
}
date.setHours(12 - date.getTimezoneOffset() / 60);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date;
};
var getDateFromIsoString = isoString => isoString ? setTimeToNoon(new Date(isoString)) : null;
var getIsoStringFromDate = date => date ? setTimeToNoon(date).toISOString() : null;
var _makeInputValueString = (date, separator, dateFormat) => {
var month = date.getMonth() + 1;
var day = date.getDate();
if (dateFormat.match(/MM.DD.YYYY/)) {
return (month > 9 ? month : "0".concat(month)) + separator + (day > 9 ? day : "0".concat(day)) + separator + date.getFullYear();
} else if (dateFormat.match(/DD.MM.YYYY/)) {
return (day > 9 ? day : "0".concat(day)) + separator + (month > 9 ? month : "0".concat(month)) + separator + date.getFullYear();
} else {
return date.getFullYear() + separator + (month > 9 ? month : "0".concat(month)) + separator + (day > 9 ? day : "0".concat(day));
}
};
var useInputValues = (controlInputRef, value, defaultValue, minDate, maxDate, dateFormat, onClear, onChange) => {
var [separator, setSeparator] = useState(dateFormat.match(/[^A-Z]/)[0]);
var [innerValue, setInnerValue] = useState(null);
var [inputValue, setInputValue] = useState(null);
var [displayDate, setDisplayDate] = useState(null);
var [selectedDate, setSelectedDate] = useState(null);
// handle props changes
useEffect(() => {
setSeparator(dateFormat.match(/[^A-Z]/)[0]);
}, [dateFormat]);
// handle input values
useEffect(() => {
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(*/() => {
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) {
var tail = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var parts = originalValue.replace(new RegExp("[^0-9".concat(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 = () => {
var _controlInputRef$curr;
var originalValue = (controlInputRef === null || controlInputRef === void 0 || (_controlInputRef$curr = controlInputRef.current) === null || _controlInputRef$curr === void 0 ? void 0 : _controlInputRef$curr.value) || '';
if (originalValue) {
handleBadInput(originalValue, true);
}
};
var handleInputChange = /*useCallback(*/() => {
var _controlInputRef$curr2;
var originalValue = (controlInputRef === null || controlInputRef === void 0 || (_controlInputRef$curr2 = controlInputRef.current) === null || _controlInputRef$curr2 === void 0 ? 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 = nDisplayDate => {
setDisplayDate(nDisplayDate);
};
var handleChangeDate = /*useCallback(*/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 = () => {
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 = (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 = (id, name, customControl) => {
var _customControl$props;
var idSuffix = _getIdSuffix(id, name);
var group = "rdp-input-group-".concat(idSuffix);
var hidden = id != undefined ? id : "rdp-hidden-".concat(idSuffix);
var control = "rdp-form-control-".concat(idSuffix);
if (customControl != undefined && customControl !== null && customControl !== void 0 && (_customControl$props = customControl.props) !== null && _customControl$props !== void 0 && _customControl$props.id) {
control = customControl.props.id;
}
var overlay = "rdp-overlay-".concat(idSuffix);
return [group, hidden, control, overlay];
};
var useInputIds = (id, name, customControl) => {
var [inputIds, setInputIds] = useState(_getInputIds(id, name, customControl));
useEffect(() => {
setInputIds(_getInputIds(id, name, customControl));
}, [id, name, customControl]);
return inputIds;
};
var _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 = (dayLabels, weekStartsOn) => {
var [fixedDayLabels, setFixedDayLabels] = useState(_getFixedDayLabels(dayLabels, weekStartsOn));
useEffect(() => {
setFixedDayLabels(_getFixedDayLabels(dayLabels, weekStartsOn));
}, [dayLabels, weekStartsOn]);
return fixedDayLabels;
};
var 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 = (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 = _ref => {
var {
displayDate,
minDate,
maxDate,
monthLabels,
onChangeMonth,
onChangeYear
} = _ref;
var [month, setMonth] = useState(new Date(displayDate).getMonth());
var [year, setYear] = useState(new Date(displayDate).getFullYear());
var [yearList, setYearList] = useState(_getYearList(minDate, maxDate));
useEffect(() => {
setMonth(new Date(displayDate).getMonth());
setYear(new Date(displayDate).getFullYear());
}, [displayDate]);
useEffect(() => {
setYearList(_getYearList(minDate, maxDate));
}, [minDate, maxDate]);
var handleChangeMonth = ev => {
var m = ev.target.value;
setMonth(m);
onChangeMonth(m);
};
var 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(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((lmonth, lidx) => {
return /*#__PURE__*/React.createElement("option", {
key: "month_".concat(lidx),
value: lidx
}, lmonth);
}))), /*#__PURE__*/React.createElement("div", {
className: "rdp-header-pick-month-default-year",
style: {
flex: '1 1 67px'
}
}, /*#__PURE__*/React.createElement(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(lyear => {
return /*#__PURE__*/React.createElement("option", {
key: "year".concat(lyear),
value: lyear
}, lyear);
}))));
};
function CalendarHeader(_ref) {
var {
previousButtonElement,
nextButtonElement,
pickMonthElement,
displayDate,
minDate,
maxDate,
onChange,
monthLabels
} = _ref;
var [displayingMinMonth, setDisplayingMinMonth] = useState(false);
var [displayingMaxMonth, setDisplayingMaxMonth] = useState(false);
var [title, setTitle] = useState('');
var PickMonthElement = pickMonthElement;
useEffect(() => {
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("".concat(monthLabels[displayDate.getMonth()], " ").concat(displayDate.getFullYear()));
}
} catch (e) {
console.error(e);
}
}, [displayDate, minDate, maxDate, monthLabels]);
var handleChangeMonthIncr = inc => {
var newDisplayDate = new Date(displayDate);
newDisplayDate.setMonth(newDisplayDate.getMonth() + inc, 1);
onChange(newDisplayDate);
};
var handleChangeMonth = m => {
var newDisplayDate = new Date(displayDate);
newDisplayDate.setMonth(m);
onChange(newDisplayDate);
};
var 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: () => 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: m => handleChangeMonth(m),
onChangeYear: y => handleChangeYear(y)
}) : /*#__PURE__*/React.createElement(PickMonthElement, {
displayDate: displayDate,
minDate: minDate,
maxDate: maxDate,
onChangeMonth: m => handleChangeMonth(m),
onChangeYear: y => handleChangeYear(y)
})), /*#__PURE__*/React.createElement("div", {
className: "text-muted rdp-header-next-wrapper",
onClick: () => handleChangeMonthIncr(1),
style: {
cursor: 'pointer',
userSelect: 'none',
flexBasis: '1.25em',
alignSelf: 'center'
}
}, displayingMaxMonth ? null : nextButtonElement));
}
var CalendarSubHeader = _ref => {
var {
dayLabels,
showWeeks,
cellPadding
} = _ref;
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((label, index) => /*#__PURE__*/React.createElement("td", {
key: index,
className: "text-muted",
style: {
padding: cellPadding
}
}, /*#__PURE__*/React.createElement("small", null, label)))));
};
var CalendarDayOutOfMonth = () => /*#__PURE__*/React.createElement("td", null);
var CAL_DAY_CLASSNAME_BY_MODE = {
'normal': '',
'muted': 'text-muted',
'selected': 'bg-primary',
'current': 'text-primary'
};
var CalendarDayInMonth = _ref => {
var {
day,
mode,
onDayClick,
cellPadding,
roundedCorners
} = _ref;
var 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 = _ref => {
var {
weekNum,
cellPadding
} = _ref;
return /*#__PURE__*/React.createElement("td", {
style: {
padding: cellPadding,
fontSize: '0.8em',
color: 'darkgrey'
},
className: "text-muted"
}, weekNum);
};
var CalendarBody = _ref => {
var {
calendarDays,
showWeeks,
onDayClick,
cellPadding,
roundedCorners
} = _ref;
if (!calendarDays) {
return /*#__PURE__*/React.createElement("tbody", null);
}
return /*#__PURE__*/React.createElement("tbody", null, calendarDays.map((week, weekIndex) => /*#__PURE__*/React.createElement("tr", {
key: "rdp_calendar_week_".concat(weekIndex)
}, showWeeks ? /*#__PURE__*/React.createElement(CalendarWeekNum, {
key: "rdp_calendar_week_".concat(weekIndex, "_weeknum"),
weekNum: week.weekNum,
cellPadding: cellPadding
}) : null, week.weekDays.map((weekDay, weekDayIndex) => weekDay.inMonth ? /*#__PURE__*/React.createElement(CalendarDayInMonth, {
key: "rdp_calendar_week_".concat(weekIndex, "_day_").concat(weekDayIndex),
day: weekDay.day,
mode: weekDay.mode,
onDayClick: onDayClick,
cellPadding: cellPadding,
roundedCorners: roundedCorners
}) : /*#__PURE__*/React.createElement(CalendarDayOutOfMonth, {
key: "rdp_calendar_week_".concat(weekIndex, "_day_").concat(weekDayIndex)
})))));
};
var CalendarFooter = _ref => {
var {
dayLabels,
showWeeks,
handleTodayClick,
showTodayButton,
todayButtonLabel
} = _ref;
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(Button, {
block: true,
size: "sm",
className: "u-today-button",
onClick: () => 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 = (monthDay, weekIndex, weekDay) => {
if (monthDay <= monthLength && (weekIndex > 0 || weekDay >= startingDay)) {
return true;
}
return false;
};
var 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,
weekNum
});
if (monthDay > monthLength) {
break;
}
}
return {
year,
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 = 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(week => {
var weekNum = week.weekNum;
var weekDays = week.weekDays.map(weekDay => {
return _objectSpread2(_objectSpread2({}, weekDay), {}, {
mode: weekDay.inMonth ? getDayMode(weekDay.day) : undefined
});
});
calendarDays.push({
weekNum,
weekDays
});
});
return calendarDays;
}
function useCalendarDays(displayDate, selectedDate, minDate, maxDate, weekStartsOn) {
var [year, setYear] = useState(undefined);
var [month, setMonth] = useState(undefined);
var [groupByWeeks, setGroupByWeeks] = useState(undefined);
var [calendarDays, setCalendarDays] = useState([]);
useEffect(() => {
if (displayDate) {
setYear(displayDate.getFullYear());
setMonth(displayDate.getMonth());
}
}, [displayDate]);
useEffect(() => {
setGroupByWeeks(_groupByWeeks(year, month, weekStartsOn));
}, [year, month, weekStartsOn]);
useEffect(() => {
setCalendarDays(_makeCalendarDays(groupByWeeks, selectedDate, minDate, maxDate));
}, [groupByWeeks, selectedDate, minDate, maxDate]);
return calendarDays;
}
var Calendar = _ref => {
var {
popoverRef,
selectedDate,
displayDate,
minDate,
maxDate,
onChange,
dayLabels,
cellPadding,
weekStartsOn,
showTodayButton,
todayButtonLabel,
roundedCorners,
showWeeks,
monthLabels,
previousButtonElement,
nextButtonElement,
pickMonthElement,
placement,
open,
container,
target,
onChangeMonth
} = _ref;
var calendarDays = useCalendarDays(displayDate, selectedDate, minDate, maxDate, weekStartsOn);
var handleDayClick = e => {
var day = e.currentTarget.getAttribute('data-day');
var newSelectedDate = setTimeToNoon(new Date(displayDate));
newSelectedDate.setDate(day);
onChange(newSelectedDate);
};
var handleTodayClick = () => {
var newSelectedDate = setTimeToNoon(new Date());
onChange(newSelectedDate);
};
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Popover, {
innerRef: popoverRef,
className: "rdp-popover ".concat(placement)
//toggle = {() => handleHide()}
,
isOpen: open,
container: container,
target: target,
placement: placement
// delay = {200} // does not apply for us (manual triggering)
}, /*#__PURE__*/React.createElement(PopoverHeader, {
tag: "div"
}, /*#__PURE__*/React.createElement(CalendarHeader, {
previousButtonElement: previousButtonElement,
nextButtonElement: nextButtonElement,
pickMonthElement: pickMonthElement,
displayDate: displayDate,
minDate: minDate,
maxDate: maxDate,
onChange: newDisplayDate => onChangeMonth(newDisplayDate),
monthLabels: monthLabels
})), /*#__PURE__*/React.createElement(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 = (inputRef, onBlur, onFocus) => {
var customOnBlur = useCallback(() => {
if (onBlur) {
var event = document.createEvent('CustomEvent');
event.initEvent('Change Date', true, false);
inputRef.current.dispatchEvent(event);
onBlur(event);
}
}, [inputRef, onBlur]);
var customOnFocus = useCallback(() => {
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 = 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 = (calendarPlacement, inputRef, autoFocus, onBlur, onFocus) => {
var [open, setOpen] = useState(false);
var [placement, setPlacement] = useState(getMaybeFuncValue(calendarPlacement));
var hiddenInputRef = useRef();
var overlayContainerRef = useRef();
var popoverRef = useRef();
var controlInputRef = typeof inputRef == 'object' ? inputRef : useRef(inputRef); // eslint-disable-line react-hooks/rules-of-hooks
// NOTE: do we want to use the controlInput or the hiddenInput here?
var [customOnBlur, customOnFocus] = useCustomEvents(/*hiddenInputRef*/controlInputRef, onBlur, onFocus);
var isOutside = useCallback(event => {
var outOfCalendar = (popoverRef === null || popoverRef === void 0 ? void 0 : popoverRef.current) == undefined || !(popoverRef !== null && popoverRef !== void 0 && popoverRef.current.contains(event.target));
var outOfControlInput = (controlInputRef === null || controlInputRef === void 0 ? void 0 : controlInputRef.current) == undefined || !controlInputRef.current.contains(event.target);
var isOut = outOfCalendar && outOfControlInput;
return isOut;
}, [popoverRef, controlInputRef]);
// Control the click outside
useEffect(() => {
function handleClickOutside(event) {
event.stopPropagation();
if (open) {
if (isOutside(event)) {
setOpen(false);
customOnBlur();
}
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => {
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 = useCallback(() => {
var nPlacement = getMaybeFuncValue(calendarPlacement);
setPlacement(nPlacement);
setOpen(true);
customOnFocus();
}, [calendarPlacement, customOnFocus]);
var handleBlur = useCallback(event => {
if (isOutside(event)) {
setOpen(false);
customOnBlur();
}
}, [isOutside, customOnBlur]);
return [hiddenInputRef, overlayContainerRef, popoverRef, controlInputRef, open, placement, handleFocus, handleBlur];
};
var _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 = (props, ref) => {
var {
// Global props
value,
defaultValue,
id,
name,
dateFormat = _defaultDateFormat(),
minDate,
maxDate,
clearButtonElement = '×',
showClearButton = true,
// Event props
onInvalid,
onChange,
onClear,
onBlur,
onFocus,
// Input Group props
size,
valid,
invalid,
customInputGroup,
// Input props
autoComplete = 'on',
autoFocus = false,
disabled = false,
noValidate = false,
placeholder,
required,
className,
style = undefined /* {
width: '100%'
} */,
inputRef,
customControl,
children,
// Calendar props
// target,
calendarContainer,
dayLabels = DEFAULT_DAY_LABELS,
monthLabels = DEFAULT_MONTH_LABELS,
weekStartsOn,
showWeeks = false,
previousButtonElement = '<',
nextButtonElement = '>',
pickMonthElement = undefined,
showTodayButton = false,
todayButtonLabel = 'Today',
roundedCorners = false,
cellPadding = '5px',
calendarPlacement = 'bottom'
} = props;
var propError = useCheckProps(value, defaultValue);
if (propError != undefined) {
throw new Error(propError);
}
var [hiddenInputRef, overlayContainerRef, popoverRef, controlInputRef, open, placement, handleFocus, handleBlur] = useCalendarProps(calendarPlacement, inputRef, autoFocus, onBlur, onFocus);
var [innerValue, inputValue, displayDate, selectedDate, handleClear, handleInputChange, handleChangeMonth, handleChangeDate, handleBadInputOnBlur] = useInputValues(controlInputRef, value, defaultValue, minDate, maxDate, dateFormat, onClear, onChange);
var [groupInputId, hiddenInputId, controlInputId, overlayId] = useInputIds(id, name, customControl);
useImperativeHandle(ref, () => ({
getValue: () => {
return selectedDate ? selectedDate.toISOString() : null;
},
getFormattedValue: () => {
return displayDate ? inputValue : null;
},
getNode: () => controlInputRef === null || controlInputRef === void 0 ? void 0 : controlInputRef.current
})); //, [controlInputRef, displayDate, inputValue, selectedDate]))
var fixedDayLabels = useFixedDayLabels(dayLabels, weekStartsOn);
var 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: () => handleFocus(),
onBlur: event => {
handleBadInputOnBlur();
handleBlur(event);
},
onChange: () => 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: newDisplayDate => handleChangeMonth(newDisplayDate),
monthLabels: monthLabels,
cellPadding: cellPadding,
selectedDate: selectedDate,
onChange: newSelectedDate => 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: () => handleClear()
}) : null, children);
};
var DatePicker = /*#__PURE__*/forwardRef(DatePickerBase);
export { DatePicker };
//# sourceMappingURL=reactstrap-date-picker.mjs.map