UNPKG

react-day-picker

Version:

Flexible date picker component for React

224 lines (201 loc) 6.82 kB
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import Weekdays from './Weekdays'; import Day from './Day'; import { ENTER } from './keys'; import * as ModifiersUtils from './ModifiersUtils'; import * as Helpers from './Helpers'; import * as DateUtils from './DateUtils'; export default class Month extends Component { static propTypes = { classNames: PropTypes.shape({ body: PropTypes.string.isRequired, month: PropTypes.string.isRequired, outside: PropTypes.string.isRequired, today: PropTypes.string.isRequired, week: PropTypes.string.isRequired, weekNumber: PropTypes.string.isRequired, disabled: PropTypes.string.isRequired, selected: PropTypes.string.isRequired, }).isRequired, tabIndex: PropTypes.number, month: PropTypes.instanceOf(Date).isRequired, months: PropTypes.arrayOf(PropTypes.string), modifiersStyles: PropTypes.object, showWeekDays: PropTypes.bool, showOutsideDays: PropTypes.bool, renderDay: PropTypes.func.isRequired, renderWeek: PropTypes.func.isRequired, captionElement: PropTypes.oneOfType([ PropTypes.element, PropTypes.func, PropTypes.instanceOf(React.Component), ]).isRequired, weekdayElement: PropTypes.oneOfType([ PropTypes.element, PropTypes.func, PropTypes.instanceOf(React.Component), ]), fixedWeeks: PropTypes.bool, showWeekNumbers: PropTypes.bool, locale: PropTypes.string.isRequired, localeUtils: PropTypes.object.isRequired, weekdaysLong: PropTypes.arrayOf(PropTypes.string), weekdaysShort: PropTypes.arrayOf(PropTypes.string), firstDayOfWeek: PropTypes.number.isRequired, onCaptionClick: PropTypes.func, onDayClick: PropTypes.func, onDayFocus: PropTypes.func, onDayKeyDown: PropTypes.func, onDayMouseEnter: PropTypes.func, onDayMouseLeave: PropTypes.func, onDayMouseDown: PropTypes.func, onDayMouseUp: PropTypes.func, onDayTouchEnd: PropTypes.func, onDayTouchStart: PropTypes.func, onWeekClick: PropTypes.func, }; renderDay = day => { const monthNumber = this.props.month.getMonth(); const propModifiers = Helpers.getModifiersFromProps(this.props); const dayModifiers = ModifiersUtils.getModifiersForDay(day, propModifiers); if ( DateUtils.isSameDay(day, new Date()) && !Object.prototype.hasOwnProperty.call( propModifiers, this.props.classNames.today ) ) { dayModifiers.push(this.props.classNames.today); } if (day.getMonth() !== monthNumber) { dayModifiers.push(this.props.classNames.outside); } const isOutside = day.getMonth() !== monthNumber; let tabIndex = -1; // Focus on the first day of the month if (this.props.onDayClick && !isOutside && day.getDate() === 1) { tabIndex = this.props.tabIndex; // eslint-disable-line prefer-destructuring } const key = `${day.getFullYear()}${day.getMonth()}${day.getDate()}`; const modifiers = {}; dayModifiers.forEach(modifier => { modifiers[modifier] = true; }); return ( <Day key={`${isOutside ? 'outside-' : ''}${key}`} classNames={this.props.classNames} day={day} modifiers={modifiers} modifiersStyles={this.props.modifiersStyles} empty={ isOutside && !this.props.showOutsideDays && !this.props.fixedWeeks } tabIndex={tabIndex} ariaLabel={this.props.localeUtils.formatDay(day, this.props.locale)} ariaDisabled={ isOutside || dayModifiers.indexOf(this.props.classNames.disabled) > -1 } ariaSelected={dayModifiers.indexOf(this.props.classNames.selected) > -1} onClick={this.props.onDayClick} onFocus={this.props.onDayFocus} onKeyDown={this.props.onDayKeyDown} onMouseEnter={this.props.onDayMouseEnter} onMouseLeave={this.props.onDayMouseLeave} onMouseDown={this.props.onDayMouseDown} onMouseUp={this.props.onDayMouseUp} onTouchEnd={this.props.onDayTouchEnd} onTouchStart={this.props.onDayTouchStart} > {this.props.renderDay(day, modifiers)} </Day> ); }; render() { const { classNames, month, months, fixedWeeks, captionElement, weekdayElement, locale, localeUtils, weekdaysLong, weekdaysShort, firstDayOfWeek, onCaptionClick, showWeekNumbers, showWeekDays, onWeekClick, } = this.props; const captionProps = { date: month, classNames, months, localeUtils, locale, onClick: onCaptionClick ? e => onCaptionClick(month, e) : undefined, }; const caption = React.isValidElement(captionElement) ? React.cloneElement(captionElement, captionProps) : React.createElement(captionElement, captionProps); const weeks = Helpers.getWeekArray(month, firstDayOfWeek, fixedWeeks); return ( <div className={classNames.month} role="grid"> {caption} {showWeekDays && ( <Weekdays classNames={classNames} weekdaysShort={weekdaysShort} weekdaysLong={weekdaysLong} firstDayOfWeek={firstDayOfWeek} showWeekNumbers={showWeekNumbers} locale={locale} localeUtils={localeUtils} weekdayElement={weekdayElement} /> )} <div className={classNames.body} role="rowgroup"> {weeks.map(week => { let weekNumber; if (showWeekNumbers) { weekNumber = DateUtils.getWeekNumber(week[6]); } return ( <div key={week[0].getTime()} className={classNames.week} role="row" > {showWeekNumbers && ( <div className={classNames.weekNumber} tabIndex={onWeekClick ? 0 : -1} role="gridcell" onClick={ onWeekClick ? e => onWeekClick(weekNumber, week, e) : undefined } onKeyUp={ onWeekClick ? e => e.keyCode === ENTER && onWeekClick(weekNumber, week, e) : undefined } > {this.props.renderWeek(weekNumber, week, month)} </div> )} {week.map(this.renderDay)} </div> ); })} </div> </div> ); } }