-
-
Notifications
You must be signed in to change notification settings - Fork 112
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add selectionType prop to Calendar component (#1563)
* feat: add selectionType prop to Calendar component * fix: code cleanup * fix: fix render when selection type is range * style: fix range highlight * style: fix range highlight * style: fix range highlight when range start date is the same as range end date * fix: fix range highlight when hovered * style: fix styles * fix: fix comments * fix: some code enhancements * fix: fix index.d.ts * fix: issues in comments * fix: fix buildNewRangeFromValue helper * styles: range color * styles: hover flicking * fix: indentation * style: fix highlight background when range starts on saturday and end in sunday * fix: fix range selection when selected end date is previous to range start date * fix: fix comments Co-authored-by: Tahimi <tahimileon@gmail.com> Co-authored-by: TahimiLeonBravo <tahimi@nexxtway.com> Co-authored-by: Maxx Greene <56657888+maxxgreene@users.noreply.github.com>
- Loading branch information
1 parent
aad2190
commit 18a894f
Showing
27 changed files
with
998 additions
and
470 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import React from 'react'; | ||
|
||
export const { Provider, Consumer } = React.createContext(); | ||
export const CalendarContext = React.createContext(); | ||
export const { Provider, Consumer } = CalendarContext; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
src/components/Calendar/helpers/__test__/buildNewRangeFromValue.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import buildNewRangeFromValue from '../buildNewRangeFromValue'; | ||
|
||
describe('buildNewRangeFromValue', () => { | ||
it('should return array with single date', () => { | ||
const value = new Date(); | ||
const ranges = [undefined, null, []]; | ||
ranges.forEach(range => { | ||
expect(buildNewRangeFromValue(value, range)).toEqual({ | ||
range: [value], | ||
}); | ||
}); | ||
}); | ||
it('should return array with two dates', () => { | ||
const date1 = new Date(2019, 2, 1); | ||
const date2 = new Date(2019, 21, 1); | ||
const range = [date1]; | ||
expect(buildNewRangeFromValue(date2, range)).toEqual({ | ||
range: [date1, date2], | ||
}); | ||
}); | ||
it('should return array with two dates and date3 as first date', () => { | ||
const date1 = new Date(2019, 0, 2); | ||
const date2 = new Date(2019, 0, 21); | ||
const date3 = new Date(2019, 0, 15); | ||
const range = [date1, date2]; | ||
expect(buildNewRangeFromValue(date3, range)).toEqual({ | ||
range: [date3, date2], | ||
nextUpdatePosition: 1, | ||
}); | ||
}); | ||
}); |
17 changes: 17 additions & 0 deletions
17
src/components/Calendar/helpers/__test__/isDateWithinRange.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import isDateWithinRange from '../isDateWithinRange'; | ||
|
||
describe('isDateWithinRange', () => { | ||
it('should return false', () => { | ||
const range = [new Date(2019, 2, 1, 0, 0, 0, 600), new Date(2019, 15, 1, 23, 12, 34, 600)]; | ||
expect(isDateWithinRange(null, range)).toBe(false); | ||
expect(isDateWithinRange(undefined, range)).toBe(false); | ||
expect(isDateWithinRange(new Date(2019, 1, 1), range)).toBe(false); | ||
expect(isDateWithinRange(new Date(2019, 18, 1), range)).toBe(false); | ||
}); | ||
it('should return true', () => { | ||
const range = [new Date(2019, 2, 1), new Date(2019, 15, 1)]; | ||
expect(isDateWithinRange(new Date(2019, 2, 1), range)).toBe(true); | ||
expect(isDateWithinRange(new Date(2019, 13, 1), range)).toBe(true); | ||
expect(isDateWithinRange(new Date(2019, 15, 1), range)).toBe(true); | ||
}); | ||
}); |
16 changes: 16 additions & 0 deletions
16
src/components/Calendar/helpers/__test__/isEmptyRange.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import isEmptyRange from '../isEmptyRange'; | ||
|
||
describe('isEmptyRange', () => { | ||
it('should return true', () => { | ||
const ranges = [null, undefined, [], {}, 0, [undefined], [undefined, undefined]]; | ||
ranges.forEach(range => { | ||
expect(isEmptyRange(range)).toBe(true); | ||
}); | ||
}); | ||
it('should return false', () => { | ||
const ranges = [[1], [1, 2]]; | ||
ranges.forEach(range => { | ||
expect(isEmptyRange(range)).toBe(false); | ||
}); | ||
}); | ||
}); |
44 changes: 44 additions & 0 deletions
44
src/components/Calendar/helpers/__test__/isSameDatesRange.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import isSameDatesRange from '../isSameDatesRange'; | ||
|
||
describe('isSameMonth', () => { | ||
it('should return true', () => { | ||
const range1 = [ | ||
null, | ||
undefined, | ||
[], | ||
[new Date(2019, 1, 1)], | ||
[new Date(2019, 1, 1), new Date(2019, 1, 10)], | ||
]; | ||
const range2 = [ | ||
null, | ||
undefined, | ||
[], | ||
[new Date(2019, 1, 1)], | ||
[new Date(2019, 1, 1), new Date(2019, 1, 10)], | ||
]; | ||
|
||
range1.forEach((value, index) => { | ||
expect(isSameDatesRange(value, range2[index])).toBe(true); | ||
}); | ||
}); | ||
it('should return false', () => { | ||
const range1 = [ | ||
null, | ||
undefined, | ||
[], | ||
[new Date(2019, 1, 1)], | ||
[new Date(2019, 1, 1), new Date(2019, 1, 10)], | ||
]; | ||
const range2 = [ | ||
undefined, | ||
[], | ||
null, | ||
[new Date(2019, 1, 1), new Date(2019, 1, 10)], | ||
[new Date(2019, 1, 1)], | ||
]; | ||
|
||
range1.forEach((value, index) => { | ||
expect(isSameDatesRange(value, range2[index])).toBe(false); | ||
}); | ||
}); | ||
}); |
42 changes: 42 additions & 0 deletions
42
src/components/Calendar/helpers/__test__/shouldDateBeSelected.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import shouldDateBeSelected from '../shouldDateBeSelected'; | ||
|
||
describe('shouldDateBeSelected', () => { | ||
it('should return true when selectionType is single and date is the same as value', () => { | ||
const date = new Date(2019, 1, 1); | ||
const value = new Date(2019, 1, 1); | ||
const range = [new Date(2019, 1, 1), new Date(2019, 1, 15)]; | ||
expect(shouldDateBeSelected(date, value, 'single', undefined)).toBe(true); | ||
expect(shouldDateBeSelected(date, value, 'single', null)).toBe(true); | ||
expect(shouldDateBeSelected(date, value, 'single', [])).toBe(true); | ||
expect(shouldDateBeSelected(date, value, 'single', range)).toBe(true); | ||
}); | ||
it('should return true when selectionType is range and date is same as range boundaries', () => { | ||
const date1 = new Date(2019, 1, 1); | ||
const date2 = new Date(2019, 1, 15); | ||
const value = new Date(2019, 1, 1); | ||
const range = [new Date(2019, 1, 1), new Date(2019, 1, 15)]; | ||
expect(shouldDateBeSelected(date1, undefined, 'range', range)).toBe(true); | ||
expect(shouldDateBeSelected(date1, null, 'range', range)).toBe(true); | ||
expect(shouldDateBeSelected(date1, value, 'range', range)).toBe(true); | ||
expect(shouldDateBeSelected(date2, value, 'range', range)).toBe(true); | ||
}); | ||
it('should return false when selectionType is single and date is not the same as value', () => { | ||
const date = new Date(2019, 1, 12); | ||
const value = new Date(2019, 1, 1); | ||
const range = [new Date(2019, 1, 1), new Date(2019, 1, 15)]; | ||
expect(shouldDateBeSelected(date, value, 'single', undefined)).toBe(false); | ||
expect(shouldDateBeSelected(date, value, 'single', null)).toBe(false); | ||
expect(shouldDateBeSelected(date, value, 'single', [])).toBe(false); | ||
expect(shouldDateBeSelected(date, value, 'single', range)).toBe(false); | ||
}); | ||
it('should return false when selectionType is range and date is not the same as range boundaries', () => { | ||
const date1 = new Date(2019, 1, 2); | ||
const date2 = new Date(2019, 1, 12); | ||
const value = new Date(2019, 1, 1); | ||
const range = [new Date(2019, 1, 1), new Date(2019, 1, 15)]; | ||
expect(shouldDateBeSelected(date1, undefined, 'range', range)).toBe(false); | ||
expect(shouldDateBeSelected(date1, null, 'range', range)).toBe(false); | ||
expect(shouldDateBeSelected(date1, value, 'range', range)).toBe(false); | ||
expect(shouldDateBeSelected(date2, value, 'range', range)).toBe(false); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import isDateWithinRange from './isDateWithinRange'; | ||
import compareDates from './compareDates'; | ||
|
||
export default function buildNewRangeFromValue(value, currentRange, currentUpdatePosition = 0) { | ||
if (!currentRange || currentRange.length === 0) | ||
return { | ||
range: [value], | ||
}; | ||
|
||
const [rangeStart, rangeEnd] = currentRange; | ||
|
||
if (!rangeEnd) { | ||
if (compareDates(value, rangeStart) >= 0) { | ||
return { | ||
range: [rangeStart, value], | ||
}; | ||
} | ||
return { | ||
range: [value], | ||
}; | ||
} | ||
|
||
if (isDateWithinRange(value, currentRange)) { | ||
if (currentUpdatePosition === 0) { | ||
return { | ||
range: [value, rangeEnd], | ||
nextUpdatePosition: 1, | ||
}; | ||
} | ||
return { | ||
range: [rangeStart, value], | ||
nextUpdatePosition: 0, | ||
}; | ||
} | ||
|
||
return { | ||
range: [value], | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,24 @@ | ||
import addDays from './addDays'; | ||
import addMonths from './addMonths'; | ||
import formatDate from './formatDate'; | ||
import getFirstDayMonth from './getFirstDayMonth'; | ||
import getFormattedMonth from './getFormattedMonth'; | ||
import getLastDayMonth from './getLastDayMonth'; | ||
import getYearsRange from './getYearsRange'; | ||
import isSameDay from './isSameDay'; | ||
import normalizeDate from './normalizeDate'; | ||
import getFormattedDayName from './getFormattedDayName'; | ||
import compareDates from './compareDates'; | ||
import isSameMonth from './isSameMonth'; | ||
import isSameYear from './isSameYear'; | ||
import getSign from './getSign'; | ||
import getCalendarBounds from './getCalendarBounds'; | ||
import isDateBelowLimit from './isDateBelowLimit'; | ||
import isDateBeyondLimit from './isDateBeyondLimit'; | ||
import getNextFocusedDate from './getNextFocusedDate'; | ||
|
||
export { | ||
addDays, | ||
addMonths, | ||
formatDate, | ||
getFirstDayMonth, | ||
getFormattedMonth, | ||
getLastDayMonth, | ||
getYearsRange, | ||
isSameDay, | ||
normalizeDate, | ||
getFormattedDayName, | ||
compareDates, | ||
isSameMonth, | ||
isSameYear, | ||
getSign, | ||
getCalendarBounds, | ||
isDateBelowLimit, | ||
isDateBeyondLimit, | ||
getNextFocusedDate, | ||
}; | ||
export { default as addDays } from './addDays'; | ||
export { default as addMonths } from './addMonths'; | ||
export { default as formatDate } from './formatDate'; | ||
export { default as getFirstDayMonth } from './getFirstDayMonth'; | ||
export { default as getFormattedMonth } from './getFormattedMonth'; | ||
export { default as getLastDayMonth } from './getLastDayMonth'; | ||
export { default as getYearsRange } from './getYearsRange'; | ||
export { default as isSameDay } from './isSameDay'; | ||
export { default as normalizeDate } from './normalizeDate'; | ||
export { default as normalizeRange } from './normalizeRange'; | ||
export { default as getFormattedDayName } from './getFormattedDayName'; | ||
export { default as compareDates } from './compareDates'; | ||
export { default as isSameMonth } from './isSameMonth'; | ||
export { default as isSameYear } from './isSameYear'; | ||
export { default as getSign } from './getSign'; | ||
export { default as getCalendarBounds } from './getCalendarBounds'; | ||
export { default as isDateBelowLimit } from './isDateBelowLimit'; | ||
export { default as isDateBeyondLimit } from './isDateBeyondLimit'; | ||
export { default as getNextFocusedDate } from './getNextFocusedDate'; | ||
export { default as isDateWithinRange } from './isDateWithinRange'; | ||
export { default as buildNewRangeFromValue } from './buildNewRangeFromValue'; | ||
export { default as shouldDateBeSelected } from './shouldDateBeSelected'; | ||
export { default as isSameDatesRange } from './isSameDatesRange'; | ||
export { default as isEmptyRange } from './isEmptyRange'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import compareDates from './compareDates'; | ||
|
||
export default function isDateWithinRange(date, range) { | ||
if (date && Array.isArray(range) && range.length > 1) { | ||
const [rangeStart, rangeEnd] = range; | ||
return compareDates(date, rangeStart) >= 0 && compareDates(date, rangeEnd) <= 0; | ||
} | ||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export default function isEmptyRange(range) { | ||
if ([null, undefined, [], {}].includes(range)) return true; | ||
if (!Array.isArray(range) || range.length === 0) return true; | ||
const nullFilteredRange = range.filter(item => !!item); | ||
return nullFilteredRange.length === 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default function isSameDatesRange(range1, range2) { | ||
return JSON.stringify(range1) === JSON.stringify(range2); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import normalizeDate from './normalizeDate'; | ||
|
||
export default function normalizeRange(range) { | ||
if (!range) return []; | ||
if (!Array.isArray(range)) return [normalizeDate(range)]; | ||
return range.map(date => normalizeDate(date)); | ||
} |
Oops, something went wrong.