UNPKG

react-calendar-toolkit

Version:

React Calendar Toolkit is a set of React Components capable of rendering various calendars, datepickers etc.

1,637 lines (1,395 loc) 72.2 kB
import React, { useContext, createContext, useReducer, useEffect, useRef, useCallback, Fragment, useState } from 'react'; import { formatWithOptions, isWeekend, toDate, isSameMonth, isSameYear, isSameDay, getTime, addMonths, isWithinInterval, endOfMonth, startOfMonth, getYear, addYears, startOfYear, startOfWeekWithOptions, endOfWeekWithOptions, differenceInDays, addDays, getDate, formatDistanceStrictWithOptions } from 'date-fns/fp'; import PropTypes from 'prop-types'; import defaultLocale from 'date-fns/locale/en-US'; import classNames from 'classnames'; import { useTheme } from 'css-vars-hook'; import Popover from 'react-tiny-popover'; import ReactDOM from 'react-dom'; function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var compose = function compose() { for (var _len = arguments.length, fns = new Array(_len), _key = 0; _key < _len; _key++) { fns[_key] = arguments[_key]; } return function () { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return fns.reduceRight(function (params, f) { return Array.isArray(params) ? f.apply(void 0, _toConsumableArray(params)) : f(params); }, args); }; }; var TOGGLE_DATEPICKER = 'TOGGLE_DATEPICKER'; var initialState = { isVisible: false }; var reducer = function reducer() { var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState; var action = arguments.length > 1 ? arguments[1] : undefined; switch (action.type) { case TOGGLE_DATEPICKER: { var isVisible = action.payload; return _objectSpread2(_objectSpread2({}, state), {}, { isVisible: isVisible }); } default: return state; } }; var ModalContext = /*#__PURE__*/createContext({}); var useModalContext = function useModalContext() { return useContext(ModalContext); }; var useModalActions = function useModalActions() { var _useModalContext = useModalContext(), dispatch = _useModalContext.dispatch; return { toggleDatepicker: function toggleDatepicker(isVisible) { dispatch({ type: TOGGLE_DATEPICKER, payload: isVisible }); } }; }; var createStoreProvider = function createStoreProvider(_ref) { var initialState = _ref.initialState, reducer = _ref.reducer, context = _ref.context; return function (_ref2) { var children = _ref2.children; var Provider = context.Provider; var _useReducer = useReducer(reducer, initialState), _useReducer2 = _slicedToArray(_useReducer, 2), state = _useReducer2[0], dispatch = _useReducer2[1]; return /*#__PURE__*/React.createElement(Provider, { value: { state: state, dispatch: dispatch } }, children); }; }; var Provider = createStoreProvider({ initialState: initialState, reducer: reducer, context: ModalContext }); var withModalProvider = function withModalProvider(WrappedComponent) { return function (props) { return /*#__PURE__*/React.createElement(Provider, null, /*#__PURE__*/React.createElement(WrappedComponent, props)); }; }; var SET_DATE = 'SET_DATE'; var SET_VISIBILITY = 'SET_VISIBILITY'; var SET_TODAY = 'SET_TODAY'; var SET_PRECISION = 'SET_PRECISION'; var initialState$1 = {}; var reducer$1 = function reducer() { var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState$1; var action = arguments.length > 1 ? arguments[1] : undefined; switch (action.type) { case SET_DATE: { var _action$payload = action.payload, selectedTimestamp = _action$payload.selectedTimestamp, precision = _action$payload.precision; return _objectSpread2(_objectSpread2({}, state), {}, { selectedTimestamp: selectedTimestamp, precision: precision || state.precision }); } case SET_VISIBILITY: { var visibleTimestamp = action.payload.visibleTimestamp; return _objectSpread2(_objectSpread2({}, state), {}, { visibleTimestamp: visibleTimestamp }); } case SET_TODAY: { var todayTimestamp = action.payload.todayTimestamp; return _objectSpread2(_objectSpread2({}, state), {}, { todayTimestamp: todayTimestamp }); } case SET_PRECISION: { return _objectSpread2(_objectSpread2({}, state), {}, { precision: action.payload }); } default: return state; } }; /** * Unix timestamp * @typedef {number} UnixTimestamp */ /** * Date union type may be Date or Unix timestamp * @typedef {(Date|UnixTimestamp)} DateUnion */ /** * @function * @name formatDateWithLocale * @description Returns formatted date * @param {Object} options - Options object with locale * @param {string} pattern - Formatting pattern * @param {Date} date - Date object to apply format * @return {string} Formatted date */ var formatDateWithLocale = formatWithOptions; /** * @function * @name checkIsSameMonth * @description Checks if two dates belong to the same month * @param {DateUnion} dateLeft - Date to check * @param {DateUnion} dateRight - Date to check * @return {boolean} */ var checkIsSameMonth = isSameMonth; /** * @function * @name checkIsSameYear * @description Checks if two dates belong to the same year * @param {DateUnion} dateLeft - Date to check * @param {DateUnion} dateRight - Date to check * @return {boolean} */ var checkIsSameYear = isSameYear; /** * @function * @name checkIsSameDay * @description Checks if two dates belong to the same day * @param {DateUnion} dateLeft - Date to check * @param {DateUnion} dateRight - Date to check * @return {boolean} */ var checkIsSameDay = isSameDay; /** * @function * @name convertToTimestamp * @description Converts provided date to Unix timestamp * @param {Date} date - Date to convert * @return {UnixTimestamp} Unix timestamp */ var convertToTimestamp = function convertToTimestamp(date) { return getTime(date); }; /** * @function * @name convertToDate * @description Converts provided Unix timestamp to Date object * @param {number} timestamp - Date to convert * @return {Date} */ var convertToDate = function convertToDate(timestamp) { return toDate(timestamp); }; /** * @function * @name checkIsWithinInterval * @description Checks if date belongs to the interval * @typedef {Object} Interval * @property {Date} start - Start of interval * @property {Date} end - End of interval * @param {DateUnion} date - Date to check * @param {Interval} interval - Time range to check * @return {boolean} */ var checkIsWithinInterval = isWithinInterval; /** * @function * @name checkIsWeekend * @description Checks if date belongs to the weekend * @param {DateUnion} date - Date to check * @return {boolean} */ var checkIsWeekend = function checkIsWeekend(date) { return isWeekend(date); }; /** * @function * @name matchDatesWithPrecision * @description Checks if dates are the same with given precision, eg belong to same day|month|year * @param {string} precision - Date to check * @param {DateUnion} dateLeft - Date to check * @param {DateUnion} dateRight - Date to check * @return {boolean} */ var matchDatesWithPrecision = function matchDatesWithPrecision(precision, dateLeft, dateRight) { return { day: checkIsSameDay, month: checkIsSameMonth, year: checkIsSameYear }[precision](dateLeft, dateRight); }; /** * @function * @name ceilMonth * @description Gets end of month date * @param {DateUnion} date * @return {Date} */ var ceilMonth = endOfMonth; /** * @function * @name floorMonth * @description Gets start of month date * @param {DateUnion} date * @return {Date} */ var floorMonth = startOfMonth; /** * @function * @name addMonth * @description Adds months * @param {DateUnion} date - Date or Unix timestamp * @param {number} amount - Amount of months to add * @return {UnixTimestamp} */ var addMonth = function addMonth(date, amount) { return compose(convertToTimestamp, addMonths)(amount, date); }; /** * @function * @name subMonth * @description Subtracts months * @param {DateUnion} date - Date or Unix timestamp * @param {number} amount - Amount of months to subtract * @return {UnixTimestamp} */ var subMonth = function subMonth(date, amount) { return compose(convertToTimestamp, addMonths)(-amount, date); }; var DatepickerContext = /*#__PURE__*/createContext({}); var useDatepickerContext = function useDatepickerContext() { return useContext(DatepickerContext); }; var useDatepickerActions = function useDatepickerActions() { var _useDatepickerContext = useDatepickerContext(), dispatch = _useDatepickerContext.dispatch; return { setDate: function setDate(date) { dispatch({ type: SET_DATE, payload: { selectedTimestamp: convertToTimestamp(date) } }); }, setToday: function setToday(date) { dispatch({ type: SET_TODAY, payload: { todayTimestamp: convertToTimestamp(date) } }); }, setVisibility: function setVisibility(date) { dispatch({ type: SET_VISIBILITY, payload: { visibleTimestamp: convertToTimestamp(date) } }); }, setPrecision: function setPrecision(precision) { dispatch({ type: SET_PRECISION, payload: precision }); } }; }; var Provider$1 = createStoreProvider({ initialState: initialState$1, reducer: reducer$1, context: DatepickerContext }); var withDatepickerProvider = function withDatepickerProvider(WrappedComponent) { return function (props) { return /*#__PURE__*/React.createElement(Provider$1, null, /*#__PURE__*/React.createElement(WrappedComponent, props)); }; }; var useHasInitialValues = function useHasInitialValues() { var _useDatepickerContext = useDatepickerContext(), _useDatepickerContext2 = _useDatepickerContext.state, selectedTimestamp = _useDatepickerContext2.selectedTimestamp, todayTimestamp = _useDatepickerContext2.todayTimestamp, visibleTimestamp = _useDatepickerContext2.visibleTimestamp; return !!selectedTimestamp && !!todayTimestamp && !!visibleTimestamp; }; var useSetInitialValues = function useSetInitialValues(_ref) { var initialDate = _ref.initialDate, today = _ref.today, minPrecision = _ref.minPrecision; var _useDatepickerActions = useDatepickerActions(), setPrecision = _useDatepickerActions.setPrecision, setVisibility = _useDatepickerActions.setVisibility, setDate = _useDatepickerActions.setDate, setToday = _useDatepickerActions.setToday; var hasInitialValues = useHasInitialValues(); useEffect(function () { if (!hasInitialValues) { setDate(initialDate); setVisibility(initialDate); setToday(today); setPrecision(minPrecision); } }, [hasInitialValues, initialDate, minPrecision, setDate, setPrecision, setToday, setVisibility, today]); }; var config = Object.freeze({ supportedPrecisions: Object.freeze(['year', 'month', 'day']) }); var useIncrementPrecision = function useIncrementPrecision(minPrecision) { var _useDatepickerContext = useDatepickerContext(), precision = _useDatepickerContext.state.precision; var _useDatepickerActions = useDatepickerActions(), setPrecision = _useDatepickerActions.setPrecision; var getNextPrecision = function getNextPrecision(precisionEnum, currentPrecision) { var currentIndex = precisionEnum.indexOf(currentPrecision); return precisionEnum[currentIndex + 1]; }; var limitPrecision = function limitPrecision(precisionEnum) { var currentIndex = precisionEnum.indexOf(minPrecision); return precisionEnum.slice(0, currentIndex + 1); }; var datepickerPrecisions = limitPrecision(config.supportedPrecisions); var nextPrecision = getNextPrecision(datepickerPrecisions, precision); return function () { nextPrecision && setPrecision(nextPrecision); }; }; function curry(fn) { var _this = this; var curried = function curried() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } if (args.length >= fn.length) { return fn.apply(_this, args); } return function () { for (var _len2 = arguments.length, args2 = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args2[_key2] = arguments[_key2]; } return curried.apply(_this, args.concat(args2)); }; }; return curried; } /** * Item name * @typedef {Object} ItemName * @property {string} [narrow] - Narrow name of item - 'S' * @property {string} [short] - Short name of item - 'Su' * @property {string} [abbreviated] - Abbreviated name of item - 'Sun' * @property {string} [wide] - Full name of item - 'Sunday' * @property {number} [numeric] - Numeric name of item - 1 */ /** * Item description * @typedef {Object} ItemDescription * @property {ItemName} name - Item name vocabulary * @property {Date} date - starting date of the item */ /** * Date union type may be Date or Unix timestamp * @typedef {(Date|number)} DateUnion */ /** * @function * @name getWeekDayNames * @description Returns array of weekday names * @param {Object} locale - Locale object * @return {Array.<ItemName>} */ var getWeekDayNames = function getWeekDayNames(locale) { return _toConsumableArray(Array(7).keys()).map(function (i) { var dayNumber = i + locale.options.weekStartsOn === 7 ? 0 : i + locale.options.weekStartsOn; return { short: locale.localize.day(dayNumber, { width: 'short' }), narrow: locale.localize.day(dayNumber, { width: 'narrow' }), abbreviated: locale.localize.day(dayNumber, { width: 'abbreviated' }), wide: locale.localize.day(dayNumber, { width: 'wide' }), numeric: i }; }); }; /** * @function * @name getYears * @description Returns collection year description objects in the provided range * @param {DateUnion} startDate - Start date * @param {DateUnion} endDate - End date * @return {Array.<ItemDescription>} */ var getYears = function getYears(startDate, endDate) { var startYear = getYear(startDate); var endYear = getYear(endDate) + 1; var years = _toConsumableArray(Array(endYear - startYear).keys()); return years.map(function (year, i) { return { name: { numeric: startYear + i }, date: addYears(i, startDate) }; }); }; var getYearsCurried = curry(getYears); /** * @function * @name getMonths * @description Returns collection of month description objects based on provided date * @param {Object} locale - Locale object * @param {DateUnion} date - Date or Unix timestamp * @return {Array.<ItemDescription>} */ var getMonths = function getMonths(locale, date) { var year = startOfYear(date); var monthNames = _toConsumableArray(Array(12).keys()).map(function (i) { return { wide: locale.localize.month(i, { width: 'wide' }), abbreviated: locale.localize.month(i, { width: 'abbreviated' }), narrow: locale.localize.month(i, { width: 'narrow' }), numeric: i }; }); return monthNames.map(function (name, i) { return { name: name, date: toDate(addMonth(year, i)) }; }); }; var getMonthsCurried = curry(getMonths); /** * @function * @name getDays * @description Returns collection of day description objects based on provided date * @param {Object} locale - Locale object * @param {DateUnion} timestamp - Unix timestamp or Date object * @return {Array.<ItemDescription>} */ var getDays = function getDays(locale, timestamp) { var monthStart = floorMonth(timestamp); var monthEnd = ceilMonth(monthStart); var startDate = startOfWeekWithOptions({ locale: locale }, monthStart); var endDate = endOfWeekWithOptions({ locale: locale }, monthEnd); var cellLength = differenceInDays(startDate, endDate); return new Array(cellLength + 1).fill('').map(function (_, i) { return { date: addDays(i, startDate), name: { numeric: getDate(addDays(i, startDate)) } }; }); }; var getDaysCurried = curry(getDays); var LocaleContext = /*#__PURE__*/React.createContext({}); var useLocaleContext = function useLocaleContext() { return useContext(LocaleContext); }; var Provider$2 = function Provider(_ref) { var children = _ref.children, dateFnsLocale = _ref.dateFnsLocale; return /*#__PURE__*/React.createElement(LocaleContext.Provider, { value: dateFnsLocale }, children); }; Provider$2.propTypes = { dateFnsLocale: PropTypes.shape({}), children: PropTypes.element.isRequired }; Provider$2.defaultProps = { dateFnsLocale: defaultLocale }; var withLocaleContext = function withLocaleContext(WrappedComponent) { return function (_ref2) { var dateFnsLocale = _ref2.dateFnsLocale, restProps = _objectWithoutProperties(_ref2, ["dateFnsLocale"]); return /*#__PURE__*/React.createElement(Provider$2, { dateFnsLocale: dateFnsLocale }, /*#__PURE__*/React.createElement(WrappedComponent, restProps)); }; }; var useLocaleEnumerators = function useLocaleEnumerators(precision) { var locale = useLocaleContext(); return { day: getDaysCurried(locale), month: getMonthsCurried(locale), year: getYearsCurried }[precision]; }; var useWeekDayNames = function useWeekDayNames() { var locale = useLocaleContext(); return getWeekDayNames(locale); }; var useMonthStepperLabels = function useMonthStepperLabels() { var locale = useLocaleContext(); var incrementMonthLabel = formatDistanceStrictWithOptions({ locale: locale, addSuffix: true }, new Date(2020, 0, 1), new Date(2020, 1, 1)); var decrementMonthLabel = formatDistanceStrictWithOptions({ locale: locale, addSuffix: true }, new Date(2020, 1, 1), new Date(2020, 0, 1)); return { incrementMonthLabel: incrementMonthLabel, decrementMonthLabel: decrementMonthLabel }; }; var useFormatDate = function useFormatDate() { var locale = useLocaleContext(); return formatDateWithLocale({ locale: locale }); }; var classes = {"grid":"Day-module_grid__-91j0","placeholder":"Day-module_placeholder__1L0Xk","wrapper":"Day-module_wrapper__1t95P","isDisabled":"Day-module_isDisabled__3G-x3","isSelected":"Day-module_isSelected__3tDFG","isWeekend":"Day-module_isWeekend__Z_3Ds","isCurrent":"Day-module_isCurrent__2Yy1O","isHighlighted":"Day-module_isHighlighted__BYgLM"}; var Day = function Day(_ref) { var _classNames; var onDateSet = _ref.onDateSet, date = _ref.date, belongsToSameMonth = _ref.belongsToSameMonth, isCurrent = _ref.isCurrent, isSelected = _ref.isSelected, isDisabled = _ref.isDisabled, isHighlighted = _ref.isHighlighted, isWeekend = _ref.isWeekend, name = _ref.name; /** * Returns formatted date * @param {string} pattern - Formatting pattern * @param {Date} date - Date object to apply format * @return {string} Formatted date */ var formatDate = useFormatDate(); var handleClick = function handleClick() { onDateSet(date); }; return belongsToSameMonth ? /*#__PURE__*/React.createElement("div", { tabIndex: isDisabled ? '-1' : '0', role: "button", onClick: handleClick, onKeyDown: handleClick, className: classNames((_classNames = {}, _defineProperty(_classNames, classes.wrapper, true), _defineProperty(_classNames, classes.isCurrent, isCurrent), _defineProperty(_classNames, classes.isSelected, isSelected), _defineProperty(_classNames, classes.isDisabled, isDisabled), _defineProperty(_classNames, classes.isWeekend, isWeekend), _defineProperty(_classNames, classes.isHighlighted, isHighlighted), _classNames)), "aria-disabled": isDisabled, "aria-label": formatDate('do LLLL EEEE', date) }, name.numeric) : /*#__PURE__*/React.createElement("div", { className: classes.placeholder }); }; Day.propTypes = { /** Flag, showing if this day entry and selected date __belong to the same month__. */ belongsToSameMonth: PropTypes.bool.isRequired, /** Flag, showing if this day entry is __selected__. */ isSelected: PropTypes.bool.isRequired, /** Flag, showing if this day entry is __disabled__. */ isDisabled: PropTypes.bool.isRequired, /** Flag, showing if this day entry is __highlighted__. */ isHighlighted: PropTypes.bool.isRequired, /** Flag, showing if this day entry is __weekend__. */ isWeekend: PropTypes.bool.isRequired, /** Function to set date for Calendar, e. g. `onDateSet(date)`. */ onDateSet: PropTypes.func.isRequired, /** Date for this day entry */ date: PropTypes.instanceOf(Date).isRequired, /** Flag, showing if this day entry is __today__. */ isCurrent: PropTypes.bool.isRequired, /** Object, which has `numeric` property with day number. */ name: PropTypes.shape({ numeric: PropTypes.number.isRequired }).isRequired }; var DayGrid = function DayGrid(_ref) { var children = _ref.children, className = _ref.className; return /*#__PURE__*/React.createElement("div", { className: className || classes.grid }, children); }; DayGrid.propTypes = { children: PropTypes.node.isRequired, className: PropTypes.string.isRequired }; var classes$1 = {"grid":"Month-module_grid__2TOtv","wrapper":"Month-module_wrapper__Ahs6a","isDisabled":"Month-module_isDisabled__3S9Dl","isSelected":"Month-module_isSelected__2xISL","isCurrent":"Month-module_isCurrent__1vqLk"}; var Month = function Month(_ref) { var _classNames; var onDateSet = _ref.onDateSet, date = _ref.date, isDisabled = _ref.isDisabled, isCurrent = _ref.isCurrent, isSelected = _ref.isSelected, name = _ref.name, isHighlighted = _ref.isHighlighted; var handleClick = function handleClick() { onDateSet(date); }; return /*#__PURE__*/React.createElement("div", { tabIndex: isDisabled ? '-1' : '0', role: "button", onClick: handleClick, onKeyPress: handleClick, className: classNames((_classNames = {}, _defineProperty(_classNames, classes$1.wrapper, true), _defineProperty(_classNames, classes$1.isSelected, isSelected), _defineProperty(_classNames, classes$1.isDisabled, isDisabled), _defineProperty(_classNames, classes$1.isCurrent, isCurrent), _defineProperty(_classNames, classes$1.isHighlighted, isHighlighted), _classNames)), "aria-disabled": isDisabled, "aria-label": name.wide }, name.abbreviated); }; Month.propTypes = { /** Flag, showing if this month entry is __disabled__. */ isDisabled: PropTypes.bool.isRequired, /** Flag, showing if this month entry is __highlighted__. */ isHighlighted: PropTypes.bool.isRequired, /** Flag, showing if this month entry is __selected__. */ isSelected: PropTypes.bool.isRequired, /** Function to set date for Calendar, e. g. `onDateSet(date)`. */ onDateSet: PropTypes.func.isRequired, /** Date for this month entry */ date: PropTypes.instanceOf(Date).isRequired, /** Flag, showing if this month entry and current date __belong to the same month__. */ isCurrent: PropTypes.bool.isRequired, /** Object containing month name localized in different forms */ name: PropTypes.shape({ /** 'enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre' */ wide: PropTypes.string.isRequired, /** 'ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.', 'sep.', 'oct.', 'nov.', 'dic.' */ abbreviated: PropTypes.string.isRequired, /** 'E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D' */ narrow: PropTypes.string.isRequired, /** 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 */ numeric: PropTypes.number.isRequired }).isRequired }; var MonthGrid = function MonthGrid(_ref) { var children = _ref.children, className = _ref.className; return /*#__PURE__*/React.createElement("div", { className: className || classes$1.grid, role: "grid" }, children); }; MonthGrid.propTypes = { className: PropTypes.string.isRequired, children: PropTypes.node.isRequired }; var isInViewport = function isInViewport(elem) { var distance = elem.getBoundingClientRect(); return distance.top >= 0 && distance.left >= 0 && distance.bottom <= (window.innerHeight || document.documentElement.clientHeight) && distance.right <= (window.innerWidth || document.documentElement.clientWidth); }; var scrollStop = function scrollStop(callback) { var isScrolling; window.addEventListener('scroll', function () { window.clearTimeout(isScrolling); // eslint-disable-next-line fp/no-mutation isScrolling = setTimeout(function () { callback(); }, 66); }, false); }; var noScroll = function noScroll() { var x = window.scrollX; var y = window.scrollY; window.scrollTo(x, y); }; /** * @function * @name useScrollIntoView * @description React hook. Scrolls element into viewport if parent container is visible. * @param {Object} ref - React ref * @param {string} containerSelector - Selector of containing element: '.className' * @param {Boolean} condition - Condition flag * @return {void} */ var useScrollIntoView = function useScrollIntoView() { var ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var containerSelector = arguments.length > 1 ? arguments[1] : undefined; var condition = arguments.length > 2 ? arguments[2] : undefined; useEffect(function () { var element = ref.current; var container = element && element.closest(containerSelector); if (element && condition && container) { container.addEventListener('scroll', function (event) { window.addEventListener('scroll', noScroll); }, false); scrollStop(function () { window.removeEventListener('scroll', noScroll); }); isInViewport(container) && element.scrollIntoView({ block: 'nearest', inline: 'nearest' }); } return function () { window.removeEventListener('scroll', noScroll); }; }, [condition, containerSelector, ref]); }; var classes$2 = {"scrollContainer":"Year-module_scrollContainer__1Qj9V","grid":"Year-module_grid__2RMMM","wrapper":"Year-module_wrapper__1PVy7","isSelected":"Year-module_isSelected__3WvJz","isCurrent":"Year-module_isCurrent__1txcW"}; var Year = function Year(_ref) { var _classNames; var isHighlighted = _ref.isHighlighted, onDateSet = _ref.onDateSet, date = _ref.date, isSelected = _ref.isSelected, isCurrent = _ref.isCurrent, name = _ref.name; var ref = useRef(); var handleClick = function handleClick() { onDateSet(date); }; useScrollIntoView(ref, ".".concat(classes$2.scrollContainer), isSelected); return /*#__PURE__*/React.createElement("div", { ref: ref, tabIndex: "0", role: "button", onClick: handleClick, onKeyPress: handleClick, className: classNames((_classNames = {}, _defineProperty(_classNames, classes$2.wrapper, true), _defineProperty(_classNames, classes$2.isCurrent, isCurrent), _defineProperty(_classNames, classes$2.isSelected, isSelected), _defineProperty(_classNames, classes$2.isHighlighted, isHighlighted), _classNames)), "aria-label": name.numeric }, name.numeric); }; Year.propTypes = { /** Flag, showing if this year entry is __selected__. */ isSelected: PropTypes.bool.isRequired, /** Flag, showing if this year entry is __highlighted__. */ isHighlighted: PropTypes.bool.isRequired, /** Function to set date for Calendar, e. g. `onDateSet(date)`. */ onDateSet: PropTypes.func.isRequired, /** Date for this year entry */ date: PropTypes.instanceOf(Date).isRequired, /** Flag, showing if this month entry and current date __belong to the same year__. */ isCurrent: PropTypes.bool.isRequired, /** Object, which has `numeric` property with current year number. */ name: PropTypes.shape({ numeric: PropTypes.number.isRequired }).isRequired }; var YearGrid = function YearGrid(_ref) { var children = _ref.children, className = _ref.className; return /*#__PURE__*/React.createElement("div", { className: classes$2.scrollContainer }, /*#__PURE__*/React.createElement("div", { className: className || classes$2.grid }, children)); }; YearGrid.propTypes = { children: PropTypes.node.isRequired, className: PropTypes.string.isRequired }; var useLogic = function useLogic(_ref) { var disableDate = _ref.disableDate, endDate = _ref.endDate, precision = _ref.precision, startDate = _ref.startDate, highlightDate = _ref.highlightDate, onDateSet = _ref.onDateSet, highlightWeekends = _ref.highlightWeekends, visibleTimestamp = _ref.visibleTimestamp, selectedTimestamp = _ref.selectedTimestamp, todayTimestamp = _ref.todayTimestamp; var getIsDisabled = useCallback(function (date) { if (precision === 'year') return false; // we are not disabling years, just rendering the range if (precision === 'month') { return !checkIsWithinInterval({ start: floorMonth(startDate), end: ceilMonth(endDate) }, date); } return disableDate({ date: date, isWeekend: checkIsWeekend(date), precision: precision }) || !checkIsWithinInterval({ start: startDate, end: endDate }, date); }, [disableDate, endDate, precision, startDate]); var getIsHighlighted = useCallback(function (date) { return highlightDate({ date: date, isWeekend: checkIsWeekend(date), precision: precision }); }, [highlightDate, precision]); var handleDateSet = useCallback(function (date) { var isDisabled = getIsDisabled(date); !isDisabled && onDateSet(date); }, [getIsDisabled, onDateSet]); var getIsWeekend = function getIsWeekend(date) { return precision === 'day' && highlightWeekends && checkIsWeekend(date); }; var getBelongsToSameMonth = function getBelongsToSameMonth(date) { return precision === 'day' && checkIsSameMonth(date, visibleTimestamp); }; var getIsSelected = function getIsSelected(date) { return matchDatesWithPrecision(precision, date, selectedTimestamp); }; var getIsCurrent = function getIsCurrent(date) { return matchDatesWithPrecision(precision, date, todayTimestamp); }; return { getIsDisabled: getIsDisabled, getIsHighlighted: getIsHighlighted, handleDateSet: handleDateSet, getIsWeekend: getIsWeekend, getBelongsToSameMonth: getBelongsToSameMonth, getIsSelected: getIsSelected, getIsCurrent: getIsCurrent }; }; var Calendar = function Calendar(_ref) { var onDateSet = _ref.onDateSet, wrapperClassName = _ref.wrapperClassName, todayTimestamp = _ref.todayTimestamp, selectedTimestamp = _ref.selectedTimestamp, visibleTimestamp = _ref.visibleTimestamp, renderAs = _ref.renderAs, precision = _ref.precision, startDate = _ref.startDate, endDate = _ref.endDate, disableDate = _ref.disableDate, highlightDate = _ref.highlightDate, highlightWeekends = _ref.highlightWeekends; var getItems = useLocaleEnumerators(precision); var items = precision === 'year' ? getItems(startDate, endDate) : getItems(visibleTimestamp); var _useLogic = useLogic({ disableDate: disableDate, endDate: endDate, precision: precision, startDate: startDate, highlightDate: highlightDate, onDateSet: onDateSet, highlightWeekends: highlightWeekends, visibleTimestamp: visibleTimestamp, selectedTimestamp: selectedTimestamp, todayTimestamp: todayTimestamp }), getIsDisabled = _useLogic.getIsDisabled, getIsHighlighted = _useLogic.getIsHighlighted, handleDateSet = _useLogic.handleDateSet, getIsWeekend = _useLogic.getIsWeekend, getBelongsToSameMonth = _useLogic.getBelongsToSameMonth, getIsSelected = _useLogic.getIsSelected, getIsCurrent = _useLogic.getIsCurrent; var Wrapper = { day: DayGrid, month: MonthGrid, year: YearGrid }[precision]; var VisualComponent = renderAs; return /*#__PURE__*/React.createElement(Wrapper, { className: wrapperClassName }, items.map(function (_ref2) { var name = _ref2.name, date = _ref2.date; return /*#__PURE__*/React.createElement(VisualComponent, { isWeekend: getIsWeekend(date), onDateSet: handleDateSet, isSelected: getIsSelected(date), isCurrent: getIsCurrent(), belongsToSameMonth: getBelongsToSameMonth(date), isDisabled: getIsDisabled(date), isHighlighted: getIsHighlighted(date), name: name, date: date, key: date }); })); }; Calendar.propTypes = { precision: PropTypes.oneOf(config.supportedPrecisions).isRequired, wrapperClassName: PropTypes.string.isRequired, renderAs: PropTypes.elementType.isRequired, onDateSet: PropTypes.func.isRequired, todayTimestamp: PropTypes.number.isRequired, selectedTimestamp: PropTypes.number.isRequired, visibleTimestamp: PropTypes.number.isRequired, startDate: PropTypes.instanceOf(Date).isRequired, endDate: PropTypes.instanceOf(Date).isRequired, disableDate: PropTypes.func.isRequired, highlightDate: PropTypes.func.isRequired, highlightWeekends: PropTypes.bool }; Calendar.defaultProps = { highlightWeekends: false }; var useLogic$1 = function useLogic(_ref) { var startDate = _ref.startDate, endDate = _ref.endDate, visibleTimestamp = _ref.visibleTimestamp; var _useDatepickerActions = useDatepickerActions(), setVisibility = _useDatepickerActions.setVisibility, setPrecision = _useDatepickerActions.setPrecision; var isAvailable = useCallback(function (date) { return checkIsWithinInterval({ start: floorMonth(startDate), end: ceilMonth(endDate) }, date); }, [endDate, startDate]); var onSetPrecision = useCallback(function (nextPrecision) { setPrecision(nextPrecision); }, [setPrecision]); var onIncrementMonth = useCallback(function () { var nextDate = addMonth(visibleTimestamp, 1); isAvailable(nextDate) && setVisibility(nextDate); }, [isAvailable, setVisibility, visibleTimestamp]); var onDecrementMonth = useCallback(function () { var nextDate = subMonth(visibleTimestamp, 1); isAvailable(nextDate) && setVisibility(nextDate); }, [isAvailable, setVisibility, visibleTimestamp]); return { onSetPrecision: onSetPrecision, onIncrementMonth: onIncrementMonth, onDecrementMonth: onDecrementMonth }; }; var Selector = function Selector(_ref) { var todayTimestamp = _ref.todayTimestamp, selectedTimestamp = _ref.selectedTimestamp, renderAs = _ref.renderAs, startDate = _ref.startDate, endDate = _ref.endDate, visibleTimestamp = _ref.visibleTimestamp, precision = _ref.precision; var monthStepperLabels = useMonthStepperLabels(); var _useLogic = useLogic$1({ startDate: startDate, endDate: endDate, visibleTimestamp: visibleTimestamp }), onSetPrecision = _useLogic.onSetPrecision, onIncrementMonth = _useLogic.onIncrementMonth, onDecrementMonth = _useLogic.onDecrementMonth; var SelectorVisual = renderAs; return /*#__PURE__*/React.createElement(SelectorVisual, { precision: precision, monthStepperLabels: monthStepperLabels, incrementMonth: onIncrementMonth, decrementMonth: onDecrementMonth, setPrecision: onSetPrecision, todayDate: convertToDate(todayTimestamp), selectedDate: convertToDate(selectedTimestamp), visibleDate: convertToDate(visibleTimestamp) }); }; Selector.propTypes = { selectedTimestamp: PropTypes.number.isRequired, todayTimestamp: PropTypes.number.isRequired, visibleTimestamp: PropTypes.number.isRequired, renderAs: PropTypes.elementType.isRequired, startDate: PropTypes.instanceOf(Date).isRequired, endDate: PropTypes.instanceOf(Date).isRequired, precision: PropTypes.oneOf(['year', 'month', 'day']).isRequired }; var Header = function Header(_ref) { var renderAs = _ref.renderAs, title = _ref.title; var _useDatepickerContext = useDatepickerContext(), _useDatepickerContext2 = _useDatepickerContext.state, selectedTimestamp = _useDatepickerContext2.selectedTimestamp, todayTimestamp = _useDatepickerContext2.todayTimestamp; var HeaderUI = renderAs; return /*#__PURE__*/React.createElement(HeaderUI, { selectedDate: convertToDate(selectedTimestamp), todayDate: convertToDate(todayTimestamp), title: title }); }; Header.propTypes = { renderAs: PropTypes.elementType.isRequired, title: PropTypes.string.isRequired }; var baseColor = '#43a047'; var gray = 'rgba(0, 0, 0, 0.38)'; var borderRadius = '4px'; var defaultTheme = { /** Set font for datepicker */ fontPrimary: 'Helvetica Neue', /** Font, which is applied, if --fontPrimary is not available */ fontSecondary: 'Arial', /** Fallback font if two previous are unavailable */ fontFallback: 'sans-serif', fontSize: '14px', fontWeight: '400', /** Applied to the title */ fontSizeSmall: '10px', /** Applied to the header text */ fontSizeBig: '24px', /** Set inner width */ calendarWidth: '240px', /** Calculate total width */ datePickerWidth: 'calc(var(--calendarWidth) + var(--innerPadding) * 2)', selectorHeight: '36px', calendarHeight: '200px', /** Set padding between elements */ innerPadding: '12px', /** Day, month, year entries height */ entryHeight: '32px', entryMargin: '1px', datepickerBorderRadius: borderRadius, entryBorderRadius: borderRadius, /** Background color of Calendar */ bgColor: 'white', /** Base color for text */ textColor: 'black', headerBgColor: baseColor, weekendTextColor: 'red', headerTextColor: 'white', borderColor: gray, modalBgColor: gray, weekDayColor: gray, entryHoverColor: 'rgba(0, 0, 0, 0.08)', entrySelectedColor: baseColor, entryHighlightColor: 'lightblue', inputWidth: '90px', inputPadding: '8px', inputBorderRadius: borderRadius, inputBorderColor: gray, inputHighlightColor: 'lightblue' }; var ThemeContext = /*#__PURE__*/React.createContext({}); var useThemeContext = function useThemeContext() { return useContext(ThemeContext); }; var Provider$3 = function Provider(_ref) { var children = _ref.children, theme = _ref.theme; return /*#__PURE__*/React.createElement(ThemeContext.Provider, { value: theme }, children); }; Provider$3.propTypes = { theme: PropTypes.shape({}), children: PropTypes.element.isRequired }; Provider$3.defaultProps = { theme: {} }; // eslint-disable-next-line react/prop-types var withTheme = function withTheme(WrappedComponent) { return function (_ref2) { var theme = _ref2.theme, restProps = _objectWithoutProperties(_ref2, ["theme"]); return /*#__PURE__*/React.createElement(Provider$3, { theme: theme }, /*#__PURE__*/React.createElement(WrappedComponent, restProps)); }; }; /** @function * @name useTheme * @description React hook. Sets css variables from Context and defaultTheme * @param {Object.<string, string>} [defaultTheme=defaults] Default theme to override with context values * @return {[Object, Function]} */ var useThemeFeature = function useThemeFeature() { var defaultTheme$1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultTheme; var propsTheme = useThemeContext(); var mergedTheme = _objectSpread2(_objectSpread2({}, defaultTheme$1), propsTheme); var _useTheme = useTheme(mergedTheme), ref = _useTheme.ref, setRef = _useTheme.setRef, style = _useTheme.style; return { ref: ref, setRef: setRef, style: style }; }; var classes$3 = {"datepickerWrapper":"DatepickerWrapper-module_datepickerWrapper__2OagP"}; var DatepickerWrapper = function DatepickerWrapper(_ref) { var title = _ref.title, children = _ref.children, className = _ref.className; var _useTheme = useThemeFeature(), setRef = _useTheme.setRef, style = _useTheme.style; return /*#__PURE__*/React.createElement("div", { style: style, ref: setRef, className: className, "aria-label": title, role: "dialog" }, children); }; DatepickerWrapper.propTypes = { children: PropTypes.node.isRequired, /** Title of the component, used for accessibility reasons */ title: PropTypes.string.isRequired, className: PropTypes.string }; DatepickerWrapper.defaultProps = { className: classes$3.datepickerWrapper }; var classes$4 = {"wrapper":"Header-module_wrapper__3P_XR","currentDate":"Header-module_currentDate__gaViY","title":"Header-module_title__3M8C7"}; var Header$1 = function Header(_ref) { var selectedDate = _ref.selectedDate, title = _ref.title, todayDate = _ref.todayDate; /** * Returns formatted date * @param {string} pattern - Formatting pattern * @param {Date} date - Date object to apply format * @return {string} Formatted date */ var formatDate = useFormatDate(); return /*#__PURE__*/React.createElement("div", { className: classes$4.wrapper }, /*#__PURE__*/React.createElement("div", { className: classes$4.title }, title), /*#__PURE__*/React.createElement("div", { "aria-live": "polite", className: classes$4.currentDate }, formatDate('MMM do', selectedDate))); }; Header$1.propTypes = { /** Set today date. */ todayDate: PropTypes.instanceOf(Date).isRequired, // eslint-disable-line react/no-unused-prop-types /** Set selected date. */ selectedDate: PropTypes.instanceOf(Date).isRequired, // eslint-disable-line react/no-unused-prop-types /** Set title of datepicker. */ title: PropTypes.string.isRequired }; var classes$5 = {"wrapper":"Selector-module_wrapper__3TwUo","buttons":"Selector-module_buttons__1j6fe","stepper":"Selector-module_stepper__2B4S4"}; var Selector$1 = function Selector(_ref) { var selectedDate = _ref.selectedDate, todayDate = _ref.todayDate, setPrecision = _ref.setPrecision, decrementMonth = _ref.decrementMonth, incrementMonth = _ref.incrementMonth, precision = _ref.precision, monthStepperLabels = _ref.monthStepperLabels, visibleDate = _ref.visibleDate; var formatDate = useFormatDate(); var year = formatDate('y', visibleDate); var month = formatDate('LLLL', visibleDate); return /*#__PURE__*/React.createElement("div", { className: classes$5.wrapper }, /*#__PURE__*/React.createElement("div", { className: classes$5.buttons }, /*#__PURE__*/React.createElement("button", { onClick: function onClick() { setPrecision('year'); }, "aria-live": "polite", type: "button" }, year), precision !== 'year' && /*#__PURE__*/React.createElement("button", { onClick: function onClick() { setPrecision('month'); }, "aria-live": "polite", type: "button" }, month)), precision === 'day' && /*#__PURE__*/React.createElement("div", { className: classes$5.stepper }, /*#__PURE__*/React.createElement("button", { onClick: function onClick() { decrementMonth(); }, "aria-label": monthStepperLabels.decrementMonthLabel, type: "button" }, "\u27E8"), /*#__PURE__*/React.createElement("button", { onClick: function onClick() { incrementMonth(); }, "aria-label": monthStepperLabels.incrementMonthLabel, type: "button" }, "\u27E9"))); }; Selector$1.propTypes = { /** Method which sets precision for Calendar shown below, e.g. `setPrecision('month')`. */ setPrecision: PropTypes.func.isRequired, /** Method which __adds 1 month__ to selected date for Calendar and Header components, e.g. `incrementMonth(selectedDate)`. */ incrementMonth: PropTypes.func.isRequired, /** Method which __subtracts 1 month__ from selected date for Calendar and Header components, e.g. `incrementMonth(selectedDate)`. */ decrementMonth: PropTypes.func.isRequired, /** Selected date of Calendar */ selectedDate: PropTypes.instanceOf(Date).isRequired, /** Defines visibility of dates, displayed in current Calendar */ visibleDate: PropTypes.instanceOf(Date).isRequired, /** Today date */ todayDate: PropTypes.instanceOf(Date).isRequired, /** Set minimum precision (measuring unit) of calendar. Possible values: 'day', 'month', 'year'. */ precision: PropTypes.oneOf(['year', 'month', 'day']).isRequired, /** Localized accessibility labels for __month stepper__ */ monthStepperLabels: PropTypes.shape({ /** +1 month */ incrementMonthLabel: PropTypes.string.isRequired, /** -1 month */ decrementMonthLabel: PropTypes.string.isRequired }).isRequired }; var classes$6 = {"grid":"Weekdays-module_grid__2dX1R","wrapper":"Weekdays-module_wrapper__1Mp2z"}; var Weekdays = function Weekdays(_ref) { var names = _ref.names; return /*#__PURE__*/React.createElement("div", { className: classes$6.grid, role: "presentation" }, names.map(function (name) { return /*#__PURE__*/React.createElement("div", { key: name.s