react-dates-rtl
Version:
Based on react-dates by airbnb [with RTL support]
156 lines (132 loc) • 4.5 kB
JSX
/* eslint react/no-array-index-key: 0 */
import React from 'react';
import PropTypes from 'prop-types';
import shallowCompare from 'react-addons-shallow-compare';
import momentPropTypes from 'react-moment-proptypes';
import { forbidExtraProps, nonNegativeInteger } from 'airbnb-prop-types';
import moment from 'moment';
import cx from 'classnames';
import { CalendarDayPhrases } from '../defaultPhrases';
import getPhrasePropTypes from '../utils/getPhrasePropTypes';
import CalendarDay from './CalendarDay';
import getCalendarMonthWeeks from '../utils/getCalendarMonthWeeks';
import isSameDay from '../utils/isSameDay';
import ScrollableOrientationShape from '../shapes/ScrollableOrientationShape';
import {
HORIZONTAL_ORIENTATION,
VERTICAL_ORIENTATION,
VERTICAL_SCROLLABLE,
DAY_SIZE,
} from '../../constants';
const propTypes = forbidExtraProps({
month: momentPropTypes.momentObj,
isVisible: PropTypes.bool,
enableOutsideDays: PropTypes.bool,
modifiers: PropTypes.object,
orientation: ScrollableOrientationShape,
daySize: nonNegativeInteger,
onDayClick: PropTypes.func,
onDayMouseEnter: PropTypes.func,
onDayMouseLeave: PropTypes.func,
renderDay: PropTypes.func,
focusedDate: momentPropTypes.momentObj, // indicates focusable day
isFocused: PropTypes.bool, // indicates whether or not to move focus to focusable day
// i18n
monthFormat: PropTypes.string,
phrases: PropTypes.shape(getPhrasePropTypes(CalendarDayPhrases)),
isRTL: PropTypes.bool,
});
const defaultProps = {
month: moment(),
isVisible: true,
enableOutsideDays: false,
modifiers: {},
orientation: HORIZONTAL_ORIENTATION,
daySize: DAY_SIZE,
onDayClick() {},
onDayMouseEnter() {},
onDayMouseLeave() {},
renderDay: null,
focusedDate: null,
isFocused: false,
// i18n
monthFormat: 'MMMM YYYY', // english locale
phrases: CalendarDayPhrases,
isRTL: false,
};
export default class CalendarMonth extends React.Component {
constructor(props) {
super(props);
this.state = {
weeks: getCalendarMonthWeeks(props.month, props.enableOutsideDays),
};
}
componentWillReceiveProps(nextProps) {
const { month, enableOutsideDays } = nextProps;
if (!month.isSame(this.props.month)) {
this.setState({
weeks: getCalendarMonthWeeks(month, enableOutsideDays),
});
}
}
shouldComponentUpdate(nextProps, nextState) {
return shallowCompare(this, nextProps, nextState);
}
render() {
const {
month,
monthFormat,
orientation,
isVisible,
modifiers,
onDayClick,
onDayMouseEnter,
onDayMouseLeave,
renderDay,
daySize,
focusedDate,
isFocused,
phrases,
} = this.props;
const { weeks } = this.state;
const monthTitle = month.format(monthFormat);
const calendarMonthClasses = cx('CalendarMonth', {
'CalendarMonth--horizontal': orientation === HORIZONTAL_ORIENTATION,
'CalendarMonth--vertical': orientation === VERTICAL_ORIENTATION,
'CalendarMonth--vertical-scrollable': orientation === VERTICAL_SCROLLABLE,
});
return (
<div className={calendarMonthClasses} data-visible={isVisible}>
<table>
<caption className="CalendarMonth__caption js-CalendarMonth__caption">
<strong>{monthTitle}</strong>
</caption>
<tbody className="js-CalendarMonth__grid">
{weeks.map((week, i) => (
<tr key={i}>
{week.map((day, dayOfWeek) => (
<CalendarDay
day={day}
daySize={daySize}
isOutsideDay={!day || day.month() !== month.month()}
tabIndex={isVisible && isSameDay(day, focusedDate) ? 0 : -1}
isFocused={isFocused}
modifiers={modifiers}
key={dayOfWeek}
onDayMouseEnter={onDayMouseEnter}
onDayMouseLeave={onDayMouseLeave}
onDayClick={onDayClick}
renderDay={renderDay}
phrases={phrases}
/>
))}
</tr>
))}
</tbody>
</table>
</div>
);
}
}
CalendarMonth.propTypes = propTypes;
CalendarMonth.defaultProps = defaultProps;