UNPKG

react-day-picker

Version:

Flexible date picker component for React

676 lines (597 loc) 24 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.ModifiersUtils = exports.LocaleUtils = exports.DateUtils = exports.DayPicker = undefined; var _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; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _Caption = require('./Caption'); var _Caption2 = _interopRequireDefault(_Caption); var _Navbar = require('./Navbar'); var _Navbar2 = _interopRequireDefault(_Navbar); var _Month = require('./Month'); var _Month2 = _interopRequireDefault(_Month); var _Weekday = require('./Weekday'); var _Weekday2 = _interopRequireDefault(_Weekday); var _Helpers = require('./Helpers'); var Helpers = _interopRequireWildcard(_Helpers); var _DateUtils = require('./DateUtils'); var DateUtils = _interopRequireWildcard(_DateUtils); var _LocaleUtils = require('./LocaleUtils'); var LocaleUtils = _interopRequireWildcard(_LocaleUtils); var _ModifiersUtils = require('./ModifiersUtils'); var ModifiersUtils = _interopRequireWildcard(_ModifiersUtils); var _classNames = require('./classNames'); var _classNames2 = _interopRequireDefault(_classNames); var _keys = require('./keys'); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var DayPicker = exports.DayPicker = function (_Component) { _inherits(DayPicker, _Component); function DayPicker(props) { _classCallCheck(this, DayPicker); var _this = _possibleConstructorReturn(this, (DayPicker.__proto__ || Object.getPrototypeOf(DayPicker)).call(this, props)); _this.dayPicker = null; _this.showNextMonth = function (callback) { if (!_this.allowNextMonth()) { return; } var deltaMonths = _this.props.pagedNavigation ? _this.props.numberOfMonths : 1; var nextMonth = DateUtils.addMonths(_this.state.currentMonth, deltaMonths); _this.showMonth(nextMonth, callback); }; _this.showPreviousMonth = function (callback) { if (!_this.allowPreviousMonth()) { return; } var deltaMonths = _this.props.pagedNavigation ? _this.props.numberOfMonths : 1; var previousMonth = DateUtils.addMonths(_this.state.currentMonth, -deltaMonths); _this.showMonth(previousMonth, callback); }; _this.handleKeyDown = function (e) { e.persist(); switch (e.keyCode) { case _keys.LEFT: if (_this.props.dir === 'rtl') { _this.showNextMonth(); } else { _this.showPreviousMonth(); } Helpers.cancelEvent(e); break; case _keys.RIGHT: if (_this.props.dir === 'rtl') { _this.showPreviousMonth(); } else { _this.showNextMonth(); } Helpers.cancelEvent(e); break; case _keys.UP: _this.showPreviousYear(); Helpers.cancelEvent(e); break; case _keys.DOWN: _this.showNextYear(); Helpers.cancelEvent(e); break; default: break; } if (_this.props.onKeyDown) { _this.props.onKeyDown(e); } }; _this.handleDayKeyDown = function (day, modifiers, e) { e.persist(); switch (e.keyCode) { case _keys.LEFT: Helpers.cancelEvent(e); if (_this.props.dir === 'rtl') { _this.focusNextDay(e.target); } else { _this.focusPreviousDay(e.target); } break; case _keys.RIGHT: Helpers.cancelEvent(e); if (_this.props.dir === 'rtl') { _this.focusPreviousDay(e.target); } else { _this.focusNextDay(e.target); } break; case _keys.UP: Helpers.cancelEvent(e); _this.focusPreviousWeek(e.target); break; case _keys.DOWN: Helpers.cancelEvent(e); _this.focusNextWeek(e.target); break; case _keys.ENTER: case _keys.SPACE: Helpers.cancelEvent(e); if (_this.props.onDayClick) { _this.handleDayClick(day, modifiers, e); } break; default: break; } if (_this.props.onDayKeyDown) { _this.props.onDayKeyDown(day, modifiers, e); } }; _this.handleDayClick = function (day, modifiers, e) { e.persist(); if (modifiers[_this.props.classNames.outside] && _this.props.enableOutsideDaysClick) { _this.handleOutsideDayClick(day); } if (_this.props.onDayClick) { _this.props.onDayClick(day, modifiers, e); } }; _this.handleTodayButtonClick = function (e) { var today = new Date(); var month = new Date(today.getFullYear(), today.getMonth()); _this.showMonth(month); e.target.blur(); if (_this.props.onTodayButtonClick) { e.persist(); _this.props.onTodayButtonClick(new Date(today.getFullYear(), today.getMonth(), today.getDate()), ModifiersUtils.getModifiersForDay(today, _this.props.modifiers), e); } }; var currentMonth = _this.getCurrentMonthFromProps(props); _this.state = { currentMonth: currentMonth }; return _this; } _createClass(DayPicker, [{ key: 'componentDidUpdate', value: function componentDidUpdate(prevProps) { // Changing the `month` props means changing the current displayed month if (prevProps.month !== this.props.month && !DateUtils.isSameMonth(prevProps.month, this.props.month)) { var currentMonth = this.getCurrentMonthFromProps(this.props); // eslint-disable-next-line react/no-did-update-set-state this.setState({ currentMonth: currentMonth }); } } }, { key: 'getCurrentMonthFromProps', /** * Return the month to be shown in the calendar based on the component props. * * @param {Object} props * @returns Date * @memberof DayPicker * @private */ value: function getCurrentMonthFromProps(props) { var initialMonth = Helpers.startOfMonth(props.month || props.initialMonth || new Date()); var currentMonth = initialMonth; if (props.pagedNavigation && props.numberOfMonths > 1 && props.fromMonth) { var fromMonth = Helpers.startOfMonth(props.fromMonth); var diffInMonths = Helpers.getMonthsDiff(fromMonth, currentMonth); currentMonth = DateUtils.addMonths(fromMonth, Math.floor(diffInMonths / props.numberOfMonths) * props.numberOfMonths); } else if (props.toMonth && props.numberOfMonths > 1 && Helpers.getMonthsDiff(currentMonth, props.toMonth) <= 0) { currentMonth = DateUtils.addMonths(Helpers.startOfMonth(props.toMonth), 1 - this.props.numberOfMonths); } return currentMonth; } }, { key: 'getNextNavigableMonth', value: function getNextNavigableMonth() { return DateUtils.addMonths(this.state.currentMonth, this.props.numberOfMonths); } }, { key: 'getPreviousNavigableMonth', value: function getPreviousNavigableMonth() { return DateUtils.addMonths(this.state.currentMonth, -1); } }, { key: 'allowPreviousMonth', value: function allowPreviousMonth() { var previousMonth = DateUtils.addMonths(this.state.currentMonth, -1); return this.allowMonth(previousMonth); } }, { key: 'allowNextMonth', value: function allowNextMonth() { var nextMonth = DateUtils.addMonths(this.state.currentMonth, this.props.numberOfMonths); return this.allowMonth(nextMonth); } }, { key: 'allowMonth', value: function allowMonth(d) { var _props = this.props, fromMonth = _props.fromMonth, toMonth = _props.toMonth, canChangeMonth = _props.canChangeMonth; if (!canChangeMonth || fromMonth && Helpers.getMonthsDiff(fromMonth, d) < 0 || toMonth && Helpers.getMonthsDiff(toMonth, d) > 0) { return false; } return true; } }, { key: 'allowYearChange', value: function allowYearChange() { return this.props.canChangeMonth; } }, { key: 'showMonth', value: function showMonth(d, callback) { var _this2 = this; if (!this.allowMonth(d)) { return; } this.setState({ currentMonth: Helpers.startOfMonth(d) }, function () { if (callback) { callback(); } if (_this2.props.onMonthChange) { _this2.props.onMonthChange(_this2.state.currentMonth); } }); } }, { key: 'showNextYear', value: function showNextYear() { if (!this.allowYearChange()) { return; } var nextMonth = DateUtils.addMonths(this.state.currentMonth, 12); this.showMonth(nextMonth); } }, { key: 'showPreviousYear', value: function showPreviousYear() { if (!this.allowYearChange()) { return; } var nextMonth = DateUtils.addMonths(this.state.currentMonth, -12); this.showMonth(nextMonth); } }, { key: 'focus', value: function focus() { this.wrapper.focus(); } }, { key: 'focusFirstDayOfMonth', value: function focusFirstDayOfMonth() { Helpers.getDayNodes(this.dayPicker, this.props.classNames)[0].focus(); } }, { key: 'focusLastDayOfMonth', value: function focusLastDayOfMonth() { var dayNodes = Helpers.getDayNodes(this.dayPicker, this.props.classNames); dayNodes[dayNodes.length - 1].focus(); } }, { key: 'focusPreviousDay', value: function focusPreviousDay(dayNode) { var _this3 = this; var dayNodes = Helpers.getDayNodes(this.dayPicker, this.props.classNames); var dayNodeIndex = Helpers.nodeListToArray(dayNodes).indexOf(dayNode); if (dayNodeIndex === -1) return; if (dayNodeIndex === 0) { this.showPreviousMonth(function () { return _this3.focusLastDayOfMonth(); }); } else { dayNodes[dayNodeIndex - 1].focus(); } } }, { key: 'focusNextDay', value: function focusNextDay(dayNode) { var _this4 = this; var dayNodes = Helpers.getDayNodes(this.dayPicker, this.props.classNames); var dayNodeIndex = Helpers.nodeListToArray(dayNodes).indexOf(dayNode); if (dayNodeIndex === -1) return; if (dayNodeIndex === dayNodes.length - 1) { this.showNextMonth(function () { return _this4.focusFirstDayOfMonth(); }); } else { dayNodes[dayNodeIndex + 1].focus(); } } }, { key: 'focusNextWeek', value: function focusNextWeek(dayNode) { var _this5 = this; var dayNodes = Helpers.getDayNodes(this.dayPicker, this.props.classNames); var dayNodeIndex = Helpers.nodeListToArray(dayNodes).indexOf(dayNode); var isInLastWeekOfMonth = dayNodeIndex > dayNodes.length - 8; if (isInLastWeekOfMonth) { this.showNextMonth(function () { var daysAfterIndex = dayNodes.length - dayNodeIndex; var nextMonthDayNodeIndex = 7 - daysAfterIndex; Helpers.getDayNodes(_this5.dayPicker, _this5.props.classNames)[nextMonthDayNodeIndex].focus(); }); } else { dayNodes[dayNodeIndex + 7].focus(); } } }, { key: 'focusPreviousWeek', value: function focusPreviousWeek(dayNode) { var _this6 = this; var dayNodes = Helpers.getDayNodes(this.dayPicker, this.props.classNames); var dayNodeIndex = Helpers.nodeListToArray(dayNodes).indexOf(dayNode); var isInFirstWeekOfMonth = dayNodeIndex <= 6; if (isInFirstWeekOfMonth) { this.showPreviousMonth(function () { var previousMonthDayNodes = Helpers.getDayNodes(_this6.dayPicker, _this6.props.classNames); var startOfLastWeekOfMonth = previousMonthDayNodes.length - 7; var previousMonthDayNodeIndex = startOfLastWeekOfMonth + dayNodeIndex; previousMonthDayNodes[previousMonthDayNodeIndex].focus(); }); } else { dayNodes[dayNodeIndex - 7].focus(); } } // Event handlers }, { key: 'handleOutsideDayClick', value: function handleOutsideDayClick(day) { var currentMonth = this.state.currentMonth; var numberOfMonths = this.props.numberOfMonths; var diffInMonths = Helpers.getMonthsDiff(currentMonth, day); if (diffInMonths > 0 && diffInMonths >= numberOfMonths) { this.showNextMonth(); } else if (diffInMonths < 0) { this.showPreviousMonth(); } } }, { key: 'renderNavbar', value: function renderNavbar() { var _props2 = this.props, labels = _props2.labels, locale = _props2.locale, localeUtils = _props2.localeUtils, canChangeMonth = _props2.canChangeMonth, navbarElement = _props2.navbarElement, attributes = _objectWithoutProperties(_props2, ['labels', 'locale', 'localeUtils', 'canChangeMonth', 'navbarElement']); if (!canChangeMonth) return null; var props = { month: this.state.currentMonth, classNames: this.props.classNames, className: this.props.classNames.navBar, nextMonth: this.getNextNavigableMonth(), previousMonth: this.getPreviousNavigableMonth(), showPreviousButton: this.allowPreviousMonth(), showNextButton: this.allowNextMonth(), onNextClick: this.showNextMonth, onPreviousClick: this.showPreviousMonth, dir: attributes.dir, labels: labels, locale: locale, localeUtils: localeUtils }; return _react2.default.isValidElement(navbarElement) ? _react2.default.cloneElement(navbarElement, props) : _react2.default.createElement(navbarElement, props); } }, { key: 'renderMonths', value: function renderMonths() { var months = []; var firstDayOfWeek = Helpers.getFirstDayOfWeekFromProps(this.props); for (var i = 0; i < this.props.numberOfMonths; i += 1) { var month = DateUtils.addMonths(this.state.currentMonth, i); months.push(_react2.default.createElement(_Month2.default, _extends({ key: i }, this.props, { month: month, firstDayOfWeek: firstDayOfWeek, onDayKeyDown: this.handleDayKeyDown, onDayClick: this.handleDayClick }))); } if (this.props.reverseMonths) { months.reverse(); } return months; } }, { key: 'renderFooter', value: function renderFooter() { if (this.props.todayButton) { return _react2.default.createElement( 'div', { className: this.props.classNames.footer }, this.renderTodayButton() ); } return null; } }, { key: 'renderTodayButton', value: function renderTodayButton() { return _react2.default.createElement( 'button', { type: 'button', tabIndex: 0, className: this.props.classNames.todayButton, 'aria-label': this.props.todayButton, onClick: this.handleTodayButtonClick }, this.props.todayButton ); } }, { key: 'render', value: function render() { var _this7 = this; var className = this.props.classNames.container; if (!this.props.onDayClick) { className = className + ' ' + this.props.classNames.interactionDisabled; } if (this.props.className) { className = className + ' ' + this.props.className; } return _react2.default.createElement( 'div', _extends({}, this.props.containerProps, { className: className, ref: function ref(el) { return _this7.dayPicker = el; }, lang: this.props.locale }), _react2.default.createElement( 'div', { className: this.props.classNames.wrapper, ref: function ref(el) { return _this7.wrapper = el; }, tabIndex: this.props.canChangeMonth && typeof this.props.tabIndex !== 'undefined' ? this.props.tabIndex : -1, onKeyDown: this.handleKeyDown, onFocus: this.props.onFocus, onBlur: this.props.onBlur }, this.renderNavbar(), _react2.default.createElement( 'div', { className: this.props.classNames.months }, this.renderMonths() ), this.renderFooter() ) ); } }]); return DayPicker; }(_react.Component); DayPicker.propTypes = { // Rendering months initialMonth: _propTypes2.default.instanceOf(Date), month: _propTypes2.default.instanceOf(Date), numberOfMonths: _propTypes2.default.number, fromMonth: _propTypes2.default.instanceOf(Date), toMonth: _propTypes2.default.instanceOf(Date), canChangeMonth: _propTypes2.default.bool, reverseMonths: _propTypes2.default.bool, pagedNavigation: _propTypes2.default.bool, todayButton: _propTypes2.default.string, showWeekNumbers: _propTypes2.default.bool, showWeekDays: _propTypes2.default.bool, // Modifiers selectedDays: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.func, _propTypes2.default.array]), disabledDays: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.func, _propTypes2.default.array]), modifiers: _propTypes2.default.object, modifiersStyles: _propTypes2.default.object, // Localization dir: _propTypes2.default.string, firstDayOfWeek: _propTypes2.default.oneOf([0, 1, 2, 3, 4, 5, 6]), labels: _propTypes2.default.shape({ nextMonth: _propTypes2.default.string.isRequired, previousMonth: _propTypes2.default.string.isRequired }), locale: _propTypes2.default.string, localeUtils: _propTypes2.default.shape({ formatMonthTitle: _propTypes2.default.func, formatWeekdayShort: _propTypes2.default.func, formatWeekdayLong: _propTypes2.default.func, getFirstDayOfWeek: _propTypes2.default.func }), months: _propTypes2.default.arrayOf(_propTypes2.default.string), weekdaysLong: _propTypes2.default.arrayOf(_propTypes2.default.string), weekdaysShort: _propTypes2.default.arrayOf(_propTypes2.default.string), // Customization showOutsideDays: _propTypes2.default.bool, enableOutsideDaysClick: _propTypes2.default.bool, fixedWeeks: _propTypes2.default.bool, // CSS and HTML classNames: _propTypes2.default.shape({ body: _propTypes2.default.string, container: _propTypes2.default.string, day: _propTypes2.default.string.isRequired, disabled: _propTypes2.default.string.isRequired, footer: _propTypes2.default.string, interactionDisabled: _propTypes2.default.string, months: _propTypes2.default.string, month: _propTypes2.default.string, navBar: _propTypes2.default.string, outside: _propTypes2.default.string.isRequired, selected: _propTypes2.default.string.isRequired, today: _propTypes2.default.string.isRequired, todayButton: _propTypes2.default.string, week: _propTypes2.default.string, wrapper: _propTypes2.default.string }), className: _propTypes2.default.string, containerProps: _propTypes2.default.object, tabIndex: _propTypes2.default.number, // Custom elements renderDay: _propTypes2.default.func, renderWeek: _propTypes2.default.func, weekdayElement: _propTypes2.default.oneOfType([_propTypes2.default.element, _propTypes2.default.func, _propTypes2.default.instanceOf(_react.Component)]), navbarElement: _propTypes2.default.oneOfType([_propTypes2.default.element, _propTypes2.default.func, _propTypes2.default.instanceOf(_react.Component)]), captionElement: _propTypes2.default.oneOfType([_propTypes2.default.element, _propTypes2.default.func, _propTypes2.default.instanceOf(_react.Component)]), // Events onBlur: _propTypes2.default.func, onFocus: _propTypes2.default.func, onKeyDown: _propTypes2.default.func, onDayClick: _propTypes2.default.func, onDayKeyDown: _propTypes2.default.func, onDayMouseEnter: _propTypes2.default.func, onDayMouseLeave: _propTypes2.default.func, onDayMouseDown: _propTypes2.default.func, onDayMouseUp: _propTypes2.default.func, onDayTouchStart: _propTypes2.default.func, onDayTouchEnd: _propTypes2.default.func, onDayFocus: _propTypes2.default.func, onMonthChange: _propTypes2.default.func, onCaptionClick: _propTypes2.default.func, onWeekClick: _propTypes2.default.func, onTodayButtonClick: _propTypes2.default.func }; DayPicker.defaultProps = { classNames: _classNames2.default, tabIndex: 0, numberOfMonths: 1, labels: { previousMonth: 'Previous Month', nextMonth: 'Next Month' }, locale: 'en', localeUtils: LocaleUtils, showOutsideDays: false, enableOutsideDaysClick: true, fixedWeeks: false, canChangeMonth: true, reverseMonths: false, pagedNavigation: false, showWeekNumbers: false, showWeekDays: true, renderDay: function renderDay(day) { return day.getDate(); }, renderWeek: function renderWeek(weekNumber) { return weekNumber; }, weekdayElement: _react2.default.createElement(_Weekday2.default, null), navbarElement: _react2.default.createElement(_Navbar2.default, { classNames: _classNames2.default }), captionElement: _react2.default.createElement(_Caption2.default, { classNames: _classNames2.default }) }; DayPicker.VERSION = '7.4.8'; DayPicker.DateUtils = DateUtils; DayPicker.LocaleUtils = LocaleUtils; DayPicker.ModifiersUtils = ModifiersUtils; exports.DateUtils = DateUtils; exports.LocaleUtils = LocaleUtils; exports.ModifiersUtils = ModifiersUtils; exports.default = DayPicker; //# sourceMappingURL=DayPicker.js.map