diff --git a/src/day.tsx b/src/day.tsx index 1c28426a5..612c2222a 100644 --- a/src/day.tsx +++ b/src/day.tsx @@ -67,6 +67,7 @@ interface DayProps locale?: Locale; monthShowsDuplicateDaysEnd?: boolean; monthShowsDuplicateDaysStart?: boolean; + swapRange?: boolean; } /** @@ -288,6 +289,7 @@ export default class Day extends Component { selectsRange, selectsDisabledDaysInRange, startDate, + swapRange, endDate, } = this.props; @@ -317,13 +319,18 @@ export default class Day extends Component { return isDayInRange(day, startDate, selectingDate); } - if ( - selectsRange && - startDate && - !endDate && - (isAfter(selectingDate, startDate) || isEqual(selectingDate, startDate)) - ) { - return isDayInRange(day, startDate, selectingDate); + if (selectsRange && startDate && !endDate) { + if (isEqual(selectingDate, startDate)) { + return isDayInRange(day, startDate, selectingDate); + } + + if (isAfter(selectingDate, startDate)) { + return isDayInRange(day, startDate, selectingDate); + } + + if (swapRange && isBefore(selectingDate, startDate)) { + return isDayInRange(day, selectingDate, startDate); + } } return false; @@ -334,14 +341,22 @@ export default class Day extends Component { return false; } - const { day, startDate, selectsStart } = this.props; + const { day, startDate, selectsStart, swapRange, selectsRange } = + this.props; const selectingDate = this.props.selectingDate ?? this.props.preSelection; if (selectsStart) { return isSameDay(day, selectingDate); - } else { - return isSameDay(day, startDate); } + + if (selectsRange && swapRange && startDate && selectingDate) { + return isSameDay( + day, + isBefore(selectingDate, startDate) ? selectingDate : startDate, + ); + } + + return isSameDay(day, startDate); }; isSelectingRangeEnd = () => { @@ -349,14 +364,26 @@ export default class Day extends Component { return false; } - const { day, endDate, selectsEnd, selectsRange } = this.props; + const { day, endDate, selectsEnd, selectsRange, swapRange, startDate } = + this.props; const selectingDate = this.props.selectingDate ?? this.props.preSelection; - if (selectsEnd || selectsRange) { + if (selectsEnd) { + return isSameDay(day, selectingDate); + } + + if (selectsRange && swapRange && startDate && selectingDate) { + return isSameDay( + day, + isBefore(selectingDate, startDate) ? startDate : selectingDate, + ); + } + + if (selectsRange) { return isSameDay(day, selectingDate); - } else { - return isSameDay(day, endDate); } + + return isSameDay(day, endDate); }; isRangeStart = () => { diff --git a/src/test/day_test.test.tsx b/src/test/day_test.test.tsx index a17775c07..6715967f7 100644 --- a/src/test/day_test.test.tsx +++ b/src/test/day_test.test.tsx @@ -896,6 +896,151 @@ describe("Day", () => { ).toBe(true); }); }); + + describe("for a date picker with selectsRange and swapRange prop", () => { + it("should select range from startDate to selectingDate if selectingDate is after startDate", () => { + const startDate = newDate(); + const dayInRange = addDays(startDate, 1); + const selectingDate = addDays(startDate, 2); + + const containerStartDay = renderDay(dayInRange, { + startDate, + selectingDate, + selectsRange: true, + swapRange: true, + }); + expect( + containerStartDay + .querySelector(".react-datepicker__day") + ?.classList.contains(rangeDayClassName), + ).toBe(true); + }); + + it("should select range from selectingDate to startDate if selectingDate is before startDate", () => { + const startDate = newDate(); + const dayInRange = subDays(startDate, 1); + const selectingDate = subDays(startDate, 2); + + const containerStartDay = renderDay(dayInRange, { + startDate, + selectingDate, + selectsRange: true, + swapRange: true, + }); + expect( + containerStartDay + .querySelector(".react-datepicker__day") + ?.classList.contains(rangeDayClassName), + ).toBe(true); + }); + + it("should select as range if selectingDate is equal to startDate", () => { + const startDate = newDate(); + const selectingDate = startDate; + + const containerStartDay = renderDay(startDate, { + startDate, + selectingDate, + selectsRange: true, + swapRange: true, + }); + expect( + containerStartDay + .querySelector(".react-datepicker__day") + ?.classList.contains(rangeDayClassName), + ).toBe(true); + }); + + it("should set selectingDate as the start of range and startDate as the end of range if selectingDate is before startDate", () => { + const startDate = newDate(); + const selectingDate = subDays(startDate, 1); + + const containerStartDay = renderDay(selectingDate, { + startDate, + selectingDate, + selectsRange: true, + swapRange: true, + }); + expect( + containerStartDay + .querySelector(".react-datepicker__day") + ?.classList.contains(rangeDayStartClassName), + ).toBe(true); + + const containerEndDay = renderDay(startDate, { + startDate, + selectingDate, + selectsRange: true, + swapRange: true, + }); + + expect( + containerEndDay + .querySelector(".react-datepicker__day") + ?.classList.contains(rangeDayEndClassName), + ).toBe(true); + }); + + it("should set selectingDate as the end of range and startDate as the start of range if selectingDate is after startDate", () => { + const startDate = newDate(); + const selectingDate = addDays(startDate, 1); + + const containerStartDay = renderDay(startDate, { + startDate, + selectingDate, + selectsRange: true, + swapRange: true, + }); + expect( + containerStartDay + .querySelector(".react-datepicker__day") + ?.classList.contains(rangeDayStartClassName), + ).toBe(true); + + const containerEndDay = renderDay(selectingDate, { + startDate, + selectingDate, + selectsRange: true, + swapRange: true, + }); + + expect( + containerEndDay + .querySelector(".react-datepicker__day") + ?.classList.contains(rangeDayEndClassName), + ).toBe(true); + }); + + it("should set startDate as the end and start range if selectionDate equal startDate", () => { + const startDate = newDate(); + const selectingDate = startDate; + + const containerStartDay = renderDay(startDate, { + startDate, + selectingDate, + selectsRange: true, + swapRange: true, + }); + expect( + containerStartDay + .querySelector(".react-datepicker__day") + ?.classList.contains(rangeDayStartClassName), + ).toBe(true); + + const containerEndDay = renderDay(selectingDate, { + startDate, + selectingDate, + selectsRange: true, + swapRange: true, + }); + + expect( + containerEndDay + .querySelector(".react-datepicker__day") + ?.classList.contains(rangeDayEndClassName), + ).toBe(true); + }); + }); }); describe("today", () => {