UNPKG

semantic-ui-calendar-react

Version:
185 lines (166 loc) 5.24 kB
import React from 'react'; import PropTypes from 'prop-types'; import moment from 'moment'; import _ from 'lodash'; import DayView from '../../views/DayView'; import { WEEKS_TO_DISPLAY } from '../../views/DayView'; import { getUnhandledProps } from '../../lib'; import { buildDays, getDisabledDays, isNextPageAvailable, isPrevPageAvailable, } from './sharedFunctions'; import BasePicker from '../BasePicker'; const PAGE_WIDTH = 7; export const DAYS_ON_PAGE = WEEKS_TO_DISPLAY * PAGE_WIDTH; class DayPicker extends BasePicker { constructor(props) { super(props); this.state = { /* moment instance */ date: props.initializeWith.clone(), }; this.PAGE_WIDTH = PAGE_WIDTH; } buildCalendarValues() { /* Return array of dates (strings) like ['31', '1', ...] that used to populate calendar's page. */ return buildDays(this.state.date, DAYS_ON_PAGE); } getSelectableCellPositions = () => { return _.filter( _.range(0, DAYS_ON_PAGE), d => !_.includes(this.getDisabledDaysPositions(), d), ); } getInitialDatePosition = () => { return this.buildCalendarValues().indexOf(this.state.date.date().toString()); } getActiveCellPosition() { /* Return position of a date that should be displayed as active (position in array returned by `this.buildCalendarValues`). */ if (this.props.value && this.props.value.isSame(this.state.date, 'month')) { const disabledPositions = this.getDisabledDaysPositions(); const active = this.buildCalendarValues() .map((day, i) => _.includes(disabledPositions, i)? undefined : day) .indexOf(this.props.value.date().toString()); if (active >= 0) { return active; } } } getDisabledDaysPositions() { /* Return position numbers of dates that should be displayed as disabled (position in array returned by `this.buildCalendarValues`). */ const { disable, maxDate, minDate, enable, } = this.props; return getDisabledDays(disable, maxDate, minDate, this.state.date, DAYS_ON_PAGE, enable); } isNextPageAvailable() { const { maxDate, enable, } = this.props; if (_.isArray(enable)) { return _.some(enable, enabledDate => enabledDate.isAfter(this.state.date, 'month')); } return isNextPageAvailable(this.state.date, maxDate); } isPrevPageAvailable() { const { minDate, enable, } = this.props; if (_.isArray(enable)) { return _.some(enable, enabledDate => enabledDate.isBefore(this.state.date, 'month')); } return isPrevPageAvailable(this.state.date, minDate); } getCurrentDate() { /* Return currently selected year and month(string) to display in calendar header. */ return this.state.date.format('MMMM YYYY'); } handleChange = (e, { value }) => { // `value` is selected date(string) like '31' or '1' const result = { year: this.state.date.year(), month: this.state.date.month(), date: parseInt(value), }; _.invoke(this.props, 'onChange', e, { ...this.props, value: result }); } switchToNextPage = () => { this.setState(({ date }) => { const nextDate = date.clone(); nextDate.add(1, 'month'); return { date: nextDate }; }); } switchToPrevPage = () => { this.setState(({ date }) => { const prevDate = date.clone(); prevDate.subtract(1, 'month'); return { date: prevDate }; }); } render() { const rest = getUnhandledProps(DayPicker, this.props); return ( <DayView { ...rest } days={this.buildCalendarValues()} hasNextPage={this.isNextPageAvailable()} hasPrevPage={this.isPrevPageAvailable()} onNextPageBtnClick={this.switchToNextPage} onPrevPageBtnClick={this.switchToPrevPage} onDayClick={this.handleChange} onBlur={this.handleBlur} inline={this.props.inline} onMount={this.props.onCalendarViewMount} hovered={this.state.hoveredCellPosition} onCellHover={this.onHoveredCellPositionChange} currentDate={this.getCurrentDate()} disabled={this.getDisabledDaysPositions()} active={this.getActiveCellPosition()} /> ); } } DayPicker.propTypes = { /** Called after day is selected. */ onChange: PropTypes.func.isRequired, /** A value for initializing day picker's state. */ initializeWith: PropTypes.instanceOf(moment).isRequired, displayWeeks: PropTypes.bool, /** Currently selected day. */ value: PropTypes.instanceOf(moment), /** Array of disabled days. */ disable: PropTypes.arrayOf( PropTypes.instanceOf(moment) ), /** Array of enabled days. */ enable: PropTypes.arrayOf( PropTypes.instanceOf(moment) ), /** Minimal date that could be selected. */ minDate: PropTypes.instanceOf(moment), /** Maximal date that could be selected. */ maxDate: PropTypes.instanceOf(moment), /** Force popup to close. */ closePopup: PropTypes.func, isPickerInFocus: PropTypes.func, isTriggerInFocus: PropTypes.func, onCalendarViewMount: PropTypes.func, inline: PropTypes.bool, }; export default DayPicker;