react-infinite-calendar
Version:
Infinite scrolling date-picker built with React, with localization, themes, keyboard support, and more.
239 lines (203 loc) • 9.09 kB
JavaScript
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; };
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; }
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import VirtualList from 'react-tiny-virtual-list';
import classNames from 'classnames';
import { emptyFn, getMonth, getWeek, getWeeksInMonth, animate } from '../utils';
import parse from 'date-fns/parse';
import startOfMonth from 'date-fns/start_of_month';
import Month from '../Month';
var styles = {
'root': 'Cal__MonthList__root',
'scrolling': 'Cal__MonthList__scrolling'
};
var AVERAGE_ROWS_PER_MONTH = 5;
var MonthList = function (_Component) {
_inherits(MonthList, _Component);
function MonthList() {
var _temp, _this, _ret;
_classCallCheck(this, MonthList);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = _possibleConstructorReturn(this, _Component.call.apply(_Component, [this].concat(args))), _this), _this.state = {
scrollTop: _this.getDateOffset(_this.props.scrollDate)
}, _this.cache = {}, _this.memoize = function (param) {
if (!this.cache[param]) {
var weekStartsOn = this.props.locale.weekStartsOn;
var _param$split = param.split(':'),
year = _param$split[0],
month = _param$split[1];
var result = getMonth(year, month, weekStartsOn);
this.cache[param] = result;
}
return this.cache[param];
}, _this.monthHeights = [], _this._getRef = function (instance) {
_this.VirtualList = instance;
}, _this.getMonthHeight = function (index) {
if (!_this.monthHeights[index]) {
var _this$props = _this.props,
weekStartsOn = _this$props.locale.weekStartsOn,
months = _this$props.months,
rowHeight = _this$props.rowHeight;
var _months$index = months[index],
month = _months$index.month,
year = _months$index.year;
var weeks = getWeeksInMonth(month, year, weekStartsOn, index === months.length - 1);
var height = weeks * rowHeight;
_this.monthHeights[index] = height;
}
return _this.monthHeights[index];
}, _this.scrollToDate = function (date) {
for (var _len2 = arguments.length, rest = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
rest[_key2 - 2] = arguments[_key2];
}
var _this2;
var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var offsetTop = _this.getDateOffset(date);
(_this2 = _this).scrollTo.apply(_this2, [offsetTop + offset].concat(rest));
}, _this.scrollTo = function () {
var scrollTop = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var shouldAnimate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var onScrollEnd = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : emptyFn;
var onComplete = function onComplete() {
return setTimeout(function () {
_this.scrollEl.style.overflowY = 'auto';
onScrollEnd();
});
};
// Interrupt iOS Momentum scroll
_this.scrollEl.style.overflowY = 'hidden';
if (shouldAnimate) {
/* eslint-disable sort-keys */
animate({
fromValue: _this.scrollEl.scrollTop,
toValue: scrollTop,
onUpdate: function onUpdate(scrollTop, callback) {
return _this.setState({ scrollTop: scrollTop }, callback);
},
onComplete: onComplete
});
} else {
window.requestAnimationFrame(function () {
_this.scrollEl.scrollTop = scrollTop;
onComplete();
});
}
}, _this.renderMonth = function (_ref) {
var index = _ref.index,
style = _ref.style;
var _this$props2 = _this.props,
DayComponent = _this$props2.DayComponent,
disabledDates = _this$props2.disabledDates,
disabledDays = _this$props2.disabledDays,
locale = _this$props2.locale,
maxDate = _this$props2.maxDate,
minDate = _this$props2.minDate,
months = _this$props2.months,
passThrough = _this$props2.passThrough,
rowHeight = _this$props2.rowHeight,
selected = _this$props2.selected,
showOverlay = _this$props2.showOverlay,
theme = _this$props2.theme,
today = _this$props2.today;
var _months$index2 = months[index],
month = _months$index2.month,
year = _months$index2.year;
var key = year + ':' + month;
var _this$memoize = _this.memoize(key),
date = _this$memoize.date,
rows = _this$memoize.rows;
return React.createElement(Month, _extends({
key: key,
selected: selected,
DayComponent: DayComponent,
monthDate: date,
disabledDates: disabledDates,
disabledDays: disabledDays,
maxDate: maxDate,
minDate: minDate,
rows: rows,
rowHeight: rowHeight,
isScrolling: false,
showOverlay: showOverlay,
today: today,
theme: theme,
style: style,
locale: locale,
passThrough: passThrough
}, passThrough.Month));
}, _temp), _possibleConstructorReturn(_this, _ret);
}
MonthList.prototype.componentDidMount = function componentDidMount() {
this.scrollEl = this.VirtualList.rootNode;
};
MonthList.prototype.componentWillReceiveProps = function componentWillReceiveProps(_ref2) {
var scrollDate = _ref2.scrollDate;
if (scrollDate !== this.props.scrollDate) {
this.setState({
scrollTop: this.getDateOffset(scrollDate)
});
}
};
MonthList.prototype.getDateOffset = function getDateOffset(date) {
var _props = this.props,
min = _props.min,
rowHeight = _props.rowHeight,
weekStartsOn = _props.locale.weekStartsOn,
height = _props.height;
var weeks = getWeek(startOfMonth(min), parse(date), weekStartsOn);
return weeks * rowHeight - (height - rowHeight / 2) / 2;
};
MonthList.prototype.render = function render() {
var _classNames;
var _props2 = this.props,
height = _props2.height,
isScrolling = _props2.isScrolling,
onScroll = _props2.onScroll,
overscanMonthCount = _props2.overscanMonthCount,
months = _props2.months,
rowHeight = _props2.rowHeight,
width = _props2.width;
var scrollTop = this.state.scrollTop;
return React.createElement(VirtualList, {
ref: this._getRef,
width: width,
height: height,
itemCount: months.length,
itemSize: this.getMonthHeight,
estimatedItemSize: rowHeight * AVERAGE_ROWS_PER_MONTH,
renderItem: this.renderMonth,
onScroll: onScroll,
scrollOffset: scrollTop,
className: classNames(styles.root, (_classNames = {}, _classNames[styles.scrolling] = isScrolling, _classNames)),
style: { lineHeight: rowHeight + 'px' },
overscanCount: overscanMonthCount
});
};
return MonthList;
}(Component);
export { MonthList as default };
process.env.NODE_ENV !== "production" ? MonthList.propTypes = {
disabledDates: PropTypes.arrayOf(PropTypes.string),
disabledDays: PropTypes.arrayOf(PropTypes.number),
height: PropTypes.number,
isScrolling: PropTypes.bool,
locale: PropTypes.object,
maxDate: PropTypes.instanceOf(Date),
min: PropTypes.instanceOf(Date),
minDate: PropTypes.instanceOf(Date),
months: PropTypes.arrayOf(PropTypes.object),
onDaySelect: PropTypes.func,
onScroll: PropTypes.func,
overscanMonthCount: PropTypes.number,
rowHeight: PropTypes.number,
selectedDate: PropTypes.instanceOf(Date),
showOverlay: PropTypes.bool,
theme: PropTypes.object,
today: PropTypes.instanceOf(Date),
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
} : void 0;