react-infinite-calendar-with-range
Version:
Infinite scrolling date-picker built with React, with localization, themes, keyboard support, and more.
837 lines (716 loc) • 28.9 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
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 _classnames = require('classnames');
var _classnames2 = _interopRequireDefault(_classnames);
var _moment = require('moment');
var _moment2 = _interopRequireDefault(_moment);
var _debounce = require('lodash/debounce');
var _debounce2 = _interopRequireDefault(_debounce);
var _range = require('lodash/range');
var _range2 = _interopRequireDefault(_range);
var _utils = require('./utils');
var _locale = require('./locale');
var _locale2 = _interopRequireDefault(_locale);
var _theme = require('./theme');
var _theme2 = _interopRequireDefault(_theme);
var _Today = require('./Today');
var _Today2 = _interopRequireDefault(_Today);
var _Header = require('./Header');
var _Header2 = _interopRequireDefault(_Header);
var _List = require('./List');
var _List2 = _interopRequireDefault(_List);
var _Weekdays = require('./Weekdays');
var _Weekdays2 = _interopRequireDefault(_Weekdays);
var _Years = require('./Years');
var _Years2 = _interopRequireDefault(_Years);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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 _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 containerStyle = {
'root': 'Cal__Container__root',
'landscape': 'Cal__Container__landscape',
'wrapper': 'Cal__Container__wrapper',
'listWrapper': 'Cal__Container__listWrapper'
};
var dayStyle = {
'root': 'Cal__Day__root',
'enabled': 'Cal__Day__enabled',
'highlighted': 'Cal__Day__highlighted',
'today': 'Cal__Day__today',
'disabled': 'Cal__Day__disabled',
'badge': 'Cal__Day__badge',
'selected': 'Cal__Day__selected',
'month': 'Cal__Day__month',
'year': 'Cal__Day__year',
'selection': 'Cal__Day__selection',
'day': 'Cal__Day__day',
'selectionStart': 'Cal__Day__selectionStart',
'selectionEnd': 'Cal__Day__selectionEnd',
'selectionBetween': 'Cal__Day__selectionBetween',
'badge_overdue': 'Cal__Day__badge_overdue'
};
var style = {
container: containerStyle,
day: dayStyle
};
var InfiniteCalendar = function (_Component) {
_inherits(InfiniteCalendar, _Component);
function InfiniteCalendar(props) {
_classCallCheck(this, InfiniteCalendar);
// Initialize
var _this = _possibleConstructorReturn(this, (InfiniteCalendar.__proto__ || Object.getPrototypeOf(InfiniteCalendar)).call(this));
_initialiseProps.call(_this);
_this.updateLocale(props.locale);
_this.updateYears(props);
var selectedDate = props.selectedDate;
var rangeSelectionEndDate = props.rangeSelectionEndDate;
if (rangeSelectionEndDate === false) {
rangeSelectionEndDate = selectedDate;
} else if (selectedDate === false) {
rangeSelectionEndDate = false;
} else if (selectedDate > rangeSelectionEndDate) {
var tmp = selectedDate;
selectedDate = rangeSelectionEndDate;
rangeSelectionEndDate = tmp;
}
_this.state = {
selectedDate: _this.parseSelectedDate(selectedDate),
selectedHovering: null,
rangeSelectionEndDate: _this.parseSelectedDate(rangeSelectionEndDate),
dragging: 0, //direction -1 reverse 0 nodrag 1 forwards
touchBehavior: false,
display: props.display,
shouldHeaderAnimate: props.shouldHeaderAnimate
};
return _this;
}
_createClass(InfiniteCalendar, [{
key: 'componentDidMount',
value: function componentDidMount() {
var _props = this.props;
var autoFocus = _props.autoFocus;
var keyboardSupport = _props.keyboardSupport;
this.node = this.refs.node;
this.list = this.refs.List;
if (keyboardSupport && autoFocus) {
this.node.focus();
}
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(next) {
var _props2 = this.props;
var min = _props2.min;
var minDate = _props2.minDate;
var max = _props2.max;
var maxDate = _props2.maxDate;
var locale = _props2.locale;
var selectedDate = _props2.selectedDate;
var rangeSelectionEndDate = _props2.rangeSelectionEndDate;
var display = this.state.display;
if (next.locale !== locale) {
this.updateLocale(next.locale);
}
if (next.min !== min || next.minDate !== minDate || next.max !== max || next.maxDate !== maxDate) {
this.updateYears(next);
}
if (next.selectedDate !== selectedDate || next.rangeSelectionEndDate !== rangeSelectionEndDate) {
var nextSelectedDate = next.selectedDate;
var nextSelectedDateEnd = next.rangeSelectionEndDate;
if (nextSelectedDateEnd === false) {
nextSelectedDateEnd = nextSelectedDate;
} else if (nextSelectedDate === false) {
nextSelectedDateEnd = false;
} else if (nextSelectedDate > nextSelectedDateEnd) {
var tmp = nextSelectedDate;
nextSelectedDate = nextSelectedDateEnd;
nextSelectedDateEnd = tmp;
}
if (nextSelectedDate !== selectedDate) {
var parsed = this.parseSelectedDate(nextSelectedDate);
var parsedEnd = this.parseSelectedDate(nextSelectedDateEnd);
this.setState({
selectedDate: parsed,
rangeSelectionEndDate: parsedEnd
});
if (parsed) this.scrollToDate(parsed, -this.props.rowHeight);
} else if (nextSelectedDateEnd !== rangeSelectionEndDate) {
this.setState({
rangeSelectionEndDate: this.parseSelectedDate(nextSelectedDateEnd)
});
}
} else if (next.minDate !== minDate || next.maxDate !== maxDate) {
// Need to make sure the currently selected date is not before the new minDate or after maxDate
var _selectedDate = this.parseSelectedDate(this.state.selectedDate);
if (!_selectedDate.isSame(this.state.selectedDate, 'day')) {
this.setState({
selectedDate: _selectedDate
});
}
var _rangeSelectionEndDate = this.parseSelectedDate(this.state.rangeSelectionEndDate);
if (!_rangeSelectionEndDate.isSame(this.state.rangeSelectionEndDate, 'day')) {
this.setState({
rangeSelectionEndDate: _rangeSelectionEndDate
});
}
}
if (next.display !== display) {
this.setState({
display: next.display
});
}
}
}, {
key: 'parseSelectedDate',
value: function parseSelectedDate(selectedDate) {
if (selectedDate) {
selectedDate = (0, _moment2.default)(selectedDate);
// Selected Date should not be before min date or after max date
if (selectedDate.isBefore(this._minDate)) {
return this._minDate;
} else if (selectedDate.isAfter(this._maxDate)) {
return this._maxDate;
}
}
return selectedDate;
}
}, {
key: 'updateYears',
value: function updateYears() {
var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0];
var min = this._min = (0, _moment2.default)(props.min);
var max = this._max = (0, _moment2.default)(props.max);
this._minDate = (0, _moment2.default)(props.minDate);
this._maxDate = (0, _moment2.default)(props.maxDate);
this.years = (0, _range2.default)(min.year(), max.year() + 1).map(function (year) {
return (0, _utils.getMonthsForYear)(year, min, max);
});
this.months = [].concat.apply([], this.years);
}
}, {
key: 'updateLocale',
value: function updateLocale(locale) {
locale = this.getLocale(locale);
_moment2.default.updateLocale(locale.name, locale);
_moment2.default.locale(locale.name);
}
}, {
key: 'getDisabledDates',
value: function getDisabledDates(disabledDates) {
return disabledDates && disabledDates.map(function (date) {
return (0, _moment2.default)(date).format('YYYYMMDD');
});
}
}, {
key: 'getLocale',
value: function getLocale() {
var customLocale = arguments.length <= 0 || arguments[0] === undefined ? this.props.locale : arguments[0];
return Object.assign({}, _locale2.default, customLocale);
}
}, {
key: 'getTheme',
value: function getTheme() {
var customTheme = arguments.length <= 0 || arguments[0] === undefined ? this.props.theme : arguments[0];
return Object.assign({}, _theme2.default, customTheme);
}
}, {
key: 'clearHighlight',
value: function clearHighlight() {
if (this.highlightedEl) {
this.highlightedEl.classList.remove(style.day.highlighted);
this.highlightedEl = null;
}
}
}, {
key: 'render',
value: function render() {
var _props3 = this.props;
var className = _props3.className;
var disabledDays = _props3.disabledDays;
var height = _props3.height;
var hideYearsOnSelect = _props3.hideYearsOnSelect;
var keyboardSupport = _props3.keyboardSupport;
var layout = _props3.layout;
var overscanMonthCount = _props3.overscanMonthCount;
var badges = _props3.badges;
var min = _props3.min;
var minDate = _props3.minDate;
var max = _props3.max;
var maxDate = _props3.maxDate;
var showTodayHelper = _props3.showTodayHelper;
var showHeader = _props3.showHeader;
var tabIndex = _props3.tabIndex;
var width = _props3.width;
var other = _objectWithoutProperties(_props3, ['className', 'disabledDays', 'height', 'hideYearsOnSelect', 'keyboardSupport', 'layout', 'overscanMonthCount', 'badges', 'min', 'minDate', 'max', 'maxDate', 'showTodayHelper', 'showHeader', 'tabIndex', 'width']);
var disabledDates = this.getDisabledDates(this.props.disabledDates);
var locale = this.getLocale();
var theme = this.getTheme();
var _state = this.state;
var display = _state.display;
var isScrolling = _state.isScrolling;
var selectedDate = _state.selectedDate;
var dragging = _state.dragging;
var rangeSelectionEndDate = _state.rangeSelectionEndDate;
var selectedHovering = _state.selectedHovering;
var showToday = _state.showToday;
var shouldHeaderAnimate = _state.shouldHeaderAnimate;
var today = this.today = (0, _utils.parseDate)((0, _moment2.default)());
// Selected date should not be disabled
if (selectedDate && (disabledDates && disabledDates.indexOf(selectedDate.format('YYYYMMDD')) !== -1 || disabledDays && disabledDays.indexOf(selectedDate.day()) !== -1)) {
selectedDate = null;
}
return _react2.default.createElement(
'div',
{ tabIndex: tabIndex, onKeyDown: keyboardSupport && this.handleKeyDown, className: (0, _classnames2.default)(className, style.container.root, _defineProperty({}, style.container.landscape, layout == 'landscape')), style: { color: theme.textColor.default, width: width }, 'aria-label': 'Calendar', ref: 'node' },
showHeader && _react2.default.createElement(_Header2.default, { selectedDate: selectedDate, rangeSelectionEndDate: rangeSelectionEndDate, shouldHeaderAnimate: shouldHeaderAnimate, layout: layout, theme: theme, locale: locale, scrollToDate: this.scrollToDate, setDisplay: this.setDisplay, display: display }),
_react2.default.createElement(
'div',
{ className: style.container.wrapper },
_react2.default.createElement(_Weekdays2.default, { theme: theme }),
_react2.default.createElement(
'div',
{ className: style.container.listWrapper },
showTodayHelper && _react2.default.createElement(_Today2.default, { scrollToDate: this.scrollToDate, show: showToday, today: today, theme: theme, locale: locale }),
_react2.default.createElement(_List2.default, _extends({
ref: 'List'
}, other, {
width: width,
height: height,
selectedDate: (0, _utils.parseDate)(selectedDate),
dragging: dragging,
selectedHovering: (0, _utils.parseDate)(selectedHovering),
rangeSelectionEndDate: (0, _utils.parseDate)(rangeSelectionEndDate),
disabledDates: disabledDates,
disabledDays: disabledDays,
months: this.months,
onDaySelect: this.onDaySelect,
onDayDown: this.onDayDown,
onDayOver: this.onDayOver,
onDayUp: this.onDayUp,
badges: badges,
onTouchStart: this.onTouchStart,
onScroll: this.onScroll,
isScrolling: isScrolling,
today: today,
min: (0, _utils.parseDate)(min),
minDate: (0, _utils.parseDate)(minDate),
maxDate: (0, _utils.parseDate)(maxDate),
theme: theme,
locale: locale,
overscanMonthCount: overscanMonthCount
}))
),
display == 'years' && _react2.default.createElement(_Years2.default, {
ref: 'years',
width: width,
height: height,
onDaySelect: this.onDaySelect,
minDate: minDate,
maxDate: maxDate,
selectedDate: selectedDate,
theme: theme,
years: (0, _range2.default)((0, _moment2.default)(min).year(), (0, _moment2.default)(max).year() + 1),
setDisplay: this.setDisplay,
scrollToDate: this.scrollToDate,
hideYearsOnSelect: hideYearsOnSelect
})
)
);
}
}]);
return InfiniteCalendar;
}(_react.Component);
InfiniteCalendar.defaultProps = {
width: 400,
height: 500,
rowHeight: 56,
overscanMonthCount: 4,
todayHelperRowOffset: 4,
layout: 'portrait',
display: 'days',
badges: null,
selectedDate: new Date(),
endDate: new Date(),
min: { year: 1980, month: 0, day: 0 },
minDate: { year: 1980, month: 0, day: 0 },
max: { year: 2050, month: 11, day: 31 },
maxDate: { year: 2050, month: 11, day: 31 },
keyboardSupport: true,
autoFocus: true,
rangeSelection: false,
rangeSelectionBehavior: "hover",
rangeSelectionEndDate: false,
shouldHeaderAnimate: true,
showOverlay: true,
showTodayHelper: true,
showHeader: true,
tabIndex: 1,
locale: {},
theme: {},
hideYearsOnSelect: true
};
InfiniteCalendar.propTypes = {
selectedDate: _utils.validDate,
endDate: _utils.validDate,
min: _utils.validDate,
max: _utils.validDate,
minDate: _utils.validDate,
maxDate: _utils.validDate,
locale: _react.PropTypes.object,
theme: _react.PropTypes.object,
width: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.string]),
height: _react.PropTypes.number,
rowHeight: _react.PropTypes.number,
className: _react.PropTypes.string,
overscanMonthCount: _react.PropTypes.number,
todayHelperRowOffset: _react.PropTypes.number,
disabledDays: _react.PropTypes.arrayOf(_react.PropTypes.number),
disabledDates: _react.PropTypes.arrayOf(_utils.validDate),
beforeSelect: _react.PropTypes.func,
onSelect: _react.PropTypes.func,
afterSelect: _react.PropTypes.func,
onScroll: _react.PropTypes.func,
onScrollEnd: _react.PropTypes.func,
keyboardSupport: _react.PropTypes.bool,
autoFocus: _react.PropTypes.bool,
rangeSelection: _react.PropTypes.bool,
rangeSelectionBehavior: _react.PropTypes.string,
rangeSelectionEndDate: _utils.validDate,
onKeyDown: _react.PropTypes.func,
tabIndex: _react.PropTypes.number,
layout: _utils.validLayout,
display: _utils.validDisplay,
badges: _react.PropTypes.oneOfType([_react.PropTypes.object, _react.PropTypes.func]),
hideYearsOnSelect: _react.PropTypes.bool,
shouldHeaderAnimate: _react.PropTypes.bool,
showOverlay: _react.PropTypes.bool,
showTodayHelper: _react.PropTypes.bool,
showHeader: _react.PropTypes.bool
};
var _initialiseProps = function _initialiseProps() {
var _this2 = this;
this.onDaySelect = function (clickedDate, e) {
var _props4 = _this2.props;
var afterSelect = _props4.afterSelect;
var beforeSelect = _props4.beforeSelect;
var onSelect = _props4.onSelect;
var rangeSelection = _props4.rangeSelection;
var shouldHeaderAnimate = _props4.shouldHeaderAnimate;
var rangeSelectionBehavior = _props4.rangeSelectionBehavior;
var selectedDate = _this2.state.selectedDate;
var rangeSelectionEndDate = _this2.state.rangeSelectionEndDate;
var dragging = 0;
if (rangeSelection && (_this2.state.touchBehavior || rangeSelectionBehavior == "hover")) {
//If we are doing a range selection in the default "hover" mode (click+click instead of drag)
if (_this2.state.dragging == 0) {
selectedDate = clickedDate;
rangeSelectionEndDate = clickedDate;
dragging = 1;
} else {
if (clickedDate > selectedDate) {
rangeSelectionEndDate = clickedDate;
} else {
selectedDate = clickedDate;
}
}
} else {
selectedDate = clickedDate;
rangeSelectionEndDate = clickedDate;
if (_this2.state.selectedDate == selectedDate) return;
}
if (!beforeSelect || typeof beforeSelect == 'function' && beforeSelect(selectedDate, rangeSelectionEndDate)) {
if (typeof onSelect == 'function') {
onSelect(selectedDate, rangeSelectionEndDate, e);
}
_this2.setState({
selectedDate: selectedDate,
rangeSelectionEndDate: rangeSelectionEndDate,
dragging: dragging,
highlightedDate: selectedDate.clone()
}, function () {
_this2.clearHighlight();
if (typeof afterSelect == 'function') {
afterSelect(selectedDate, rangeSelectionEndDate);
}
});
}
};
this.onDayDown = function (selectedDate, e) {
var _props5 = _this2.props;
var afterSelect = _props5.afterSelect;
var beforeSelect = _props5.beforeSelect;
var onSelect = _props5.onSelect;
var rangeSelection = _props5.rangeSelection;
var rangeSelectionBehavior = _props5.rangeSelectionBehavior;
if (_this2.state.touchBehavior || !rangeSelection || rangeSelectionBehavior == "hover") return false;
//only continue if we are doing range selection in "drag" mode
if (!beforeSelect || typeof beforeSelect == 'function' && beforeSelect(selectedDate, null)) {
var dragging = 1;
var rangeSelectionEndDate = selectedDate;
var selectedHovering = null;
_this2.setState({
selectedDate: selectedDate,
rangeSelectionEndDate: rangeSelectionEndDate,
selectedHovering: selectedHovering,
dragging: dragging,
highlightedDate: selectedDate.clone()
});
}
return false;
};
this.onDayOver = function (selectedHovering, e) {
if (_this2.state.dragging !== 0 && !_this2.state.touchBehavior && _this2.props.rangeSelection) {
//enter here if we are in "drag" mode for range selection
var selectedDate = _this2.state.selectedDate;
var rangeSelectionEndDate = _this2.state.rangeSelectionEndDate;
var dragging = _this2.state.dragging;
if (dragging == 1) {
//dragging forwards
rangeSelectionEndDate = selectedHovering;
} else if (dragging == -1) {
//dragging backwards
selectedDate = selectedHovering;
}
if (selectedDate > rangeSelectionEndDate) {
//flip directions of dragging start to end (1) or end to start (-1)
dragging = -dragging;
var tmp = selectedDate;
selectedDate = rangeSelectionEndDate;
rangeSelectionEndDate = tmp;
}
_this2.setState({
selectedDate: selectedDate,
rangeSelectionEndDate: rangeSelectionEndDate,
selectedHovering: selectedHovering,
dragging: dragging
});
}
return false;
};
this.onDayUp = function (overDate, e) {
var _props6 = _this2.props;
var afterSelect = _props6.afterSelect;
var beforeSelect = _props6.beforeSelect;
var onSelect = _props6.onSelect;
var rangeSelection = _props6.rangeSelection;
var rangeSelectionBehavior = _props6.rangeSelectionBehavior;
if (_this2.state.dragging !== 0 && !_this2.state.touchBehavior && rangeSelectionBehavior == "drag" && rangeSelection) {
//enter here if we are doing the "drag" mode of range selection
var selectedDate = _this2.state.selectedDate;
var rangeSelectionEndDate = _this2.state.rangeSelectionEndDate;
var dragging = 0;
var selectedHovering = null;
if (_this2.state.dragging == 1) {
//dragging forwards (start to end)
rangeSelectionEndDate = overDate;
} else if (_this2.state.dragging == -1) {
//dragging backwards (end to start)
selectedDate = overDate;
}
if (selectedDate > rangeSelectionEndDate) {
//this should already be taken care of, but I leave in for defensive programming
var tmp = selectedDate;
selectedDate = rangeSelectionEndDate;
rangeSelectionEndDate = tmp;
}
var valid = true;
if (beforeSelect || typeof beforeSelect == 'function') valid = beforeSelect(selectedDate, rangeSelectionEndDate);
if (valid) {
if (typeof onSelect == 'function') {
onSelect(selectedDate, rangeSelectionEndDate, e);
}
_this2.setState({
selectedDate: selectedDate,
rangeSelectionEndDate: rangeSelectionEndDate,
selectedHovering: selectedHovering,
dragging: dragging
}, function () {
_this2.clearHighlight();
if (typeof afterSelect == 'function') {
afterSelect(selectedDate, rangeSelectionEndDate);
}
});
} else {
//released the mouse on an invalid date, so clear the whole range
selectedDate = null;
rangeSelectionEndDate = null;
_this2.setState({
selectedDate: selectedDate,
rangeSelectionEndDate: rangeSelectionEndDate,
selectedHovering: selectedHovering,
dragging: dragging
});
}
}
return false;
};
this.onTouchStart = function (startDate, e) {
_this2.setState({ touchBehavior: true });
};
this.getCurrentOffset = function () {
return _this2.scrollTop;
};
this.getDateOffset = function (date) {
return _this2.list && _this2.list.getDateOffset(date);
};
this.scrollTo = function (offset) {
return _this2.list && _this2.list.scrollTo(offset);
};
this.scrollToDate = function () {
var date = arguments.length <= 0 || arguments[0] === undefined ? (0, _moment2.default)() : arguments[0];
var offset = arguments[1];
return _this2.list && _this2.list.scrollToDate(date, offset);
};
this.getScrollSpeed = (0, _utils.getScrollSpeed)();
this.onScroll = function (_ref) {
var scrollTop = _ref.scrollTop;
var _props7 = _this2.props;
var onScroll = _props7.onScroll;
var showOverlay = _props7.showOverlay;
var showTodayHelper = _props7.showTodayHelper;
var isScrolling = _this2.state.isScrolling;
var scrollSpeed = _this2.scrollSpeed = Math.abs(_this2.getScrollSpeed(scrollTop));
_this2.scrollTop = scrollTop;
// We only want to display the months overlay if the user is rapidly scrolling
if (showOverlay && scrollSpeed >= 50 && !isScrolling) {
_this2.setState({
isScrolling: true
});
}
if (showTodayHelper) {
_this2.updateTodayHelperPosition(scrollSpeed);
}
if (typeof onScroll == 'function') {
onScroll(scrollTop);
}
_this2.onScrollEnd();
};
this.onScrollEnd = (0, _debounce2.default)(function () {
var _props8 = _this2.props;
var onScrollEnd = _props8.onScrollEnd;
var showTodayHelper = _props8.showTodayHelper;
var isScrolling = _this2.state.isScrolling;
if (isScrolling) _this2.setState({ isScrolling: false });
if (showTodayHelper) _this2.updateTodayHelperPosition(0);
if (typeof onScrollEnd == 'function') onScrollEnd(_this2.scrollTop);
}, 150);
this.updateTodayHelperPosition = function (scrollSpeed) {
var date = _this2.today.date;
if (!_this2.todayOffset) _this2.todayOffset = _this2.getDateOffset(date); //scrollTop offset of the month "today" is in
var scrollTop = _this2.scrollTop;
var showToday = _this2.state.showToday;
var _props9 = _this2.props;
var height = _props9.height;
var rowHeight = _props9.rowHeight;
var todayHelperRowOffset = _props9.todayHelperRowOffset;
var newState = void 0;
var dayOffset = Math.ceil((date.date() - 7 + (0, _moment2.default)(date).startOf("month").day()) / 7) * rowHeight; //offset of "today" within its month
if (scrollTop >= _this2.todayOffset + dayOffset + rowHeight * (todayHelperRowOffset + 1)) {
if (showToday !== 1) newState = 1; //today is above the fold
} else if (scrollTop + height <= _this2.todayOffset + dayOffset + rowHeight - rowHeight * (todayHelperRowOffset + 1)) {
if (showToday !== -1) newState = -1; //today is below the fold
} else if (showToday && scrollSpeed <= 1) {
newState = false;
}
if (scrollTop == 0) {
newState = false;
}
if (newState != null) {
_this2.setState({ showToday: newState });
}
};
this.handleKeyDown = function (e) {
var _props10 = _this2.props;
var maxDate = _props10.maxDate;
var minDate = _props10.minDate;
var onKeyDown = _props10.onKeyDown;
var _state2 = _this2.state;
var display = _state2.display;
var selectedDate = _state2.selectedDate;
var highlightedDate = _state2.highlightedDate;
var showToday = _state2.showToday;
var delta = 0;
if (typeof onKeyDown == 'function') {
onKeyDown(e);
}
if ([_utils.keyCodes.left, _utils.keyCodes.up, _utils.keyCodes.right, _utils.keyCodes.down].indexOf(e.keyCode) > -1 && typeof e.preventDefault == 'function') {
e.preventDefault();
}
if (!selectedDate) {
selectedDate = (0, _moment2.default)();
}
if (display == 'days') {
if (!highlightedDate) {
highlightedDate = selectedDate.clone();
_this2.setState({ highlightedDate: highlightedDate });
}
switch (e.keyCode) {
case _utils.keyCodes.enter:
_this2.onDaySelect((0, _moment2.default)(highlightedDate), e);
return;
case _utils.keyCodes.left:
delta = -1;
break;
case _utils.keyCodes.right:
delta = +1;
break;
case _utils.keyCodes.down:
delta = +7;
break;
case _utils.keyCodes.up:
delta = -7;
break;
}
if (delta) {
var rowHeight = _this2.props.rowHeight;
var newHighlightedDate = (0, _moment2.default)(highlightedDate).add(delta, 'days');
// Make sure the new highlighted date isn't before min / max
if (newHighlightedDate.isBefore(minDate)) {
newHighlightedDate = (0, _moment2.default)(minDate);
} else if (newHighlightedDate.isAfter(maxDate)) {
newHighlightedDate = (0, _moment2.default)(maxDate);
}
// Update the highlight indicator
_this2.clearHighlight();
// Scroll the view
if (!_this2.currentOffset) _this2.currentOffset = _this2.getCurrentOffset();
var currentOffset = _this2.currentOffset;
var monthOffset = _this2.getDateOffset(newHighlightedDate);
var navOffset = showToday ? 36 : 0;
var highlightedEl = _this2.highlightedEl = _this2.node.querySelector('[data-date=\'' + newHighlightedDate.format('YYYYMMDD') + '\']');
// Edge-case: if the user tries to use the keyboard when the new highlighted date isn't rendered because it's too far off-screen
// We need to scroll to the month of the new highlighted date so it renders
if (!highlightedEl) {
_this2.scrollTo(monthOffset - navOffset);
return;
}
highlightedEl.classList.add(style.day.highlighted);
var dateOffset = highlightedEl.offsetTop - rowHeight;
var newOffset = monthOffset + dateOffset;
if (currentOffset !== newOffset) {
_this2.currentOffset = newOffset;
_this2.scrollTo(newOffset - navOffset);
}
// Update the reference to the currently highlighted date
_this2.setState({
highlightedDate: newHighlightedDate
});
}
} else if (display == 'years' && _this2.refs.years) {
_this2.refs.years.handleKeyDown(e);
}
};
this.setDisplay = function (display) {
_this2.setState({ display: display });
};
};
exports.default = InfiniteCalendar;