UNPKG

terra-date-picker

Version:

The terra-date-picker component provides users a way to enter or select a date from the date picker.

278 lines (259 loc) 8.22 kB
import React from 'react' import { FormattedMessage } from 'react-intl'; import PropTypes from 'prop-types' import classNames from 'classnames/bind' import Week from './week' import * as utils from './date_utils' import styles from './stylesheets/react_datepicker.module.scss' const cx = classNames.bind(styles); const FIXED_HEIGHT_STANDARD_WEEK_COUNT = 6 export default class Month extends React.Component { static propTypes = { /** * day Value Entered. */ day: PropTypes.object.isRequired, /** * A callback function for custom day class names. */ dayClassName: PropTypes.func, /** * Maximum Date value for a date range. */ endDate: PropTypes.object, /** * Array to store values of date that are disabled to pick . */ excludeDates: PropTypes.array, /** * A callback function to be executed to determine if a given date should be filtered. */ filterDate: PropTypes.func, /** * Specifies whether the height of calendar dom fixed or variable. */ fixedHeight: PropTypes.bool, /** * A callback function to format week number . */ formatWeekNumber: PropTypes.func, /** * Highlight range of dates with custom classes. */ highlightDates: PropTypes.instanceOf(WeakMap), /** * Show dates only in the given array. */ includeDates: PropTypes.array, /** * Timezone value to indicate in which timezone the date-time component is rendered. * The value provided should be a valid [timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) string, else will default to browser/local timezone. */ initialTimeZone: PropTypes.string, /** * Prop to show inline version of date picker component. */ inline: PropTypes.bool, /** * @private * Internationalization object with translation APIs. Provided by `injectIntl`. */ intl: PropTypes.shape({ formatMessage: PropTypes.func }), /** * @private * Name of locale data for different international formatting. */ locale: PropTypes.string, /** * Maximum value of date that can be selected by user. */ maxDate: PropTypes.object, /** * Minimum value of date that can be selected by user. */ minDate: PropTypes.object, /** * A callback function to execute when a day is selected. */ onDayClick: PropTypes.func, /** * A callback function to execute when the mouse cursor hovers over the day.. */ onDayMouseEnter: PropTypes.func, /** * A callback function to execute when the mouse cursor leaves the element. */ onMouseLeave: PropTypes.func, /** * A callback function to execute when a week is selected. */ onWeekSelect: PropTypes.func, /** * A callback function to execute when month component receives focus. * requires no parameter. */ onMonthFocus: PropTypes.func, /** * A callback function to execute when month component loses focus. * requires no parameter. */ onMonthBlur: PropTypes.func, /** * A callback function to execute on mouse down on day. * requires no parameter. */ onDayMouseDown: PropTypes.func, /** * A prop to check next month dates. */ peekNextMonth: PropTypes.bool, /** * Prop to store previous selection value. */ preSelection: PropTypes.object, /** * Callback ref to pass into the dom element. */ refCallback: PropTypes.func, /** * Prop to store current selection value. */ selected: PropTypes.object, /** * Prop to store value while selecting date. */ selectingDate: PropTypes.object, /** * Mark date picker to select end of range . */ selectsEnd: PropTypes.bool, /** * Mark date picker to select start of range . */ selectsStart: PropTypes.bool, /** * Prop to show week numbers . */ showWeekNumbers: PropTypes.bool, /** * Minimum date for a given range . */ startDate: PropTypes.object, /** * Whether or not calendar is opened via keyboard */ isCalendarKeyboardFocused: PropTypes.bool, } handleDayClick = (day, event) => { if (this.props.onDayClick) { this.props.onDayClick(day, event) } } handleDayMouseEnter = (day) => { if (this.props.onDayMouseEnter) { this.props.onDayMouseEnter(day) } } handleDayMouseDown = () => { if (this.props.onDayMouseDown) { this.props.onDayMouseDown(); } } handleMouseLeave = () => { if (this.props.onMouseLeave) { this.props.onMouseLeave() } } handleMonthBlur = () => { if (this.props.onMonthBlur) { this.props.onMonthBlur() } } handleMonthFocus = () => { if (this.props.onMonthFocus) { this.props.onMonthFocus() } } isWeekInMonth = (startOfWeek) => { const day = this.props.day const endOfWeek = utils.addDays(utils.cloneDate(startOfWeek), 6) return utils.isSameMonth(startOfWeek, day) || utils.isSameMonth(endOfWeek, day) } renderWeeks = () => { const weeks = [] var isFixedHeight = this.props.fixedHeight let currentWeekStart = utils.getStartOfWeek(utils.getStartOfMonth(utils.cloneDate(this.props.day))) let i = 0 let breakAfterNextPush = false while (true) { weeks.push(<Week isCalendarKeyboardFocused={this.props.isCalendarKeyboardFocused} key={i} day={currentWeekStart} month={utils.getMonth(this.props.day)} onDayClick={this.handleDayClick} onDayMouseEnter={this.handleDayMouseEnter} onDayMouseDown={this.handleDayMouseDown} onWeekSelect={this.props.onWeekSelect} formatWeekNumber={this.props.formatWeekNumber} minDate={this.props.minDate} maxDate={this.props.maxDate} excludeDates={this.props.excludeDates} includeDates={this.props.includeDates} initialTimeZone={this.props.initialTimeZone} inline={this.props.inline} highlightDates={this.props.highlightDates} selectingDate={this.props.selectingDate} filterDate={this.props.filterDate} preSelection={this.props.preSelection} selected={this.props.selected} selectsStart={this.props.selectsStart} selectsEnd={this.props.selectsEnd} showWeekNumber={this.props.showWeekNumbers} startDate={this.props.startDate} endDate={this.props.endDate} dayClassName={this.props.dayClassName}/>) if (breakAfterNextPush) break i++ currentWeekStart = utils.addWeeks(utils.cloneDate(currentWeekStart), 1) // If one of these conditions is true, we will either break on this week // or break on the next week const isFixedAndFinalWeek = isFixedHeight && i >= FIXED_HEIGHT_STANDARD_WEEK_COUNT const isNonFixedAndOutOfMonth = !isFixedHeight && !this.isWeekInMonth(currentWeekStart) if (isFixedAndFinalWeek || isNonFixedAndOutOfMonth) { if (this.props.peekNextMonth) { breakAfterNextPush = true } else { break } } } return weeks } render() { const getClassNames = cx({ 'react-datepicker-month': true, 'react-datepicker-body': true, 'react-datepicker-month--selecting-range': this.props.selectingDate && (this.props.selectsStart || this.props.selectsEnd), }); return ( <FormattedMessage id="Terra.datePicker.calendarInstructions"> {text => ( <div tabIndex="0" className={getClassNames} onMouseLeave={this.handleMouseLeave} role="application" onBlur={this.handleMonthBlur} onFocus={this.handleMonthFocus} aria-label={`${utils.getLocalizedDateForScreenReader(this.props.preSelection, { intl: this.props.intl, locale: this.props.locale })}. ${text}`} onKeyDown={this.props.handleCalendarKeyDown} ref={this.props.refCallback} > {this.renderWeeks()} </div> )} </FormattedMessage> ) } }