Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for updating a range without losing the opposite end of the selection #928

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/react-calendar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ Displays a complete, interactive calendar.
| formatYear | Function called to override default formatting of year in the top navigation section. Can be used to use your own formatting function. | (default formatter) | `(locale, date) => formatDate(date, 'YYYY')` |
| goToRangeStartOnSelect | Whether to go to the beginning of the range when selecting the end of the range. | `true` | `false` |
| inputRef | A prop that behaves like [ref](https://reactjs.org/docs/refs-and-the-dom.html), but it's passed to main `<div>` rendered by `<Calendar>` component. | n/a | <ul><li>Function:<br />`(ref) => { this.myCalendar = ref; }`</li><li>Ref created using `createRef`:<br />`this.ref = createRef();`<br />…<br />`inputRef={this.ref}`</li><li>Ref created using `useRef`:<br />`const ref = useRef();`<br />…<br />`inputRef={ref}`</li></ul> |
| keepBoundarySelected | Whether the range should remain selected if the user clicks on one of the "range boundaries". For instance, if the user selects days 1 and 3, and subsequently clicks on day 3 again, day 1 will remain selected to "update" the range. | `false` | `true` |
| locale | Locale that should be used by the calendar. Can be any [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag). **Note**: When using SSR, setting this prop may help resolving hydration errors caused by locale mismatch between server and client. | Server locale/User's browser settings | `"hu-HU"` |
| maxDate | Maximum date that the user can select. Periods partially overlapped by maxDate will also be selectable, although react-calendar will ensure that no later date is selected. | n/a | Date: `new Date()` |
| maxDetail | The most detailed view that the user shall see. View defined here also becomes the one on which clicking an item will select a date and pass it to onChange. Can be `"month"`, `"year"`, `"decade"` or `"century"`. | `"month"` | `"year"` |
Expand Down
4 changes: 2 additions & 2 deletions packages/react-calendar/src/Calendar.css
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,7 @@
color: #cdcdcd;
}

.react-calendar__tile:enabled:hover,
.react-calendar__tile:enabled:focus {
.react-calendar__tile:enabled:hover {
background-color: #e6e6e6;
}

Expand Down Expand Up @@ -153,4 +152,5 @@

.react-calendar--selectRange .react-calendar__tile--hover {
background-color: #e6e6e6;
color: unset;
}
20 changes: 19 additions & 1 deletion packages/react-calendar/src/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ export type CalendarProps = {
* @example ref
*/
inputRef?: React.Ref<HTMLDivElement>;
/**
* Whether the range should remain selected if the user clicks on one of the "range boundaries". For instance, if the user selects days 1 and 3, and subsequently clicks on day 3 again, day 1 will remain selected to "update" the range.
*/
keepBoundarySelected?: boolean;
/**
* Locale that should be used by the calendar. Can be any [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag).
*
Expand Down Expand Up @@ -615,6 +619,7 @@ const Calendar: React.ForwardRefExoticComponent<CalendarProps & React.RefAttribu
formatWeekday,
formatYear,
goToRangeStartOnSelect = true,
keepBoundarySelected,
inputRef,
locale,
maxDate = defaultMaxDate,
Expand Down Expand Up @@ -891,7 +896,19 @@ const Calendar: React.ForwardRefExoticComponent<CalendarProps & React.RefAttribu
if (selectRange) {
// Range selection turned on

if (isFirstValueInRange) {
if (
keepBoundarySelected &&
Array.isArray(previousValue) &&
areDatesEqual(rawNextValue, previousValue[0])
) {
nextValue = previousValue[1];
} else if (
keepBoundarySelected &&
Array.isArray(previousValue) &&
areDatesEqual(getEnd(valueType, rawNextValue), previousValue[1])
) {
nextValue = previousValue[0];
} else if (isFirstValueInRange) {
// Value has 0 or 2 elements - either way we're starting a new array
// First value
nextValue = getBegin(valueType, rawNextValue);
Expand Down Expand Up @@ -968,6 +985,7 @@ const Calendar: React.ForwardRefExoticComponent<CalendarProps & React.RefAttribu
allowPartialRange,
getProcessedValue,
goToRangeStartOnSelect,
keepBoundarySelected,
maxDate,
maxDetail,
minDate,
Expand Down