UNPKG

react-date-range-headless

Version:

A React component for choosing dates and date ranges. A fork of hypeserver/react-date-range in which the Headless UI Listbox (Select) uses instead html select and options

149 lines (143 loc) 5.29 kB
/* eslint-disable no-fallthrough */ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import DayCell, { rangeShape } from '../DayCell'; import { format, startOfDay, endOfDay, startOfWeek, endOfWeek, isBefore, isSameDay, isAfter, isWeekend, isWithinInterval, eachDayOfInterval, } from 'date-fns'; import { getMonthDisplayRange } from '../../utils'; function renderWeekdays(styles, dateOptions, weekdayDisplayFormat) { const now = new Date(); return ( <div className={styles.weekDays}> {eachDayOfInterval({ start: startOfWeek(now, dateOptions), end: endOfWeek(now, dateOptions), }).map((day, i) => ( <span className={styles.weekDay} key={i}> {format(day, weekdayDisplayFormat, dateOptions)} </span> ))} </div> ); } class Month extends PureComponent { render() { const now = new Date(); const { displayMode, focusedRange, drag, styles, disabledDates, disabledDay } = this.props; const minDate = this.props.minDate && startOfDay(this.props.minDate); const maxDate = this.props.maxDate && endOfDay(this.props.maxDate); const monthDisplay = getMonthDisplayRange( this.props.month, this.props.dateOptions, this.props.fixedHeight ); let ranges = this.props.ranges; if (displayMode === 'dateRange' && drag.status) { let { startDate, endDate } = drag.range; ranges = ranges.map((range, i) => { if (i !== focusedRange[0]) return range; return { ...range, startDate, endDate, }; }); } const showPreview = this.props.showPreview && !drag.disablePreview; return ( <div className={styles.month} style={this.props.style}> {this.props.showMonthName ? ( <div className={styles.monthName}> {format(this.props.month, this.props.monthDisplayFormat, this.props.dateOptions)} </div> ) : null} {this.props.showWeekDays && renderWeekdays(styles, this.props.dateOptions, this.props.weekdayDisplayFormat)} <div className={styles.days} onMouseLeave={this.props.onMouseLeave}> {eachDayOfInterval({ start: monthDisplay.start, end: monthDisplay.end }).map( (day, index) => { const isStartOfMonth = isSameDay(day, monthDisplay.startDateOfMonth); const isEndOfMonth = isSameDay(day, monthDisplay.endDateOfMonth); const isOutsideMinMax = (minDate && isBefore(day, minDate)) || (maxDate && isAfter(day, maxDate)); const isDisabledSpecifically = disabledDates.some(disabledDate => isSameDay(disabledDate, day) ); const isDisabledDay = disabledDay(day); return ( <DayCell {...this.props} ranges={ranges} day={day} preview={showPreview ? this.props.preview : null} isWeekend={isWeekend(day, this.props.dateOptions)} isToday={isSameDay(day, now)} isStartOfWeek={isSameDay(day, startOfWeek(day, this.props.dateOptions))} isEndOfWeek={isSameDay(day, endOfWeek(day, this.props.dateOptions))} isStartOfMonth={isStartOfMonth} isEndOfMonth={isEndOfMonth} key={index} disabled={isOutsideMinMax || isDisabledSpecifically || isDisabledDay} isPassive={ !isWithinInterval(day, { start: monthDisplay.startDateOfMonth, end: monthDisplay.endDateOfMonth, }) } styles={styles} onMouseDown={this.props.onDragSelectionStart} onMouseUp={this.props.onDragSelectionEnd} onMouseEnter={this.props.onDragSelectionMove} dragRange={drag.range} drag={drag.status} /> ); } )} </div> </div> ); } } Month.defaultProps = {}; Month.propTypes = { style: PropTypes.object, styles: PropTypes.object, month: PropTypes.object, drag: PropTypes.object, dateOptions: PropTypes.object, disabledDates: PropTypes.array, disabledDay: PropTypes.func, preview: PropTypes.shape({ startDate: PropTypes.object, endDate: PropTypes.object, }), showPreview: PropTypes.bool, displayMode: PropTypes.oneOf(['dateRange', 'date']), minDate: PropTypes.object, maxDate: PropTypes.object, ranges: PropTypes.arrayOf(rangeShape), focusedRange: PropTypes.arrayOf(PropTypes.number), onDragSelectionStart: PropTypes.func, onDragSelectionEnd: PropTypes.func, onDragSelectionMove: PropTypes.func, onMouseLeave: PropTypes.func, monthDisplayFormat: PropTypes.string, weekdayDisplayFormat: PropTypes.string, dayDisplayFormat: PropTypes.string, showWeekDays: PropTypes.bool, showMonthName: PropTypes.bool, fixedHeight: PropTypes.bool, }; export default Month;