From 412d8db2feb1a9e14ecc9cbe4270cf25749b4678 Mon Sep 17 00:00:00 2001
From: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com>
Date: Fri, 26 Aug 2022 14:12:56 +0200
Subject: [PATCH] [DateRangePicker] disable day on date range (#5773)
---
.../date-pickers/date-range-picker-pt.json | 2 +-
.../date-pickers/date-range-picker-zh.json | 2 +-
.../date-pickers/date-range-picker.json | 2 +-
.../desktop-date-range-picker-pt.json | 2 +-
.../desktop-date-range-picker-zh.json | 2 +-
.../desktop-date-range-picker.json | 2 +-
.../mobile-date-range-picker-pt.json | 2 +-
.../mobile-date-range-picker-zh.json | 2 +-
.../mobile-date-range-picker.json | 2 +-
.../static-date-range-picker-pt.json | 2 +-
.../static-date-range-picker-zh.json | 2 +-
.../static-date-range-picker.json | 2 +-
.../src/DateRangePicker/DateRangePicker.tsx | 1 +
.../DateRangePicker/DateRangePickerView.tsx | 21 +++++++++--
.../DesktopDateRangePicker.test.tsx | 29 +++++++++++++++
.../DesktopDateRangePicker.tsx | 1 +
.../MobileDateRangePicker.test.tsx | 37 +++++++++++++++++--
.../MobileDateRangePicker.tsx | 1 +
.../StaticDateRangePicker.tsx | 1 +
.../validation/useDateRangeValidation.ts | 25 ++++++++++---
.../src/internal/models/dateRange.ts | 14 +++++++
21 files changed, 129 insertions(+), 25 deletions(-)
diff --git a/docs/translations/api-docs/date-pickers/date-range-picker-pt.json b/docs/translations/api-docs/date-pickers/date-range-picker-pt.json
index 9576efec6cfe..6a76893c0e23 100644
--- a/docs/translations/api-docs/date-pickers/date-range-picker-pt.json
+++ b/docs/translations/api-docs/date-pickers/date-range-picker-pt.json
@@ -47,7 +47,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/docs/translations/api-docs/date-pickers/date-range-picker-zh.json b/docs/translations/api-docs/date-pickers/date-range-picker-zh.json
index 9576efec6cfe..6a76893c0e23 100644
--- a/docs/translations/api-docs/date-pickers/date-range-picker-zh.json
+++ b/docs/translations/api-docs/date-pickers/date-range-picker-zh.json
@@ -47,7 +47,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/docs/translations/api-docs/date-pickers/date-range-picker.json b/docs/translations/api-docs/date-pickers/date-range-picker.json
index 9576efec6cfe..6a76893c0e23 100644
--- a/docs/translations/api-docs/date-pickers/date-range-picker.json
+++ b/docs/translations/api-docs/date-pickers/date-range-picker.json
@@ -47,7 +47,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/docs/translations/api-docs/date-pickers/desktop-date-range-picker-pt.json b/docs/translations/api-docs/date-pickers/desktop-date-range-picker-pt.json
index a74e8a7b4839..efd923f090cf 100644
--- a/docs/translations/api-docs/date-pickers/desktop-date-range-picker-pt.json
+++ b/docs/translations/api-docs/date-pickers/desktop-date-range-picker-pt.json
@@ -45,7 +45,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/docs/translations/api-docs/date-pickers/desktop-date-range-picker-zh.json b/docs/translations/api-docs/date-pickers/desktop-date-range-picker-zh.json
index a74e8a7b4839..efd923f090cf 100644
--- a/docs/translations/api-docs/date-pickers/desktop-date-range-picker-zh.json
+++ b/docs/translations/api-docs/date-pickers/desktop-date-range-picker-zh.json
@@ -45,7 +45,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/docs/translations/api-docs/date-pickers/desktop-date-range-picker.json b/docs/translations/api-docs/date-pickers/desktop-date-range-picker.json
index a74e8a7b4839..efd923f090cf 100644
--- a/docs/translations/api-docs/date-pickers/desktop-date-range-picker.json
+++ b/docs/translations/api-docs/date-pickers/desktop-date-range-picker.json
@@ -45,7 +45,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/docs/translations/api-docs/date-pickers/mobile-date-range-picker-pt.json b/docs/translations/api-docs/date-pickers/mobile-date-range-picker-pt.json
index bfa2be4611d0..f7c3789b0a21 100644
--- a/docs/translations/api-docs/date-pickers/mobile-date-range-picker-pt.json
+++ b/docs/translations/api-docs/date-pickers/mobile-date-range-picker-pt.json
@@ -44,7 +44,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/docs/translations/api-docs/date-pickers/mobile-date-range-picker-zh.json b/docs/translations/api-docs/date-pickers/mobile-date-range-picker-zh.json
index bfa2be4611d0..f7c3789b0a21 100644
--- a/docs/translations/api-docs/date-pickers/mobile-date-range-picker-zh.json
+++ b/docs/translations/api-docs/date-pickers/mobile-date-range-picker-zh.json
@@ -44,7 +44,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/docs/translations/api-docs/date-pickers/mobile-date-range-picker.json b/docs/translations/api-docs/date-pickers/mobile-date-range-picker.json
index bfa2be4611d0..f7c3789b0a21 100644
--- a/docs/translations/api-docs/date-pickers/mobile-date-range-picker.json
+++ b/docs/translations/api-docs/date-pickers/mobile-date-range-picker.json
@@ -44,7 +44,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/docs/translations/api-docs/date-pickers/static-date-range-picker-pt.json b/docs/translations/api-docs/date-pickers/static-date-range-picker-pt.json
index 8341d0575c58..9cf47868e35e 100644
--- a/docs/translations/api-docs/date-pickers/static-date-range-picker-pt.json
+++ b/docs/translations/api-docs/date-pickers/static-date-range-picker-pt.json
@@ -41,7 +41,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/docs/translations/api-docs/date-pickers/static-date-range-picker-zh.json b/docs/translations/api-docs/date-pickers/static-date-range-picker-zh.json
index 8341d0575c58..9cf47868e35e 100644
--- a/docs/translations/api-docs/date-pickers/static-date-range-picker-zh.json
+++ b/docs/translations/api-docs/date-pickers/static-date-range-picker-zh.json
@@ -41,7 +41,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/docs/translations/api-docs/date-pickers/static-date-range-picker.json b/docs/translations/api-docs/date-pickers/static-date-range-picker.json
index 8341d0575c58..9cf47868e35e 100644
--- a/docs/translations/api-docs/date-pickers/static-date-range-picker.json
+++ b/docs/translations/api-docs/date-pickers/static-date-range-picker.json
@@ -41,7 +41,7 @@
"renderLoading": "Component displaying when passed loading
true.
Signature:
function() => React.ReactNode
returns (React.ReactNode): The node to render when loading.",
"rifmFormatter": "Custom formatter to be passed into Rifm component.
Signature:
function(str: string) => string
str: The un-formatted string.
returns (string): The formatted string.",
"rightArrowButtonText": "Right arrow icon aria-label text.",
- "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate) => boolean
day: The date to test.
returns (boolean): Returns true
if the date should be disabled.",
+ "shouldDisableDate": "Disable specific date. @DateIOType
Signature:
function(day: TDate, position: string) => boolean
day: The date to test.
position: The date to test, 'start' or 'end'.
returns (boolean): Returns true
if the date should be disabled.",
"shouldDisableMonth": "Disable specific months dynamically. Works like shouldDisableDate
but for month selection view @DateIOType.
Signature:
function(month: TDate) => boolean
month: The month to check.
returns (boolean): If true
the month will be disabled.",
"shouldDisableYear": "Disable specific years dynamically. Works like shouldDisableDate
but for year selection view @DateIOType.
Signature:
function(year: TDate) => boolean
year: The year to test.
returns (boolean): Returns true
if the year should be disabled.",
"showDaysOutsideCurrentMonth": "If true
, days that have outsideCurrentMonth={true}
are displayed.",
diff --git a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.tsx b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.tsx
index f0f6ae127af7..e5161776b348 100644
--- a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.tsx
+++ b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.tsx
@@ -380,6 +380,7 @@ DateRangePicker.propTypes = {
* Disable specific date. @DateIOType
* @template TDate
* @param {TDate} day The date to test.
+ * @param {string} position The date to test, 'start' or 'end'.
* @returns {boolean} Returns `true` if the date should be disabled.
*/
shouldDisableDate: PropTypes.func,
diff --git a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerView.tsx b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerView.tsx
index eca5f3c198fd..379c940c4726 100644
--- a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerView.tsx
+++ b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerView.tsx
@@ -11,8 +11,13 @@ import {
PickerStatePickerProps,
DayPickerProps,
BaseDateValidationProps,
+ DayValidationProps,
} from '@mui/x-date-pickers/internals';
-import { DateRange, CurrentlySelectingRangeEndProps } from '../internal/models/dateRange';
+import {
+ DateRange,
+ CurrentlySelectingRangeEndProps,
+ DayRangeValidationProps,
+} from '../internal/models/dateRange';
import { isRangeValid } from '../internal/utils/date-utils';
import { calculateRangeChange } from './date-range-manager';
import { DateRangePickerToolbar } from './DateRangePickerToolbar';
@@ -38,9 +43,13 @@ export interface DateRangePickerViewSlotsComponentsProps
export interface ExportedDateRangePickerViewProps
extends ExportedDesktopDateRangeCalendarProps,
+ DayRangeValidationProps,
Omit<
ExportedCalendarPickerProps,
- 'onYearChange' | 'renderDay' | keyof BaseDateValidationProps
+ | 'onYearChange'
+ | 'renderDay'
+ | keyof BaseDateValidationProps
+ | keyof DayValidationProps
> {
/**
* Overrideable components.
@@ -130,6 +139,10 @@ function DateRangePickerViewRaw(
const utils = useUtils();
const wrapperVariant = React.useContext(WrapperVariantContext);
+ const wrappedShouldDisableDate =
+ shouldDisableDate &&
+ ((dayToTest: TDate) => shouldDisableDate?.(dayToTest, currentlySelectingRangeEnd));
+
const [start, end] = parsedValue;
const {
changeMonth,
@@ -147,7 +160,7 @@ function DateRangePickerViewRaw(
minDate,
onMonthChange,
reduceAnimations,
- shouldDisableDate,
+ shouldDisableDate: wrappedShouldDisableDate,
});
const toShowToolbar = showToolbar ?? wrapperVariant !== 'desktop';
@@ -234,7 +247,7 @@ function DateRangePickerViewRaw(
disablePast,
minDate,
maxDate,
- shouldDisableDate,
+ shouldDisableDate: wrappedShouldDisableDate,
...calendarState,
...other,
};
diff --git a/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.test.tsx b/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.test.tsx
index 4e871f4e59d9..a0dde01316e4 100644
--- a/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.test.tsx
+++ b/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.test.tsx
@@ -95,6 +95,35 @@ describe('', () => {
expect(textboxes[0]).to.have.attribute('aria-invalid', 'true');
expect(textboxes[1]).to.have.attribute('aria-invalid', 'true');
});
+
+ it('should allow `shouldDisableDate` to depends on start or end date', () => {
+ render(
+ {
+ if (position === 'start') {
+ return adapterToUse.isAfter(date as any, adapterToUse.date(new Date(2018, 0, 15)));
+ }
+ return adapterToUse.isBefore(date as any, adapterToUse.date(new Date(2018, 0, 15)));
+ }}
+ />,
+ );
+
+ openPicker({ type: 'date-range', variant: 'desktop', initialFocus: 'start' });
+
+ const firstPicker = getPickerDay('5', 'January 2018');
+ const secondPicker = getPickerDay('25', 'January 2018');
+
+ expect(firstPicker).not.to.have.attribute('disabled');
+ expect(secondPicker).to.have.attribute('disabled');
+ fireEvent.click(firstPicker);
+
+ expect(firstPicker).to.have.attribute('disabled');
+ expect(secondPicker).not.to.have.attribute('disabled');
+ });
});
it('should highlight the selected range of dates', () => {
diff --git a/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.tsx b/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.tsx
index 75c1b2b43fbd..06d5f1a19ff8 100644
--- a/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.tsx
+++ b/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.tsx
@@ -409,6 +409,7 @@ DesktopDateRangePicker.propTypes = {
* Disable specific date. @DateIOType
* @template TDate
* @param {TDate} day The date to test.
+ * @param {string} position The date to test, 'start' or 'end'.
* @returns {boolean} Returns `true` if the date should be disabled.
*/
shouldDisableDate: PropTypes.func,
diff --git a/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.test.tsx b/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.test.tsx
index 1f27ae6b877f..6fd67c1fa117 100644
--- a/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.test.tsx
+++ b/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.test.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import { spy } from 'sinon';
import { expect } from 'chai';
import TextField from '@mui/material/TextField';
-import { describeConformance, screen, userEvent } from '@mui/monorepo/test/utils';
+import { describeConformance, screen, userEvent, fireEvent } from '@mui/monorepo/test/utils';
import { MobileDateRangePicker } from '@mui/x-date-pickers-pro/MobileDateRangePicker';
import {
wrapPickerMount,
@@ -295,8 +295,37 @@ describe('', () => {
expect(onClose.callCount).to.equal(1);
});
- // TODO: Write test
- // it('should call onClose and onAccept with the live value when clicking outside of the picker', () => {
- // })
+ it('should allow `shouldDisableDate` to depends on start or end date', () => {
+ render(
+ {
+ if (position === 'start') {
+ return adapterToUse.isAfter(date as any, adapterToUse.date(new Date(2018, 0, 15)));
+ }
+ return adapterToUse.isBefore(date as any, adapterToUse.date(new Date(2018, 0, 15)));
+ }}
+ />,
+ );
+
+ openPicker({ type: 'date-range', variant: 'mobile', initialFocus: 'start' });
+
+ const firstPicker = screen.getByText('5');
+ const secondPicker = screen.getByText('25');
+
+ expect(firstPicker).not.to.have.attribute('disabled');
+ expect(secondPicker).to.have.attribute('disabled');
+ fireEvent.click(firstPicker);
+
+ expect(firstPicker).to.have.attribute('disabled');
+ expect(secondPicker).not.to.have.attribute('disabled');
+ });
});
+
+ // TODO: Write test
+ // it('should call onClose and onAccept with the live value when clicking outside of the picker', () => {
+ // })
});
diff --git a/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.tsx b/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.tsx
index 4469c90153bd..d760916118fd 100644
--- a/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.tsx
+++ b/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.tsx
@@ -401,6 +401,7 @@ MobileDateRangePicker.propTypes = {
* Disable specific date. @DateIOType
* @template TDate
* @param {TDate} day The date to test.
+ * @param {string} position The date to test, 'start' or 'end'.
* @returns {boolean} Returns `true` if the date should be disabled.
*/
shouldDisableDate: PropTypes.func,
diff --git a/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.tsx b/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.tsx
index 18c638121208..eb2b58dd3469 100644
--- a/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.tsx
+++ b/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.tsx
@@ -381,6 +381,7 @@ StaticDateRangePicker.propTypes = {
* Disable specific date. @DateIOType
* @template TDate
* @param {TDate} day The date to test.
+ * @param {string} position The date to test, 'start' or 'end'.
* @returns {boolean} Returns `true` if the date should be disabled.
*/
shouldDisableDate: PropTypes.func,
diff --git a/packages/x-date-pickers-pro/src/internal/hooks/validation/useDateRangeValidation.ts b/packages/x-date-pickers-pro/src/internal/hooks/validation/useDateRangeValidation.ts
index c9b1c372dc42..d4420e9b2dd3 100644
--- a/packages/x-date-pickers-pro/src/internal/hooks/validation/useDateRangeValidation.ts
+++ b/packages/x-date-pickers-pro/src/internal/hooks/validation/useDateRangeValidation.ts
@@ -5,13 +5,12 @@ import {
DateValidationError,
validateDate,
BaseDateValidationProps,
- DayValidationProps,
} from '@mui/x-date-pickers/internals';
import { isRangeValid, parseRangeInputValue } from '../../utils/date-utils';
-import { DateRange } from '../../models';
+import { DateRange, DayRangeValidationProps } from '../../models/dateRange';
export interface DateRangeValidationProps
- extends DayValidationProps,
+ extends DayRangeValidationProps,
Required>,
ValidationProps> {}
@@ -27,9 +26,25 @@ export const validateDateRange: Validator !!shouldDisableDate?.(day, 'start'),
+ },
+ }),
+ validateDate({
+ adapter,
+ value: end,
+ props: {
+ ...otherProps,
+ shouldDisableDate: (day) => !!shouldDisableDate?.(day, 'end'),
+ },
+ }),
];
if (dateValidations[0] || dateValidations[1]) {
diff --git a/packages/x-date-pickers-pro/src/internal/models/dateRange.ts b/packages/x-date-pickers-pro/src/internal/models/dateRange.ts
index 79fee141dc0f..1b5245c54874 100644
--- a/packages/x-date-pickers-pro/src/internal/models/dateRange.ts
+++ b/packages/x-date-pickers-pro/src/internal/models/dateRange.ts
@@ -5,3 +5,17 @@ export interface CurrentlySelectingRangeEndProps {
currentlySelectingRangeEnd: 'start' | 'end';
setCurrentlySelectingRangeEnd: (newSelectingEnd: 'start' | 'end') => void;
}
+
+/**
+ * Props used to validate a day value in range pickers.
+ */
+export interface DayRangeValidationProps {
+ /**
+ * Disable specific date. @DateIOType
+ * @template TDate
+ * @param {TDate} day The date to test.
+ * @param {string} position The date to test, 'start' or 'end'.
+ * @returns {boolean} Returns `true` if the date should be disabled.
+ */
+ shouldDisableDate?: (day: TDate, position: 'start' | 'end') => boolean;
+}