react-dates
Version:
A responsive and accessible date range picker component built with React
1,154 lines (969 loc) • 38.3 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; };
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; }; }();
import _objectAssign from 'object.assign';
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
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 from 'react';
import PropTypes from 'prop-types';
import shallowCompare from 'react-addons-shallow-compare';
import { forbidExtraProps, nonNegativeInteger } from 'airbnb-prop-types';
import { css, withStyles, withStylesPropTypes } from 'react-with-styles';
import moment from 'moment';
import throttle from 'lodash/throttle';
import isTouchDevice from 'is-touch-device';
import { DayPickerPhrases } from '../defaultPhrases';
import getPhrasePropTypes from '../utils/getPhrasePropTypes';
import OutsideClickHandler from './OutsideClickHandler';
import CalendarMonthGrid from './CalendarMonthGrid';
import DayPickerNavigation from './DayPickerNavigation';
import DayPickerKeyboardShortcuts, { TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT } from './DayPickerKeyboardShortcuts';
import getCalendarMonthWidth from '../utils/getCalendarMonthWidth';
import getActiveElement from '../utils/getActiveElement';
import isDayVisible from '../utils/isDayVisible';
import ScrollableOrientationShape from '../shapes/ScrollableOrientationShape';
import DayOfWeekShape from '../shapes/DayOfWeekShape';
import { HORIZONTAL_ORIENTATION, VERTICAL_ORIENTATION, VERTICAL_SCROLLABLE, DAY_SIZE } from '../constants';
var MONTH_PADDING = 23;
var DAY_PICKER_PADDING = 9;
var PREV_TRANSITION = 'prev';
var NEXT_TRANSITION = 'next';
var propTypes = forbidExtraProps(_objectAssign({}, withStylesPropTypes, {
// calendar presentation props
enableOutsideDays: PropTypes.bool,
numberOfMonths: PropTypes.number,
orientation: ScrollableOrientationShape,
withPortal: PropTypes.bool,
onOutsideClick: PropTypes.func,
hidden: PropTypes.bool,
initialVisibleMonth: PropTypes.func,
firstDayOfWeek: DayOfWeekShape,
renderCalendarInfo: PropTypes.func,
hideKeyboardShortcutsPanel: PropTypes.bool,
daySize: nonNegativeInteger,
isRTL: PropTypes.bool,
verticalHeight: nonNegativeInteger,
// navigation props
navPrev: PropTypes.node,
navNext: PropTypes.node,
onPrevMonthClick: PropTypes.func,
onNextMonthClick: PropTypes.func,
onMultiplyScrollableMonths: PropTypes.func, // VERTICAL_SCROLLABLE daypickers only
// month props
renderMonth: PropTypes.func,
// day props
modifiers: PropTypes.object,
renderDay: PropTypes.func,
onDayClick: PropTypes.func,
onDayMouseEnter: PropTypes.func,
onDayMouseLeave: PropTypes.func,
// accessibility props
isFocused: PropTypes.bool,
getFirstFocusableDay: PropTypes.func,
onBlur: PropTypes.func,
showKeyboardShortcuts: PropTypes.bool,
// internationalization
monthFormat: PropTypes.string,
weekDayFormat: PropTypes.string,
phrases: PropTypes.shape(getPhrasePropTypes(DayPickerPhrases)),
dayAriaLabelFormat: PropTypes.string
}));
export var defaultProps = {
// calendar presentation props
enableOutsideDays: false,
numberOfMonths: 2,
orientation: HORIZONTAL_ORIENTATION,
withPortal: false,
onOutsideClick: function () {
function onOutsideClick() {}
return onOutsideClick;
}(),
hidden: false,
initialVisibleMonth: function () {
function initialVisibleMonth() {
return moment();
}
return initialVisibleMonth;
}(),
firstDayOfWeek: null,
renderCalendarInfo: null,
hideKeyboardShortcutsPanel: false,
daySize: DAY_SIZE,
isRTL: false,
verticalHeight: null,
// navigation props
navPrev: null,
navNext: null,
onPrevMonthClick: function () {
function onPrevMonthClick() {}
return onPrevMonthClick;
}(),
onNextMonthClick: function () {
function onNextMonthClick() {}
return onNextMonthClick;
}(),
onMultiplyScrollableMonths: function () {
function onMultiplyScrollableMonths() {}
return onMultiplyScrollableMonths;
}(),
// month props
renderMonth: null,
// day props
modifiers: {},
renderDay: null,
onDayClick: function () {
function onDayClick() {}
return onDayClick;
}(),
onDayMouseEnter: function () {
function onDayMouseEnter() {}
return onDayMouseEnter;
}(),
onDayMouseLeave: function () {
function onDayMouseLeave() {}
return onDayMouseLeave;
}(),
// accessibility props
isFocused: false,
getFirstFocusableDay: null,
onBlur: function () {
function onBlur() {}
return onBlur;
}(),
showKeyboardShortcuts: false,
// internationalization
monthFormat: 'MMMM YYYY',
weekDayFormat: 'dd',
phrases: DayPickerPhrases
};
var DayPicker = function (_React$Component) {
_inherits(DayPicker, _React$Component);
function DayPicker(props) {
_classCallCheck(this, DayPicker);
var _this = _possibleConstructorReturn(this, (DayPicker.__proto__ || Object.getPrototypeOf(DayPicker)).call(this, props));
var currentMonth = props.hidden ? moment() : props.initialVisibleMonth();
var focusedDate = currentMonth.clone().startOf('month');
if (props.getFirstFocusableDay) {
focusedDate = props.getFirstFocusableDay(currentMonth);
}
var translationValue = props.isRTL && _this.isHorizontal() ? -getCalendarMonthWidth(props.daySize) : 0;
_this.hasSetInitialVisibleMonth = !props.hidden;
_this.state = {
currentMonth: currentMonth,
monthTransition: null,
translationValue: translationValue,
scrollableMonthMultiple: 1,
calendarMonthWidth: getCalendarMonthWidth(props.daySize),
focusedDate: !props.hidden || props.isFocused ? focusedDate : null,
nextFocusedDate: null,
showKeyboardShortcuts: props.showKeyboardShortcuts,
onKeyboardShortcutsPanelClose: function () {
function onKeyboardShortcutsPanelClose() {}
return onKeyboardShortcutsPanelClose;
}(),
isTouchDevice: isTouchDevice(),
withMouseInteractions: true,
hasSetHeight: false
};
_this.calendarMonthHeights = [];
_this.calendarMonthGridHeight = 0;
_this.onKeyDown = _this.onKeyDown.bind(_this);
_this.onPrevMonthClick = _this.onPrevMonthClick.bind(_this);
_this.onNextMonthClick = _this.onNextMonthClick.bind(_this);
_this.multiplyScrollableMonths = _this.multiplyScrollableMonths.bind(_this);
_this.updateStateAfterMonthTransition = _this.updateStateAfterMonthTransition.bind(_this);
_this.openKeyboardShortcutsPanel = _this.openKeyboardShortcutsPanel.bind(_this);
_this.closeKeyboardShortcutsPanel = _this.closeKeyboardShortcutsPanel.bind(_this);
_this.setContainerRef = _this.setContainerRef.bind(_this);
_this.setTransitionContainerRef = _this.setTransitionContainerRef.bind(_this);
_this.setCalendarMonthHeights = _this.setCalendarMonthHeights.bind(_this);
return _this;
}
_createClass(DayPicker, [{
key: 'componentDidMount',
value: function () {
function componentDidMount() {
this.setState({ isTouchDevice: isTouchDevice() });
}
return componentDidMount;
}()
}, {
key: 'componentWillReceiveProps',
value: function () {
function componentWillReceiveProps(nextProps) {
var hidden = nextProps.hidden,
isFocused = nextProps.isFocused,
showKeyboardShortcuts = nextProps.showKeyboardShortcuts,
onBlur = nextProps.onBlur;
var currentMonth = this.state.currentMonth;
if (!hidden) {
if (!this.hasSetInitialVisibleMonth) {
this.hasSetInitialVisibleMonth = true;
this.setState({
currentMonth: nextProps.initialVisibleMonth()
});
}
}
if (nextProps.daySize !== this.props.daySize) {
this.setState({
calendarMonthWidth: getCalendarMonthWidth(nextProps.daySize)
});
}
if (isFocused !== this.props.isFocused) {
if (isFocused) {
var focusedDate = this.getFocusedDay(currentMonth);
var onKeyboardShortcutsPanelClose = this.state.onKeyboardShortcutsPanelClose;
if (nextProps.showKeyboardShortcuts) {
// the ? shortcut came from the input and we should return input there once it is close
onKeyboardShortcutsPanelClose = onBlur;
}
this.setState({
showKeyboardShortcuts: showKeyboardShortcuts,
onKeyboardShortcutsPanelClose: onKeyboardShortcutsPanelClose,
focusedDate: focusedDate,
withMouseInteractions: false
});
} else {
this.setState({ focusedDate: null });
}
}
}
return componentWillReceiveProps;
}()
}, {
key: 'shouldComponentUpdate',
value: function () {
function shouldComponentUpdate(nextProps, nextState) {
return shallowCompare(this, nextProps, nextState);
}
return shouldComponentUpdate;
}()
}, {
key: 'componentDidUpdate',
value: function () {
function componentDidUpdate(prevProps) {
var isFocused = this.props.isFocused;
var focusedDate = this.state.focusedDate;
if (!prevProps.isFocused && isFocused && !focusedDate) {
this.container.focus();
}
}
return componentDidUpdate;
}()
}, {
key: 'onKeyDown',
value: function () {
function onKeyDown(e) {
e.stopPropagation();
this.setState({ withMouseInteractions: false });
var _props = this.props,
onBlur = _props.onBlur,
isRTL = _props.isRTL;
var _state = this.state,
focusedDate = _state.focusedDate,
showKeyboardShortcuts = _state.showKeyboardShortcuts;
if (!focusedDate) return;
var newFocusedDate = focusedDate.clone();
var didTransitionMonth = false;
// focus might be anywhere when the keyboard shortcuts panel is opened so we want to
// return it to wherever it was before when the panel was opened
var activeElement = getActiveElement();
var onKeyboardShortcutsPanelClose = function () {
function onKeyboardShortcutsPanelClose() {
if (activeElement) activeElement.focus();
}
return onKeyboardShortcutsPanelClose;
}();
switch (e.key) {
case 'ArrowUp':
e.preventDefault();
newFocusedDate.subtract(1, 'week');
didTransitionMonth = this.maybeTransitionPrevMonth(newFocusedDate);
break;
case 'ArrowLeft':
e.preventDefault();
if (isRTL) {
newFocusedDate.add(1, 'day');
} else {
newFocusedDate.subtract(1, 'day');
}
didTransitionMonth = this.maybeTransitionPrevMonth(newFocusedDate);
break;
case 'Home':
e.preventDefault();
newFocusedDate.startOf('week');
didTransitionMonth = this.maybeTransitionPrevMonth(newFocusedDate);
break;
case 'PageUp':
e.preventDefault();
newFocusedDate.subtract(1, 'month');
didTransitionMonth = this.maybeTransitionPrevMonth(newFocusedDate);
break;
case 'ArrowDown':
e.preventDefault();
newFocusedDate.add(1, 'week');
didTransitionMonth = this.maybeTransitionNextMonth(newFocusedDate);
break;
case 'ArrowRight':
e.preventDefault();
if (isRTL) {
newFocusedDate.subtract(1, 'day');
} else {
newFocusedDate.add(1, 'day');
}
didTransitionMonth = this.maybeTransitionNextMonth(newFocusedDate);
break;
case 'End':
e.preventDefault();
newFocusedDate.endOf('week');
didTransitionMonth = this.maybeTransitionNextMonth(newFocusedDate);
break;
case 'PageDown':
e.preventDefault();
newFocusedDate.add(1, 'month');
didTransitionMonth = this.maybeTransitionNextMonth(newFocusedDate);
break;
case '?':
this.openKeyboardShortcutsPanel(onKeyboardShortcutsPanelClose);
break;
case 'Escape':
if (showKeyboardShortcuts) {
this.closeKeyboardShortcutsPanel();
} else {
onBlur();
}
break;
default:
break;
}
// If there was a month transition, do not update the focused date until the transition has
// completed. Otherwise, attempting to focus on a DOM node may interrupt the CSS animation. If
// didTransitionMonth is true, the focusedDate gets updated in #updateStateAfterMonthTransition
if (!didTransitionMonth) {
this.setState({
focusedDate: newFocusedDate
});
}
}
return onKeyDown;
}()
}, {
key: 'onPrevMonthClick',
value: function () {
function onPrevMonthClick(nextFocusedDate, e) {
var _props2 = this.props,
numberOfMonths = _props2.numberOfMonths,
isRTL = _props2.isRTL;
var calendarMonthWidth = this.state.calendarMonthWidth;
if (e) e.preventDefault();
var translationValue = this.isVertical() ? this.calendarMonthHeights[0] : calendarMonthWidth;
if (this.isHorizontal()) {
if (isRTL) {
translationValue = -2 * calendarMonthWidth;
}
var newMonthHeight = Math.max.apply(Math, [0].concat(_toConsumableArray(this.calendarMonthHeights.slice(0, numberOfMonths))));
this.adjustDayPickerHeight(newMonthHeight);
}
this.setState({
monthTransition: PREV_TRANSITION,
translationValue: translationValue,
focusedDate: null,
nextFocusedDate: nextFocusedDate
});
}
return onPrevMonthClick;
}()
}, {
key: 'onNextMonthClick',
value: function () {
function onNextMonthClick(nextFocusedDate, e) {
var isRTL = this.props.isRTL;
var calendarMonthWidth = this.state.calendarMonthWidth;
if (e) e.preventDefault();
var translationValue = this.isVertical() ? -this.calendarMonthHeights[1] : -calendarMonthWidth;
if (this.isHorizontal()) {
if (isRTL) {
translationValue = 0;
}
var newMonthHeight = Math.max.apply(Math, [0].concat(_toConsumableArray(this.calendarMonthHeights.slice(2))));
this.adjustDayPickerHeight(newMonthHeight);
}
this.setState({
monthTransition: NEXT_TRANSITION,
translationValue: translationValue,
focusedDate: null,
nextFocusedDate: nextFocusedDate
});
}
return onNextMonthClick;
}()
}, {
key: 'getFirstVisibleIndex',
value: function () {
function getFirstVisibleIndex() {
var orientation = this.props.orientation;
var monthTransition = this.state.monthTransition;
if (orientation === VERTICAL_SCROLLABLE) return 0;
var firstVisibleMonthIndex = 1;
if (monthTransition === PREV_TRANSITION) {
firstVisibleMonthIndex -= 1;
} else if (monthTransition === NEXT_TRANSITION) {
firstVisibleMonthIndex += 1;
}
return firstVisibleMonthIndex;
}
return getFirstVisibleIndex;
}()
}, {
key: 'getFocusedDay',
value: function () {
function getFocusedDay(newMonth) {
var _props3 = this.props,
getFirstFocusableDay = _props3.getFirstFocusableDay,
numberOfMonths = _props3.numberOfMonths;
var focusedDate = void 0;
if (getFirstFocusableDay) {
focusedDate = getFirstFocusableDay(newMonth);
}
if (newMonth && (!focusedDate || !isDayVisible(focusedDate, newMonth, numberOfMonths))) {
focusedDate = newMonth.clone().startOf('month');
}
return focusedDate;
}
return getFocusedDay;
}()
}, {
key: 'setCalendarMonthHeights',
value: function () {
function setCalendarMonthHeights(calendarMonthHeights) {
var numberOfMonths = this.props.numberOfMonths;
var firstVisibleMonthIndex = this.getFirstVisibleIndex();
var lastVisibleMonthIndex = firstVisibleMonthIndex + numberOfMonths;
this.calendarMonthHeights = calendarMonthHeights;
var visibleCalendarMonthHeights = calendarMonthHeights.filter(function (_, i) {
return i >= firstVisibleMonthIndex && i < lastVisibleMonthIndex;
});
this.calendarMonthGridHeight = Math.max.apply(Math, [0].concat(_toConsumableArray(visibleCalendarMonthHeights))) + MONTH_PADDING;
this.setState({ hasSetHeight: true });
}
return setCalendarMonthHeights;
}()
}, {
key: 'setContainerRef',
value: function () {
function setContainerRef(ref) {
this.container = ref;
}
return setContainerRef;
}()
}, {
key: 'setTransitionContainerRef',
value: function () {
function setTransitionContainerRef(ref) {
this.transitionContainer = ref;
}
return setTransitionContainerRef;
}()
}, {
key: 'maybeTransitionNextMonth',
value: function () {
function maybeTransitionNextMonth(newFocusedDate) {
var numberOfMonths = this.props.numberOfMonths;
var _state2 = this.state,
currentMonth = _state2.currentMonth,
focusedDate = _state2.focusedDate;
var newFocusedDateMonth = newFocusedDate.month();
var focusedDateMonth = focusedDate.month();
var isNewFocusedDateVisible = isDayVisible(newFocusedDate, currentMonth, numberOfMonths);
if (newFocusedDateMonth !== focusedDateMonth && !isNewFocusedDateVisible) {
this.onNextMonthClick(newFocusedDate);
return true;
}
return false;
}
return maybeTransitionNextMonth;
}()
}, {
key: 'maybeTransitionPrevMonth',
value: function () {
function maybeTransitionPrevMonth(newFocusedDate) {
var numberOfMonths = this.props.numberOfMonths;
var _state3 = this.state,
currentMonth = _state3.currentMonth,
focusedDate = _state3.focusedDate;
var newFocusedDateMonth = newFocusedDate.month();
var focusedDateMonth = focusedDate.month();
var isNewFocusedDateVisible = isDayVisible(newFocusedDate, currentMonth, numberOfMonths);
if (newFocusedDateMonth !== focusedDateMonth && !isNewFocusedDateVisible) {
this.onPrevMonthClick(newFocusedDate);
return true;
}
return false;
}
return maybeTransitionPrevMonth;
}()
}, {
key: 'multiplyScrollableMonths',
value: function () {
function multiplyScrollableMonths(e) {
var onMultiplyScrollableMonths = this.props.onMultiplyScrollableMonths;
if (e) e.preventDefault();
if (onMultiplyScrollableMonths) onMultiplyScrollableMonths(e);
this.setState({
scrollableMonthMultiple: this.state.scrollableMonthMultiple + 1
});
}
return multiplyScrollableMonths;
}()
}, {
key: 'isHorizontal',
value: function () {
function isHorizontal() {
return this.props.orientation === HORIZONTAL_ORIENTATION;
}
return isHorizontal;
}()
}, {
key: 'isVertical',
value: function () {
function isVertical() {
return this.props.orientation === VERTICAL_ORIENTATION || this.props.orientation === VERTICAL_SCROLLABLE;
}
return isVertical;
}()
}, {
key: 'updateStateAfterMonthTransition',
value: function () {
function updateStateAfterMonthTransition() {
var _props4 = this.props,
onPrevMonthClick = _props4.onPrevMonthClick,
onNextMonthClick = _props4.onNextMonthClick;
var _state4 = this.state,
currentMonth = _state4.currentMonth,
monthTransition = _state4.monthTransition,
focusedDate = _state4.focusedDate,
nextFocusedDate = _state4.nextFocusedDate,
withMouseInteractions = _state4.withMouseInteractions,
calendarMonthWidth = _state4.calendarMonthWidth;
if (!monthTransition) return;
var newMonth = currentMonth.clone();
if (monthTransition === PREV_TRANSITION) {
if (onPrevMonthClick) onPrevMonthClick();
newMonth.subtract(1, 'month');
} else if (monthTransition === NEXT_TRANSITION) {
if (onNextMonthClick) onNextMonthClick();
newMonth.add(1, 'month');
}
var newFocusedDate = null;
if (nextFocusedDate) {
newFocusedDate = nextFocusedDate;
} else if (!focusedDate && !withMouseInteractions) {
newFocusedDate = this.getFocusedDay(newMonth);
}
this.setState({
currentMonth: newMonth,
monthTransition: null,
translationValue: this.props.isRTL && this.isHorizontal() ? -calendarMonthWidth : 0,
nextFocusedDate: null,
focusedDate: newFocusedDate
}, function () {
// we don't want to focus on the relevant calendar day after a month transition
// if the user is navigating around using a mouse
if (withMouseInteractions) {
var activeElement = getActiveElement();
if (activeElement && activeElement !== document.body) {
activeElement.blur();
}
}
});
}
return updateStateAfterMonthTransition;
}()
}, {
key: 'adjustDayPickerHeight',
value: function () {
function adjustDayPickerHeight(newMonthHeight) {
var monthHeight = newMonthHeight + MONTH_PADDING;
if (monthHeight !== this.calendarMonthGridHeight) {
this.calendarMonthGridHeight = monthHeight;
this.transitionContainer.style.height = String(monthHeight) + 'px';
}
}
return adjustDayPickerHeight;
}()
}, {
key: 'openKeyboardShortcutsPanel',
value: function () {
function openKeyboardShortcutsPanel(onCloseCallBack) {
this.setState({
showKeyboardShortcuts: true,
onKeyboardShortcutsPanelClose: onCloseCallBack
});
}
return openKeyboardShortcutsPanel;
}()
}, {
key: 'closeKeyboardShortcutsPanel',
value: function () {
function closeKeyboardShortcutsPanel() {
var onKeyboardShortcutsPanelClose = this.state.onKeyboardShortcutsPanelClose;
if (onKeyboardShortcutsPanelClose) {
onKeyboardShortcutsPanelClose();
}
this.setState({
onKeyboardShortcutsPanelClose: null,
showKeyboardShortcuts: false
});
}
return closeKeyboardShortcutsPanel;
}()
}, {
key: 'renderNavigation',
value: function () {
function renderNavigation() {
var _this2 = this;
var _props5 = this.props,
navPrev = _props5.navPrev,
navNext = _props5.navNext,
orientation = _props5.orientation,
phrases = _props5.phrases,
isRTL = _props5.isRTL;
var onNextMonthClick = void 0;
if (orientation === VERTICAL_SCROLLABLE) {
onNextMonthClick = this.multiplyScrollableMonths;
} else {
onNextMonthClick = function () {
function onNextMonthClick(e) {
_this2.onNextMonthClick(null, e);
}
return onNextMonthClick;
}();
}
return React.createElement(DayPickerNavigation, {
onPrevMonthClick: function () {
function onPrevMonthClick(e) {
_this2.onPrevMonthClick(null, e);
}
return onPrevMonthClick;
}(),
onNextMonthClick: onNextMonthClick,
navPrev: navPrev,
navNext: navNext,
orientation: orientation,
phrases: phrases,
isRTL: isRTL
});
}
return renderNavigation;
}()
}, {
key: 'renderWeekHeader',
value: function () {
function renderWeekHeader(index) {
var _props6 = this.props,
daySize = _props6.daySize,
orientation = _props6.orientation,
weekDayFormat = _props6.weekDayFormat,
styles = _props6.styles;
var calendarMonthWidth = this.state.calendarMonthWidth;
var verticalScrollable = orientation === VERTICAL_SCROLLABLE;
var horizontalStyle = {
left: index * calendarMonthWidth
};
var verticalStyle = {
marginLeft: -calendarMonthWidth / 2
};
var weekHeaderStyle = {}; // no styles applied to the vertical-scrollable orientation
if (this.isHorizontal()) {
weekHeaderStyle = horizontalStyle;
} else if (this.isVertical() && !verticalScrollable) {
weekHeaderStyle = verticalStyle;
}
var firstDayOfWeek = this.props.firstDayOfWeek;
if (firstDayOfWeek == null) {
firstDayOfWeek = moment.localeData().firstDayOfWeek();
}
var header = [];
for (var i = 0; i < 7; i += 1) {
header.push(React.createElement(
'li',
_extends({ key: i }, css(styles.DayPicker_weekHeader_li, { width: daySize })),
React.createElement(
'small',
null,
moment().day((i + firstDayOfWeek) % 7).format(weekDayFormat)
)
));
}
return React.createElement(
'div',
_extends({}, css(styles.DayPicker_weekHeader, this.isVertical() && styles.DayPicker_weekHeader__vertical, verticalScrollable && styles.DayPicker_weekHeader__verticalScrollable, weekHeaderStyle), {
key: 'week-' + String(index)
}),
React.createElement(
'ul',
css(styles.DayPicker_weekHeader_ul),
header
)
);
}
return renderWeekHeader;
}()
}, {
key: 'render',
value: function () {
function render() {
var _this3 = this;
var _state5 = this.state,
calendarMonthWidth = _state5.calendarMonthWidth,
currentMonth = _state5.currentMonth,
monthTransition = _state5.monthTransition,
translationValue = _state5.translationValue,
scrollableMonthMultiple = _state5.scrollableMonthMultiple,
focusedDate = _state5.focusedDate,
showKeyboardShortcuts = _state5.showKeyboardShortcuts,
isTouch = _state5.isTouchDevice,
hasSetHeight = _state5.hasSetHeight;
var _props7 = this.props,
enableOutsideDays = _props7.enableOutsideDays,
numberOfMonths = _props7.numberOfMonths,
orientation = _props7.orientation,
modifiers = _props7.modifiers,
withPortal = _props7.withPortal,
onDayClick = _props7.onDayClick,
onDayMouseEnter = _props7.onDayMouseEnter,
onDayMouseLeave = _props7.onDayMouseLeave,
firstDayOfWeek = _props7.firstDayOfWeek,
renderMonth = _props7.renderMonth,
renderDay = _props7.renderDay,
renderCalendarInfo = _props7.renderCalendarInfo,
hideKeyboardShortcutsPanel = _props7.hideKeyboardShortcutsPanel,
onOutsideClick = _props7.onOutsideClick,
monthFormat = _props7.monthFormat,
daySize = _props7.daySize,
isFocused = _props7.isFocused,
isRTL = _props7.isRTL,
styles = _props7.styles,
phrases = _props7.phrases,
verticalHeight = _props7.verticalHeight,
dayAriaLabelFormat = _props7.dayAriaLabelFormat;
var numOfWeekHeaders = this.isVertical() ? 1 : numberOfMonths;
var weekHeaders = [];
for (var i = 0; i < numOfWeekHeaders; i += 1) {
weekHeaders.push(this.renderWeekHeader(i));
}
var verticalScrollable = this.props.orientation === VERTICAL_SCROLLABLE;
var firstVisibleMonthIndex = this.getFirstVisibleIndex();
var horizontalWidth = calendarMonthWidth * numberOfMonths + 2 * DAY_PICKER_PADDING;
var dayPickerStyle = {
width: this.isHorizontal() && horizontalWidth,
// These values are to center the datepicker (approximately) on the page
marginLeft: this.isHorizontal() && withPortal && -horizontalWidth / 2,
marginTop: this.isHorizontal() && withPortal && -calendarMonthWidth / 2
};
var height = void 0;
if (this.isHorizontal()) {
height = this.calendarMonthGridHeight;
} else if (this.isVertical() && !verticalScrollable && !withPortal) {
// If the user doesn't set a desired height,
// we default back to this kind of made-up value that generally looks good
height = verticalHeight || 1.75 * calendarMonthWidth;
}
var transitionContainerStyle = {
width: this.isHorizontal() && horizontalWidth,
height: height
};
var isCalendarMonthGridAnimating = monthTransition !== null;
var transformType = this.isVertical() ? 'translateY' : 'translateX';
var transformValue = transformType + '(' + String(translationValue) + 'px)';
var shouldFocusDate = !isCalendarMonthGridAnimating && isFocused;
var keyboardShortcutButtonLocation = BOTTOM_RIGHT;
if (this.isVertical()) {
keyboardShortcutButtonLocation = withPortal ? TOP_LEFT : TOP_RIGHT;
}
var isHorizontalAndAnimating = this.isHorizontal() && isCalendarMonthGridAnimating;
return React.createElement(
'div',
_extends({
role: 'application',
'aria-label': phrases.calendarLabel
}, css(styles.DayPicker, this.isHorizontal() && styles.DayPicker__horizontal, this.isVertical() && styles.DayPicker__vertical, verticalScrollable && styles.DayPicker__verticalScrollable, this.isHorizontal() && withPortal && styles.DayPicker_portal__horizontal, this.isVertical() && withPortal && styles.DayPicker_portal__vertical, dayPickerStyle, !hasSetHeight && styles.DayPicker__hidden)),
React.createElement(
OutsideClickHandler,
{ onOutsideClick: onOutsideClick },
React.createElement(
'div',
_extends({}, css(styles.DayPicker_weekHeaders, this.isHorizontal() && styles.DayPicker_weekHeaders__horizontal), {
'aria-hidden': 'true',
role: 'presentation'
}),
weekHeaders
),
React.createElement(
'div',
_extends({}, css(styles.DayPicker_focusRegion), {
ref: this.setContainerRef,
onClick: function () {
function onClick(e) {
e.stopPropagation();
}
return onClick;
}(),
onKeyDown: throttle(this.onKeyDown, 300),
onMouseUp: function () {
function onMouseUp() {
_this3.setState({ withMouseInteractions: true });
}
return onMouseUp;
}(),
role: 'region',
tabIndex: -1
}),
!verticalScrollable && this.renderNavigation(),
React.createElement(
'div',
_extends({}, css(styles.DayPicker_transitionContainer, isHorizontalAndAnimating && styles.DayPicker_transitionContainer__horizontal, this.isVertical() && styles.DayPicker_transitionContainer__vertical, verticalScrollable && styles.DayPicker_transitionContainer__verticalScrollable, transitionContainerStyle), {
ref: this.setTransitionContainerRef
}),
React.createElement(CalendarMonthGrid, {
setCalendarMonthHeights: this.setCalendarMonthHeights,
transformValue: transformValue,
enableOutsideDays: enableOutsideDays,
firstVisibleMonthIndex: firstVisibleMonthIndex,
initialMonth: currentMonth,
isAnimating: isCalendarMonthGridAnimating,
modifiers: modifiers,
orientation: orientation,
numberOfMonths: numberOfMonths * scrollableMonthMultiple,
onDayClick: onDayClick,
onDayMouseEnter: onDayMouseEnter,
onDayMouseLeave: onDayMouseLeave,
renderMonth: renderMonth,
renderDay: renderDay,
onMonthTransitionEnd: this.updateStateAfterMonthTransition,
monthFormat: monthFormat,
daySize: daySize,
firstDayOfWeek: firstDayOfWeek,
isFocused: shouldFocusDate,
focusedDate: focusedDate,
phrases: phrases,
isRTL: isRTL,
dayAriaLabelFormat: dayAriaLabelFormat
}),
verticalScrollable && this.renderNavigation()
),
!isTouch && !hideKeyboardShortcutsPanel && React.createElement(DayPickerKeyboardShortcuts, {
block: this.isVertical() && !withPortal,
buttonLocation: keyboardShortcutButtonLocation,
showKeyboardShortcutsPanel: showKeyboardShortcuts,
openKeyboardShortcutsPanel: this.openKeyboardShortcutsPanel,
closeKeyboardShortcutsPanel: this.closeKeyboardShortcutsPanel,
phrases: phrases
})
),
renderCalendarInfo && renderCalendarInfo()
)
);
}
return render;
}()
}]);
return DayPicker;
}(React.Component);
DayPicker.propTypes = propTypes;
DayPicker.defaultProps = defaultProps;
export { DayPicker as PureDayPicker };
export default withStyles(function (_ref) {
var _ref$reactDates = _ref.reactDates,
color = _ref$reactDates.color,
zIndex = _ref$reactDates.zIndex;
return {
DayPicker: {
background: color.background,
position: 'relative',
textAlign: 'left'
},
DayPicker__horizontal: {
background: color.background,
boxShadow: '0 2px 6px rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(0, 0, 0, 0.07)',
borderRadius: 3
},
DayPicker__verticalScrollable: {
height: '100%'
},
DayPicker__hidden: {
visibility: 'hidden'
},
DayPicker_portal__horizontal: {
boxShadow: 'none',
position: 'absolute',
left: '50%',
top: '50%'
},
DayPicker_portal__vertical: {
position: 'initial'
},
DayPicker_focusRegion: {
outline: 'none'
},
DayPicker_weekHeaders: {
position: 'relative'
},
DayPicker_weekHeaders__horizontal: {
marginLeft: 9
},
DayPicker_weekHeader: {
color: color.placeholderText,
position: 'absolute',
top: 62,
zIndex: zIndex + 2,
padding: '0 13px',
textAlign: 'left'
},
DayPicker_weekHeader__vertical: {
left: '50%'
},
DayPicker_weekHeader__verticalScrollable: {
top: 0,
display: 'table-row',
borderBottom: '1px solid ' + String(color.core.border),
background: color.background,
marginLeft: 0,
left: 0,
width: '100%',
textAlign: 'center'
},
DayPicker_weekHeader_ul: {
listStyle: 'none',
margin: '1px 0',
paddingLeft: 0,
paddingRight: 0
},
DayPicker_weekHeader_li: {
display: 'inline-block',
textAlign: 'center'
},
DayPicker_transitionContainer: {
position: 'relative',
overflow: 'hidden',
borderRadius: 3
},
DayPicker_transitionContainer__horizontal: {
transition: 'height 0.2s ease-in-out'
},
DayPicker_transitionContainer__vertical: {
width: '100%'
},
DayPicker_transitionContainer__verticalScrollable: {
paddingTop: 20,
height: '100%',
position: 'absolute',
top: 0,
bottom: 0,
right: 0,
left: 0,
overflowY: 'scroll'
}
};
})(DayPicker);