From ceb58b996c3bbd5cf49ab05c2b2e2da719126d65 Mon Sep 17 00:00:00 2001 From: Maja Wichrowska Date: Tue, 9 May 2017 09:55:32 -0700 Subject: [PATCH] Patch issues with the perf architecture - after-hovered-start is no longer applied on touch devices - transitioning months no longer grabs extra hidden months - vertical scrollable daypickers update modifier state accordingly --- css/CalendarMonth.scss | 17 +++++---- src/components/CalendarMonthGrid.jsx | 15 ++++---- src/components/DayPicker.jsx | 6 ++++ src/components/DayPickerRangeController.jsx | 39 ++++++++++++++++----- src/utils/getVisibleDays.js | 11 ++++-- 5 files changed, 63 insertions(+), 25 deletions(-) diff --git a/css/CalendarMonth.scss b/css/CalendarMonth.scss index b419ce0d25..b178796a5f 100644 --- a/css/CalendarMonth.scss +++ b/css/CalendarMonth.scss @@ -5,13 +5,6 @@ padding: 0 13px; vertical-align: top; - &:first-of-type { - position: absolute; - z-index: $react-dates-z-index - 1; - opacity: 0; - pointer-events: none; - } - table { border-collapse: collapse; border-spacing: 0; @@ -26,6 +19,16 @@ user-select: none; } +.CalendarMonth--horizontal, +.CalendarMonth--vertical { + &:first-of-type { + position: absolute; + z-index: $react-dates-z-index - 1; + opacity: 0; + pointer-events: none; + } +} + .CalendarMonth--horizontal { display: inline-block; min-height: 100%; diff --git a/src/components/CalendarMonthGrid.jsx b/src/components/CalendarMonthGrid.jsx index 0c1bd7cb47..542c2e9db7 100644 --- a/src/components/CalendarMonthGrid.jsx +++ b/src/components/CalendarMonthGrid.jsx @@ -75,11 +75,12 @@ const defaultProps = { phrases: CalendarDayPhrases, }; -function getMonths(initialMonth, numberOfMonths) { - let month = initialMonth.clone().subtract(1, 'month'); +function getMonths(initialMonth, numberOfMonths, withoutTransitionMonths) { + let month = initialMonth.clone(); + if (!withoutTransitionMonths) month = month.subtract(1, 'month'); const months = []; - for (let i = 0; i < numberOfMonths + 2; i += 1) { + for (let i = 0; i < (withoutTransitionMonths ? numberOfMonths : numberOfMonths + 2); i += 1) { months.push(month); month = month.clone().add(1, 'month'); } @@ -90,8 +91,9 @@ function getMonths(initialMonth, numberOfMonths) { export default class CalendarMonthGrid extends React.Component { constructor(props) { super(props); + const withoutTransitionMonths = props.orientation === VERTICAL_SCROLLABLE; this.state = { - months: getMonths(props.initialMonth, props.numberOfMonths), + months: getMonths(props.initialMonth, props.numberOfMonths, withoutTransitionMonths), }; this.isTransitionEndSupported = isTransitionEndSupported(); @@ -107,7 +109,7 @@ export default class CalendarMonthGrid extends React.Component { } componentWillReceiveProps(nextProps) { - const { initialMonth, numberOfMonths } = nextProps; + const { initialMonth, numberOfMonths, orientation } = nextProps; const { months } = this.state; const hasMonthChanged = !this.props.initialMonth.isSame(initialMonth, 'month'); @@ -125,7 +127,8 @@ export default class CalendarMonthGrid extends React.Component { } if (hasNumberOfMonthsChanged) { - newMonths = getMonths(initialMonth, numberOfMonths); + const withoutTransitionMonths = orientation === VERTICAL_SCROLLABLE; + newMonths = getMonths(initialMonth, numberOfMonths, withoutTransitionMonths); } this.setState({ diff --git a/src/components/DayPicker.jsx b/src/components/DayPicker.jsx index 136cfb0149..7fa965a5af 100644 --- a/src/components/DayPicker.jsx +++ b/src/components/DayPicker.jsx @@ -58,6 +58,7 @@ const propTypes = forbidExtraProps({ navNext: PropTypes.node, onPrevMonthClick: PropTypes.func, onNextMonthClick: PropTypes.func, + onMultiplyScrollableMonths: PropTypes.func, // VERTICAL_SCROLLABLE daypickers only // month props renderMonth: PropTypes.func, @@ -99,6 +100,7 @@ export const defaultProps = { navNext: null, onPrevMonthClick() {}, onNextMonthClick() {}, + onMultiplyScrollableMonths() {}, // month props renderMonth: null, @@ -476,8 +478,11 @@ export default class DayPicker extends React.Component { } multiplyScrollableMonths(e) { + const { onMultiplyScrollableMonths } = this.props; if (e) e.preventDefault(); + if (onMultiplyScrollableMonths) onMultiplyScrollableMonths(e); + this.setState({ scrollableMonthMultiple: this.state.scrollableMonthMultiple + 1, }); @@ -730,6 +735,7 @@ export default class DayPicker extends React.Component { } const verticalScrollable = this.props.orientation === VERTICAL_SCROLLABLE; + if (verticalScrollable) firstVisibleMonthIndex = 0; const dayPickerClassNames = cx('DayPicker', { 'DayPicker--horizontal': this.isHorizontal(), diff --git a/src/components/DayPickerRangeController.jsx b/src/components/DayPickerRangeController.jsx index 29f231f9c7..5865a16b56 100644 --- a/src/components/DayPickerRangeController.jsx +++ b/src/components/DayPickerRangeController.jsx @@ -28,6 +28,7 @@ import { START_DATE, END_DATE, HORIZONTAL_ORIENTATION, + VERTICAL_SCROLLABLE, DAY_SIZE, } from '../../constants'; @@ -163,6 +164,7 @@ export default class DayPickerRangeController extends React.Component { this.onDayMouseLeave = this.onDayMouseLeave.bind(this); this.onPrevMonthClick = this.onPrevMonthClick.bind(this); this.onNextMonthClick = this.onNextMonthClick.bind(this); + this.onMultiplyScrollableMonths = this.onMultiplyScrollableMonths.bind(this); this.getFirstFocusableDay = this.getFirstFocusableDay.bind(this); } @@ -256,7 +258,7 @@ export default class DayPickerRangeController extends React.Component { } } - if (didStartDateChange && startDate && !endDate) { + if (!this.isTouchDevice && didStartDateChange && startDate && !endDate) { const startSpan = startDate.clone().add(1, 'day'); const endSpan = startDate.clone().add(minimumNights + 1, 'days'); modifiers = this.addModifierToRange(modifiers, startSpan, endSpan, 'after-hovered-start'); @@ -468,11 +470,11 @@ export default class DayPickerRangeController extends React.Component { newVisibleDays[month] = visibleDays[month]; }); - const prevMonth = currentMonth.clone().subtract(1, 'months'); - const prevMonthVisibleDays = getVisibleDays(prevMonth, 1, enableOutsideDays); + const prevMonth = currentMonth.clone().subtract(2, 'months'); + const prevMonthVisibleDays = getVisibleDays(prevMonth, 1, enableOutsideDays, true); this.setState({ - currentMonth: prevMonth, + currentMonth: currentMonth.clone().subtract(1, 'month'), visibleDays: { ...newVisibleDays, ...this.getModifiers(prevMonthVisibleDays), @@ -491,8 +493,8 @@ export default class DayPickerRangeController extends React.Component { newVisibleDays[month] = visibleDays[month]; }); - const nextMonth = currentMonth.clone().add(numberOfMonths, 'month'); - const nextMonthVisibleDays = getVisibleDays(nextMonth, 1, enableOutsideDays); + const nextMonth = currentMonth.clone().add(numberOfMonths + 1, 'month'); + const nextMonthVisibleDays = getVisibleDays(nextMonth, 1, enableOutsideDays, true); this.setState({ currentMonth: currentMonth.clone().add(1, 'month'), @@ -505,6 +507,22 @@ export default class DayPickerRangeController extends React.Component { onNextMonthClick(); } + onMultiplyScrollableMonths() { + const { numberOfMonths, enableOutsideDays } = this.props; + const { currentMonth, visibleDays } = this.state; + + const numberOfVisibleMonths = Object.keys(visibleDays).length; + const nextMonth = currentMonth.clone().add(numberOfVisibleMonths, 'month'); + const newVisibleDays = getVisibleDays(nextMonth, numberOfMonths, enableOutsideDays, true); + + this.setState({ + visibleDays: { + ...visibleDays, + ...this.getModifiers(newVisibleDays), + }, + }); + } + getFirstFocusableDay(newMonth) { const { startDate, endDate, focusedInput, minimumNights, numberOfMonths } = this.props; @@ -551,10 +569,12 @@ export default class DayPickerRangeController extends React.Component { } getStateForNewMonth(nextProps) { - const { initialVisibleMonth, numberOfMonths, enableOutsideDays } = nextProps; + const { initialVisibleMonth, numberOfMonths, enableOutsideDays, orientation } = nextProps; const currentMonth = initialVisibleMonth(); - const visibleDays = - this.getModifiers(getVisibleDays(currentMonth, numberOfMonths, enableOutsideDays)); + const withoutTransitionMonths = orientation === VERTICAL_SCROLLABLE; + const visibleDays = this.getModifiers( + getVisibleDays(currentMonth, numberOfMonths, enableOutsideDays, withoutTransitionMonths), + ); return { currentMonth, visibleDays }; } @@ -755,6 +775,7 @@ export default class DayPickerRangeController extends React.Component { onDayMouseLeave={this.onDayMouseLeave} onPrevMonthClick={this.onPrevMonthClick} onNextMonthClick={this.onNextMonthClick} + onMultiplyScrollableMonths={this.onMultiplyScrollableMonths} monthFormat={monthFormat} renderMonth={renderMonth} withPortal={withPortal} diff --git a/src/utils/getVisibleDays.js b/src/utils/getVisibleDays.js index bd67e8e4ae..2c1f215775 100644 --- a/src/utils/getVisibleDays.js +++ b/src/utils/getVisibleDays.js @@ -1,12 +1,17 @@ import moment from 'moment'; import toISOMonthString from './toISOMonthString'; -export default function getVisibleDays(month, numberOfMonths, enableOutsideDays) { +export default function getVisibleDays( + month, + numberOfMonths, + enableOutsideDays, + withoutTransitionMonths, +) { if (!moment.isMoment(month)) return {}; const visibleDaysByMonth = {}; - let currentMonth = month.clone().subtract(1, 'month'); - for (let i = 0; i < numberOfMonths + 2; i += 1) { // account for transition months + let currentMonth = withoutTransitionMonths ? month.clone() : month.clone().subtract(1, 'month'); + for (let i = 0; i < (withoutTransitionMonths ? numberOfMonths : numberOfMonths + 2); i += 1) { const visibleDays = []; // set utc offset to get correct dates in future (when timezone changes)