From db2fbcca96b91d350424612e62b467dfb13693a6 Mon Sep 17 00:00:00 2001 From: delangle Date: Wed, 4 Sep 2024 12:00:59 +0200 Subject: [PATCH 1/8] [pickers] Clean the validation internals DX to prepare for publication --- .../experimentation/CustomField.js | 52 ++++++++++ .../experimentation/CustomField.tsx | 51 ++++++++++ .../experimentation/CustomField.tsx.preview | 6 ++ .../experimentation/experimentation.md | 11 +++ .../x/react-date-pickers/experimentation.js | 7 ++ .../date-pickers/date-field/date-field.json | 6 +- .../date-pickers/date-picker/date-picker.json | 6 +- .../date-range-picker/date-range-picker.json | 6 +- .../date-time-field/date-time-field.json | 6 +- .../date-time-picker/date-time-picker.json | 6 +- .../date-time-range-picker.json | 6 +- .../desktop-date-picker.json | 6 +- .../desktop-date-range-picker.json | 6 +- .../desktop-date-time-picker.json | 6 +- .../desktop-date-time-range-picker.json | 6 +- .../desktop-time-picker.json | 6 +- .../mobile-date-picker.json | 6 +- .../mobile-date-range-picker.json | 6 +- .../mobile-date-time-picker.json | 6 +- .../mobile-date-time-range-picker.json | 6 +- .../mobile-time-picker.json | 6 +- .../multi-input-date-range-field.json | 6 +- .../multi-input-date-time-range-field.json | 6 +- .../multi-input-time-range-field.json | 6 +- .../single-input-date-range-field.json | 6 +- .../single-input-date-time-range-field.json | 6 +- .../single-input-time-range-field.json | 6 +- .../static-date-picker.json | 6 +- .../static-date-range-picker.json | 6 +- .../static-date-time-picker.json | 6 +- .../static-time-picker.json | 6 +- .../date-pickers/time-field/time-field.json | 6 +- .../date-pickers/time-picker/time-picker.json | 6 +- .../src/DateRangePicker/DateRangePicker.tsx | 10 +- .../DateTimeRangePicker.tsx | 10 +- .../DesktopDateRangePicker.tsx | 15 +-- .../DesktopDateTimeRangePicker.tsx | 14 +-- .../MobileDateRangePicker.tsx | 15 +-- .../MobileDateTimeRangePicker.tsx | 14 +-- .../MultiInputDateRangeField.tsx | 8 +- .../MultiInputDateTimeRangeField.tsx | 8 +- ...nputDateTimeRangeField.validation.test.tsx | 21 ---- ...ibes.MultiInputDateTimeRangeField.test.tsx | 19 +++- .../MultiInputTimeRangeField.tsx | 8 +- ...ltiInputTimeRangeField.validation.test.tsx | 21 ---- ...escribes.MultiInputTimeRangeField.test.tsx | 19 +++- .../SingleInputDateRangeField.tsx | 8 +- .../useSingleInputDateRangeField.ts | 7 +- .../SingleInputDateTimeRangeField.tsx | 8 +- .../useSingleInputDateTimeRangeField.ts | 7 +- .../SingleInputTimeRangeField.tsx | 8 +- .../useSingleInputTimeRangeField.ts | 7 +- .../StaticDateRangePicker.tsx | 12 +-- packages/x-date-pickers-pro/src/index.ts | 1 + .../useDesktopRangePicker.tsx | 8 +- .../useMobileRangePicker.tsx | 8 +- .../useMultiInputDateRangeField.ts | 36 +++---- .../useMultiInputDateTimeRangeField.ts | 35 +++---- .../useMultiInputTimeRangeField.ts | 35 +++---- .../src/validation/index.ts | 8 ++ .../validation/validateDateRange.ts | 32 +++--- .../validation/validateDateTimeRange.ts | 33 +++---- .../validation/validateTimeRange.ts | 28 +++--- .../src/DateCalendar/useIsDateDisabled.ts | 12 +-- .../src/DateField/DateField.tsx | 8 +- .../src/DateField/DateField.types.ts | 16 ++- .../x-date-pickers/src/DateField/index.ts | 1 + .../src/DateField/useDateField.ts | 7 +- .../src/DatePicker/DatePicker.tsx | 10 +- .../src/DateTimeField/DateTimeField.tsx | 8 +- .../src/DateTimeField/DateTimeField.types.ts | 20 +++- .../x-date-pickers/src/DateTimeField/index.ts | 1 + .../src/DateTimeField/useDateTimeField.ts | 7 +- .../src/DateTimePicker/DateTimePicker.tsx | 10 +- .../DesktopDatePicker/DesktopDatePicker.tsx | 13 ++- .../DesktopDateTimePicker.tsx | 13 ++- .../DesktopTimePicker/DesktopTimePicker.tsx | 13 ++- .../src/MobileDatePicker/MobileDatePicker.tsx | 13 ++- .../MobileDateTimePicker.tsx | 13 ++- .../src/MobileTimePicker/MobileTimePicker.tsx | 13 ++- .../src/StaticDatePicker/StaticDatePicker.tsx | 12 +-- .../StaticDateTimePicker.tsx | 12 +-- .../src/StaticTimePicker/StaticTimePicker.tsx | 12 +-- .../src/TimeField/TimeField.tsx | 8 +- .../src/TimeField/TimeField.types.ts | 16 ++- .../x-date-pickers/src/TimeField/index.ts | 1 + .../src/TimeField/useTimeField.ts | 7 +- .../src/TimePicker/TimePicker.tsx | 10 +- packages/x-date-pickers/src/index.ts | 3 +- .../useDesktopPicker/useDesktopPicker.tsx | 2 +- .../src/internals/hooks/useField/useField.ts | 17 ++-- .../hooks/useField/useField.types.ts | 31 ++---- .../internals/hooks/useField/useFieldState.ts | 5 +- .../hooks/useMobilePicker/useMobilePicker.tsx | 2 +- .../internals/hooks/usePicker/usePicker.ts | 3 +- .../hooks/usePicker/usePickerValue.ts | 29 +++--- .../hooks/usePicker/usePickerValue.types.ts | 24 +---- .../src/internals/hooks/useValidation.ts | 63 ------------ .../x-date-pickers/src/internals/index.ts | 6 -- .../src/internals/utils/fields.ts | 18 ++-- .../utils/validation/validateDateTime.ts | 31 ------ .../x-date-pickers/src/models/validation.ts | 18 ++++ .../validation/extractValidationProps.ts | 2 +- .../x-date-pickers/src/validation/index.ts | 13 +++ .../src/validation/useValidation.ts | 99 +++++++++++++++++++ .../utils => }/validation/validateDate.ts | 31 +++--- .../src/validation/validateDateTime.ts | 36 +++++++ .../utils => }/validation/validateTime.ts | 22 ++--- scripts/x-date-pickers-pro.exports.json | 20 ++++ scripts/x-date-pickers.exports.json | 14 +++ 110 files changed, 853 insertions(+), 650 deletions(-) create mode 100644 docs/data/date-pickers/experimentation/CustomField.js create mode 100644 docs/data/date-pickers/experimentation/CustomField.tsx create mode 100644 docs/data/date-pickers/experimentation/CustomField.tsx.preview create mode 100644 docs/data/date-pickers/experimentation/experimentation.md create mode 100644 docs/pages/x/react-date-pickers/experimentation.js delete mode 100644 packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/MultiInputDateTimeRangeField.validation.test.tsx delete mode 100644 packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/MultiInputTimeRangeField.validation.test.tsx create mode 100644 packages/x-date-pickers-pro/src/validation/index.ts rename packages/x-date-pickers-pro/src/{internals/utils => }/validation/validateDateRange.ts (55%) rename packages/x-date-pickers-pro/src/{internals/utils => }/validation/validateDateTimeRange.ts (55%) rename packages/x-date-pickers-pro/src/{internals/utils => }/validation/validateTimeRange.ts (52%) delete mode 100644 packages/x-date-pickers/src/internals/hooks/useValidation.ts delete mode 100644 packages/x-date-pickers/src/internals/utils/validation/validateDateTime.ts rename packages/x-date-pickers/src/{internals/utils => }/validation/extractValidationProps.ts (97%) create mode 100644 packages/x-date-pickers/src/validation/index.ts create mode 100644 packages/x-date-pickers/src/validation/useValidation.ts rename packages/x-date-pickers/src/{internals/utils => }/validation/validateDate.ts (67%) create mode 100644 packages/x-date-pickers/src/validation/validateDateTime.ts rename packages/x-date-pickers/src/{internals/utils => }/validation/validateTime.ts (73%) diff --git a/docs/data/date-pickers/experimentation/CustomField.js b/docs/data/date-pickers/experimentation/CustomField.js new file mode 100644 index 000000000000..109be3934956 --- /dev/null +++ b/docs/data/date-pickers/experimentation/CustomField.js @@ -0,0 +1,52 @@ +import * as React from 'react'; +import dayjs from 'dayjs'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; +import TextField from '@mui/material/TextField'; + +import { useValidation, validateDate } from '@mui/x-date-pickers/validation'; + +import { splitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/internals'; + +function ReadOnlyField(props) { + const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps( + props, + 'date', + ); + + const { value, timezone, format } = internalProps; + const { InputProps, slotProps, slots, ...other } = forwardedProps; + + const { hasValidationError } = useValidation({ + validator: validateDate, + value, + timezone, + props: internalProps, + }); + + return ( + + ); +} + +export default function CustomField() { + return ( + + + + + + ); +} diff --git a/docs/data/date-pickers/experimentation/CustomField.tsx b/docs/data/date-pickers/experimentation/CustomField.tsx new file mode 100644 index 000000000000..7cd411931895 --- /dev/null +++ b/docs/data/date-pickers/experimentation/CustomField.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; +import dayjs, { Dayjs } from 'dayjs'; +import TextField from '@mui/material/TextField'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; +import { useValidation, validateDate } from '@mui/x-date-pickers/validation'; +import { DateFieldInPickerProps } from '@mui/x-date-pickers/DateField'; +import { splitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/internals'; + +function ReadOnlyField(props: DateFieldInPickerProps) { + const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps( + props, + 'date', + ); + + const { value, timezone, format } = internalProps; + const { InputProps, slotProps, slots, ...other } = forwardedProps; + + const { hasValidationError } = useValidation({ + validator: validateDate, + value, + timezone, + props: internalProps, + }); + + return ( + + ); +} + +export default function CustomField() { + return ( + + + + + + ); +} diff --git a/docs/data/date-pickers/experimentation/CustomField.tsx.preview b/docs/data/date-pickers/experimentation/CustomField.tsx.preview new file mode 100644 index 000000000000..b489d70b2175 --- /dev/null +++ b/docs/data/date-pickers/experimentation/CustomField.tsx.preview @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/docs/data/date-pickers/experimentation/experimentation.md b/docs/data/date-pickers/experimentation/experimentation.md new file mode 100644 index 000000000000..d5f906e32868 --- /dev/null +++ b/docs/data/date-pickers/experimentation/experimentation.md @@ -0,0 +1,11 @@ +--- +productId: x-date-pickers +--- + +# Date and Time Pickers experimentation + +

Demos not accessible through the navbar of the doc

+ +## Custom field + +{{"demo": "CustomField.js"}} diff --git a/docs/pages/x/react-date-pickers/experimentation.js b/docs/pages/x/react-date-pickers/experimentation.js new file mode 100644 index 000000000000..bf599b0bb69e --- /dev/null +++ b/docs/pages/x/react-date-pickers/experimentation.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/date-pickers/experimentation/experimentation.md?muiMarkdown'; + +export default function Page() { + return ; +} diff --git a/docs/translations/api-docs/date-pickers/date-field/date-field.json b/docs/translations/api-docs/date-pickers/date-field/date-field.json index e023b91557cb..618744b87c46 100644 --- a/docs/translations/api-docs/date-pickers/date-field/date-field.json +++ b/docs/translations/api-docs/date-pickers/date-field/date-field.json @@ -66,10 +66,10 @@ }, "onClear": { "description": "Callback fired when the clear button is clicked." }, "onError": { - "description": "Callback fired when the error associated to the current value changes.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onSelectedSectionsChange": { diff --git a/docs/translations/api-docs/date-pickers/date-picker/date-picker.json b/docs/translations/api-docs/date-pickers/date-picker/date-picker.json index fa776f7501a5..5555b7f4ffa4 100644 --- a/docs/translations/api-docs/date-pickers/date-picker/date-picker.json +++ b/docs/translations/api-docs/date-pickers/date-picker/date-picker.json @@ -77,10 +77,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/date-range-picker/date-range-picker.json b/docs/translations/api-docs/date-pickers/date-range-picker/date-range-picker.json index b847113e3e87..e36497d59678 100644 --- a/docs/translations/api-docs/date-pickers/date-range-picker/date-range-picker.json +++ b/docs/translations/api-docs/date-pickers/date-range-picker/date-range-picker.json @@ -91,10 +91,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/date-time-field/date-time-field.json b/docs/translations/api-docs/date-pickers/date-time-field/date-time-field.json index 4e77982370d0..95121dacea2d 100644 --- a/docs/translations/api-docs/date-pickers/date-time-field/date-time-field.json +++ b/docs/translations/api-docs/date-pickers/date-time-field/date-time-field.json @@ -83,10 +83,10 @@ }, "onClear": { "description": "Callback fired when the clear button is clicked." }, "onError": { - "description": "Callback fired when the error associated to the current value changes.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onSelectedSectionsChange": { diff --git a/docs/translations/api-docs/date-pickers/date-time-picker/date-time-picker.json b/docs/translations/api-docs/date-pickers/date-time-picker/date-time-picker.json index e6bc667be2c4..d9f6a88b0bac 100644 --- a/docs/translations/api-docs/date-pickers/date-time-picker/date-time-picker.json +++ b/docs/translations/api-docs/date-pickers/date-time-picker/date-time-picker.json @@ -97,10 +97,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/date-time-range-picker/date-time-range-picker.json b/docs/translations/api-docs/date-pickers/date-time-range-picker/date-time-range-picker.json index 38ff71b4a0bc..5c365483d5c3 100644 --- a/docs/translations/api-docs/date-pickers/date-time-range-picker/date-time-range-picker.json +++ b/docs/translations/api-docs/date-pickers/date-time-range-picker/date-time-range-picker.json @@ -108,10 +108,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/desktop-date-picker/desktop-date-picker.json b/docs/translations/api-docs/date-pickers/desktop-date-picker/desktop-date-picker.json index bd5ad6552128..c87e5e21816d 100644 --- a/docs/translations/api-docs/date-pickers/desktop-date-picker/desktop-date-picker.json +++ b/docs/translations/api-docs/date-pickers/desktop-date-picker/desktop-date-picker.json @@ -74,10 +74,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/desktop-date-range-picker/desktop-date-range-picker.json b/docs/translations/api-docs/date-pickers/desktop-date-range-picker/desktop-date-range-picker.json index 280773356bff..064000584821 100644 --- a/docs/translations/api-docs/date-pickers/desktop-date-range-picker/desktop-date-range-picker.json +++ b/docs/translations/api-docs/date-pickers/desktop-date-range-picker/desktop-date-range-picker.json @@ -88,10 +88,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/desktop-date-time-picker/desktop-date-time-picker.json b/docs/translations/api-docs/date-pickers/desktop-date-time-picker/desktop-date-time-picker.json index 850e02434af9..fd18750143b3 100644 --- a/docs/translations/api-docs/date-pickers/desktop-date-time-picker/desktop-date-time-picker.json +++ b/docs/translations/api-docs/date-pickers/desktop-date-time-picker/desktop-date-time-picker.json @@ -94,10 +94,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/desktop-date-time-range-picker/desktop-date-time-range-picker.json b/docs/translations/api-docs/date-pickers/desktop-date-time-range-picker/desktop-date-time-range-picker.json index 44308fe67c43..e078dbbc15d4 100644 --- a/docs/translations/api-docs/date-pickers/desktop-date-time-range-picker/desktop-date-time-range-picker.json +++ b/docs/translations/api-docs/date-pickers/desktop-date-time-range-picker/desktop-date-time-range-picker.json @@ -105,10 +105,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/desktop-time-picker/desktop-time-picker.json b/docs/translations/api-docs/date-pickers/desktop-time-picker/desktop-time-picker.json index cb08e6dbe9b5..4ddf39b2d428 100644 --- a/docs/translations/api-docs/date-pickers/desktop-time-picker/desktop-time-picker.json +++ b/docs/translations/api-docs/date-pickers/desktop-time-picker/desktop-time-picker.json @@ -66,10 +66,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onOpen": { diff --git a/docs/translations/api-docs/date-pickers/mobile-date-picker/mobile-date-picker.json b/docs/translations/api-docs/date-pickers/mobile-date-picker/mobile-date-picker.json index 6fdc6eaca82e..79e03e073898 100644 --- a/docs/translations/api-docs/date-pickers/mobile-date-picker/mobile-date-picker.json +++ b/docs/translations/api-docs/date-pickers/mobile-date-picker/mobile-date-picker.json @@ -74,10 +74,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/mobile-date-range-picker/mobile-date-range-picker.json b/docs/translations/api-docs/date-pickers/mobile-date-range-picker/mobile-date-range-picker.json index 4f31ae0b2920..9979387f247d 100644 --- a/docs/translations/api-docs/date-pickers/mobile-date-range-picker/mobile-date-range-picker.json +++ b/docs/translations/api-docs/date-pickers/mobile-date-range-picker/mobile-date-range-picker.json @@ -85,10 +85,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/mobile-date-time-picker/mobile-date-time-picker.json b/docs/translations/api-docs/date-pickers/mobile-date-time-picker/mobile-date-time-picker.json index 3731b8d7d2f7..4d5af5592845 100644 --- a/docs/translations/api-docs/date-pickers/mobile-date-time-picker/mobile-date-time-picker.json +++ b/docs/translations/api-docs/date-pickers/mobile-date-time-picker/mobile-date-time-picker.json @@ -94,10 +94,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/mobile-date-time-range-picker/mobile-date-time-range-picker.json b/docs/translations/api-docs/date-pickers/mobile-date-time-range-picker/mobile-date-time-range-picker.json index 743e5f688d34..c2eb9b111653 100644 --- a/docs/translations/api-docs/date-pickers/mobile-date-time-range-picker/mobile-date-time-range-picker.json +++ b/docs/translations/api-docs/date-pickers/mobile-date-time-range-picker/mobile-date-time-range-picker.json @@ -102,10 +102,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/mobile-time-picker/mobile-time-picker.json b/docs/translations/api-docs/date-pickers/mobile-time-picker/mobile-time-picker.json index cd9f9871246e..9e4aee022d83 100644 --- a/docs/translations/api-docs/date-pickers/mobile-time-picker/mobile-time-picker.json +++ b/docs/translations/api-docs/date-pickers/mobile-time-picker/mobile-time-picker.json @@ -66,10 +66,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onOpen": { diff --git a/docs/translations/api-docs/date-pickers/multi-input-date-range-field/multi-input-date-range-field.json b/docs/translations/api-docs/date-pickers/multi-input-date-range-field/multi-input-date-range-field.json index 3249b81c4e44..5091832ca274 100644 --- a/docs/translations/api-docs/date-pickers/multi-input-date-range-field/multi-input-date-range-field.json +++ b/docs/translations/api-docs/date-pickers/multi-input-date-range-field/multi-input-date-range-field.json @@ -34,10 +34,10 @@ } }, "onError": { - "description": "Callback fired when the error associated to the current value changes.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onSelectedSectionsChange": { diff --git a/docs/translations/api-docs/date-pickers/multi-input-date-time-range-field/multi-input-date-time-range-field.json b/docs/translations/api-docs/date-pickers/multi-input-date-time-range-field/multi-input-date-time-range-field.json index 5a80d81c50d9..2657b5ed1a3f 100644 --- a/docs/translations/api-docs/date-pickers/multi-input-date-time-range-field/multi-input-date-time-range-field.json +++ b/docs/translations/api-docs/date-pickers/multi-input-date-time-range-field/multi-input-date-time-range-field.json @@ -51,10 +51,10 @@ } }, "onError": { - "description": "Callback fired when the error associated to the current value changes.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onSelectedSectionsChange": { diff --git a/docs/translations/api-docs/date-pickers/multi-input-time-range-field/multi-input-time-range-field.json b/docs/translations/api-docs/date-pickers/multi-input-time-range-field/multi-input-time-range-field.json index 36121c5af67d..29a60e20be62 100644 --- a/docs/translations/api-docs/date-pickers/multi-input-time-range-field/multi-input-time-range-field.json +++ b/docs/translations/api-docs/date-pickers/multi-input-time-range-field/multi-input-time-range-field.json @@ -43,10 +43,10 @@ } }, "onError": { - "description": "Callback fired when the error associated to the current value changes.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onSelectedSectionsChange": { diff --git a/docs/translations/api-docs/date-pickers/single-input-date-range-field/single-input-date-range-field.json b/docs/translations/api-docs/date-pickers/single-input-date-range-field/single-input-date-range-field.json index 4b27f2a62221..a24a00361f7d 100644 --- a/docs/translations/api-docs/date-pickers/single-input-date-range-field/single-input-date-range-field.json +++ b/docs/translations/api-docs/date-pickers/single-input-date-range-field/single-input-date-range-field.json @@ -67,10 +67,10 @@ }, "onClear": { "description": "Callback fired when the clear button is clicked." }, "onError": { - "description": "Callback fired when the error associated to the current value changes.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onSelectedSectionsChange": { diff --git a/docs/translations/api-docs/date-pickers/single-input-date-time-range-field/single-input-date-time-range-field.json b/docs/translations/api-docs/date-pickers/single-input-date-time-range-field/single-input-date-time-range-field.json index 2fd5f3960613..e98b84401aca 100644 --- a/docs/translations/api-docs/date-pickers/single-input-date-time-range-field/single-input-date-time-range-field.json +++ b/docs/translations/api-docs/date-pickers/single-input-date-time-range-field/single-input-date-time-range-field.json @@ -84,10 +84,10 @@ }, "onClear": { "description": "Callback fired when the clear button is clicked." }, "onError": { - "description": "Callback fired when the error associated to the current value changes.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onSelectedSectionsChange": { diff --git a/docs/translations/api-docs/date-pickers/single-input-time-range-field/single-input-time-range-field.json b/docs/translations/api-docs/date-pickers/single-input-time-range-field/single-input-time-range-field.json index d14d95e0e73b..7814309458a6 100644 --- a/docs/translations/api-docs/date-pickers/single-input-time-range-field/single-input-time-range-field.json +++ b/docs/translations/api-docs/date-pickers/single-input-time-range-field/single-input-time-range-field.json @@ -76,10 +76,10 @@ }, "onClear": { "description": "Callback fired when the clear button is clicked." }, "onError": { - "description": "Callback fired when the error associated to the current value changes.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onSelectedSectionsChange": { diff --git a/docs/translations/api-docs/date-pickers/static-date-picker/static-date-picker.json b/docs/translations/api-docs/date-pickers/static-date-picker/static-date-picker.json index 7ebb4803d895..289d1ade78f4 100644 --- a/docs/translations/api-docs/date-pickers/static-date-picker/static-date-picker.json +++ b/docs/translations/api-docs/date-pickers/static-date-picker/static-date-picker.json @@ -60,10 +60,10 @@ "description": "Callback fired when component requests to be closed. Can be fired when selecting (by default on desktop mode) or clearing a value." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/static-date-range-picker/static-date-range-picker.json b/docs/translations/api-docs/date-pickers/static-date-range-picker/static-date-range-picker.json index a5948b80f383..902cddeda703 100644 --- a/docs/translations/api-docs/date-pickers/static-date-range-picker/static-date-range-picker.json +++ b/docs/translations/api-docs/date-pickers/static-date-range-picker/static-date-range-picker.json @@ -70,10 +70,10 @@ "description": "Callback fired when component requests to be closed. Can be fired when selecting (by default on desktop mode) or clearing a value." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/static-date-time-picker/static-date-time-picker.json b/docs/translations/api-docs/date-pickers/static-date-time-picker/static-date-time-picker.json index 49348e673329..f249adf4217e 100644 --- a/docs/translations/api-docs/date-pickers/static-date-time-picker/static-date-time-picker.json +++ b/docs/translations/api-docs/date-pickers/static-date-time-picker/static-date-time-picker.json @@ -80,10 +80,10 @@ "description": "Callback fired when component requests to be closed. Can be fired when selecting (by default on desktop mode) or clearing a value." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onMonthChange": { diff --git a/docs/translations/api-docs/date-pickers/static-time-picker/static-time-picker.json b/docs/translations/api-docs/date-pickers/static-time-picker/static-time-picker.json index 8ba5b454d5e6..df19b36acd95 100644 --- a/docs/translations/api-docs/date-pickers/static-time-picker/static-time-picker.json +++ b/docs/translations/api-docs/date-pickers/static-time-picker/static-time-picker.json @@ -52,10 +52,10 @@ "description": "Callback fired when component requests to be closed. Can be fired when selecting (by default on desktop mode) or clearing a value." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onViewChange": { diff --git a/docs/translations/api-docs/date-pickers/time-field/time-field.json b/docs/translations/api-docs/date-pickers/time-field/time-field.json index afe127369650..e54b304b64b5 100644 --- a/docs/translations/api-docs/date-pickers/time-field/time-field.json +++ b/docs/translations/api-docs/date-pickers/time-field/time-field.json @@ -75,10 +75,10 @@ }, "onClear": { "description": "Callback fired when the clear button is clicked." }, "onError": { - "description": "Callback fired when the error associated to the current value changes.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onSelectedSectionsChange": { diff --git a/docs/translations/api-docs/date-pickers/time-picker/time-picker.json b/docs/translations/api-docs/date-pickers/time-picker/time-picker.json index 3e18c58879a8..17d4ee6c9f6a 100644 --- a/docs/translations/api-docs/date-pickers/time-picker/time-picker.json +++ b/docs/translations/api-docs/date-pickers/time-picker/time-picker.json @@ -69,10 +69,10 @@ "description": "Callback fired when the popup requests to be closed. Use in controlled mode (see open)." }, "onError": { - "description": "Callback fired when the error associated to the current value changes. If the error has a non-null value, then the TextField will be rendered in error state.", + "description": "Callback fired when the error associated to the current value changes. When a validation error is detected, the error parameter contains a non-null value. This can be used to render an appropriate form error.", "typeDescriptions": { - "error": "The new error describing why the current value is not valid.", - "value": "The value associated to the error." + "error": "The reason why the current value is not valid.", + "value": "The value associated to the error" } }, "onOpen": { diff --git a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.tsx b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.tsx index 7fa21dbb2ee8..8002fc939798 100644 --- a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.tsx @@ -217,12 +217,12 @@ DateRangePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePicker.tsx b/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePicker.tsx index 4d94546246f8..9249006814e5 100644 --- a/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePicker.tsx @@ -250,12 +250,12 @@ DateTimeRangePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.tsx b/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.tsx index 1a583b12807b..025c7c1ca786 100644 --- a/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/DesktopDateRangePicker/DesktopDateRangePicker.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; -import { extractValidationProps, PickerViewRendererLookup } from '@mui/x-date-pickers/internals'; +import { PickerViewRendererLookup } from '@mui/x-date-pickers/internals'; +import { extractValidationProps } from '@mui/x-date-pickers/validation'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import resolveComponentProps from '@mui/utils/resolveComponentProps'; import { refType } from '@mui/utils'; @@ -10,7 +11,7 @@ import { useDateRangePickerDefaultizedProps } from '../DateRangePicker/shared'; import { renderDateRangeViewCalendar } from '../dateRangeViewRenderers'; import { MultiInputDateRangeField } from '../MultiInputDateRangeField'; import { useDesktopRangePicker } from '../internals/hooks/useDesktopRangePicker'; -import { validateDateRange } from '../internals/utils/validation/validateDateRange'; +import { validateDateRange } from '../validation'; import { DateRange } from '../models'; type DesktopDateRangePickerComponent = (< @@ -252,12 +253,12 @@ DesktopDateRangePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/DesktopDateTimeRangePicker.tsx b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/DesktopDateTimeRangePicker.tsx index 069e4d66cc75..89e375c96dab 100644 --- a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/DesktopDateTimeRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/DesktopDateTimeRangePicker.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { DefaultizedProps, - extractValidationProps, isDatePickerView, isInternalTimeView, PickerViewRenderer, @@ -10,6 +9,7 @@ import { resolveDateTimeFormat, useUtils, } from '@mui/x-date-pickers/internals'; +import { extractValidationProps } from '@mui/x-date-pickers/validation'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import resolveComponentProps from '@mui/utils/resolveComponentProps'; import { refType } from '@mui/utils'; @@ -32,7 +32,7 @@ import { useDesktopRangePicker, UseDesktopRangePickerProps, } from '../internals/hooks/useDesktopRangePicker'; -import { validateDateTimeRange } from '../internals/utils/validation/validateDateTimeRange'; +import { validateDateTimeRange } from '../validation'; import { DateTimeRangePickerView } from '../internals/models'; import { DateRange } from '../models'; import { @@ -418,12 +418,12 @@ DesktopDateTimeRangePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.tsx b/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.tsx index 54558b1607ea..c3605de2d5ac 100644 --- a/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/MobileDateRangePicker/MobileDateRangePicker.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; -import { extractValidationProps, PickerViewRendererLookup } from '@mui/x-date-pickers/internals'; +import { PickerViewRendererLookup } from '@mui/x-date-pickers/internals'; +import { extractValidationProps } from '@mui/x-date-pickers/validation'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import resolveComponentProps from '@mui/utils/resolveComponentProps'; import { refType } from '@mui/utils'; @@ -10,7 +11,7 @@ import { useDateRangePickerDefaultizedProps } from '../DateRangePicker/shared'; import { renderDateRangeViewCalendar } from '../dateRangeViewRenderers'; import { MultiInputDateRangeField } from '../MultiInputDateRangeField'; import { useMobileRangePicker } from '../internals/hooks/useMobileRangePicker'; -import { validateDateRange } from '../internals/utils/validation/validateDateRange'; +import { validateDateRange } from '../validation'; import { DateRange } from '../models'; type MobileDateRangePickerComponent = (< @@ -248,12 +249,12 @@ MobileDateRangePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/MobileDateTimeRangePicker.tsx b/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/MobileDateTimeRangePicker.tsx index 27036c430d8e..cdbabfe04eea 100644 --- a/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/MobileDateTimeRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/MobileDateTimeRangePicker.tsx @@ -4,7 +4,6 @@ import { refType } from '@mui/utils'; import { DIALOG_WIDTH, VIEW_HEIGHT, - extractValidationProps, isInternalTimeView, isDatePickerView, PickerViewRenderer, @@ -14,6 +13,7 @@ import { resolveDateTimeFormat, useUtils, } from '@mui/x-date-pickers/internals'; +import { extractValidationProps } from '@mui/x-date-pickers/validation'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import resolveComponentProps from '@mui/utils/resolveComponentProps'; import { @@ -32,7 +32,7 @@ import { UseMobileRangePickerProps, useMobileRangePicker, } from '../internals/hooks/useMobileRangePicker'; -import { validateDateTimeRange } from '../internals/utils/validation/validateDateTimeRange'; +import { validateDateTimeRange } from '../validation'; import { DateTimeRangePickerView } from '../internals/models'; import { DateRange } from '../models'; import { @@ -408,12 +408,12 @@ MobileDateTimeRangePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx index 909fc6c29e7c..4fb1f4622428 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx @@ -270,10 +270,12 @@ MultiInputDateRangeField.propTypes = { onChange: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx index 133685debe58..95eee8c613eb 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx @@ -302,10 +302,12 @@ MultiInputDateTimeRangeField.propTypes = { onChange: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/MultiInputDateTimeRangeField.validation.test.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/MultiInputDateTimeRangeField.validation.test.tsx deleted file mode 100644 index 4fd962807ba7..000000000000 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/MultiInputDateTimeRangeField.validation.test.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { MultiInputDateTimeRangeField } from '@mui/x-date-pickers-pro/MultiInputDateTimeRangeField'; -import { - createPickerRenderer, - adapterToUse, - describeRangeValidation, - setValueOnFieldInput, -} from 'test/utils/pickers'; - -describe('', () => { - const { render, clock } = createPickerRenderer({ clock: 'fake' }); - - describeRangeValidation(MultiInputDateTimeRangeField, () => ({ - render, - clock, - componentFamily: 'field', - views: ['year', 'month', 'day', 'hours', 'minutes'], - setValue: (value, { setEndDate } = {}) => { - setValueOnFieldInput(adapterToUse.format(value, 'keyboardDateTime'), setEndDate ? 1 : 0); - }, - })); -}); diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/describes.MultiInputDateTimeRangeField.test.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/describes.MultiInputDateTimeRangeField.test.tsx index 7bb1d6cc437b..5bc464f729e5 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/describes.MultiInputDateTimeRangeField.test.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/describes.MultiInputDateTimeRangeField.test.tsx @@ -1,10 +1,15 @@ import * as React from 'react'; import { MultiInputDateTimeRangeField } from '@mui/x-date-pickers-pro/MultiInputDateTimeRangeField'; -import { createPickerRenderer } from 'test/utils/pickers'; +import { + adapterToUse, + createPickerRenderer, + describeRangeValidation, + setValueOnFieldInput, +} from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe('', () => { - const { render } = createPickerRenderer(); + const { render, clock } = createPickerRenderer(); describeConformance(, () => ({ classes: {} as any, @@ -14,4 +19,14 @@ describe('', () => { refInstanceof: window.HTMLDivElement, skip: ['componentProp', 'componentsProp', 'themeVariants'], })); + + describeRangeValidation(MultiInputDateTimeRangeField, () => ({ + render, + clock, + componentFamily: 'field', + views: ['year', 'month', 'day', 'hours', 'minutes'], + setValue: (value, { setEndDate } = {}) => { + setValueOnFieldInput(adapterToUse.format(value, 'keyboardDateTime'), setEndDate ? 1 : 0); + }, + })); }); diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx index ee04099dff91..a682b755b87b 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx @@ -287,10 +287,12 @@ MultiInputTimeRangeField.propTypes = { onChange: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/MultiInputTimeRangeField.validation.test.tsx b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/MultiInputTimeRangeField.validation.test.tsx deleted file mode 100644 index a84da9d27b0a..000000000000 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/MultiInputTimeRangeField.validation.test.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { MultiInputTimeRangeField } from '@mui/x-date-pickers-pro/MultiInputTimeRangeField'; -import { - createPickerRenderer, - adapterToUse, - describeRangeValidation, - setValueOnFieldInput, -} from 'test/utils/pickers'; - -describe('', () => { - const { render, clock } = createPickerRenderer({ clock: 'fake' }); - - describeRangeValidation(MultiInputTimeRangeField, () => ({ - render, - clock, - componentFamily: 'field', - views: ['hours', 'minutes'], - setValue: (value, { setEndDate } = {}) => { - setValueOnFieldInput(adapterToUse.format(value, 'fullTime'), setEndDate ? 1 : 0); - }, - })); -}); diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/describes.MultiInputTimeRangeField.test.tsx b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/describes.MultiInputTimeRangeField.test.tsx index 47047c3007d4..f25cd1cd33f4 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/describes.MultiInputTimeRangeField.test.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/describes.MultiInputTimeRangeField.test.tsx @@ -1,10 +1,15 @@ import * as React from 'react'; import { MultiInputTimeRangeField } from '@mui/x-date-pickers-pro/MultiInputTimeRangeField'; -import { createPickerRenderer } from 'test/utils/pickers'; +import { + adapterToUse, + createPickerRenderer, + describeRangeValidation, + setValueOnFieldInput, +} from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe('', () => { - const { render } = createPickerRenderer(); + const { render, clock } = createPickerRenderer(); describeConformance(, () => ({ classes: {} as any, @@ -14,4 +19,14 @@ describe('', () => { refInstanceof: window.HTMLDivElement, skip: ['themeVariants', 'componentProp', 'componentsProp'], })); + + describeRangeValidation(MultiInputTimeRangeField, () => ({ + render, + clock, + componentFamily: 'field', + views: ['hours', 'minutes'], + setValue: (value, { setEndDate } = {}) => { + setValueOnFieldInput(adapterToUse.format(value, 'fullTime'), setEndDate ? 1 : 0); + }, + })); }); diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.tsx b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.tsx index edc1e5b91b69..88e25ad3ff8e 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.tsx +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.tsx @@ -230,10 +230,12 @@ SingleInputDateRangeField.propTypes = { onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, onFocus: PropTypes.func, diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts index acd9177c5fa6..4ea36bb67943 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts @@ -7,7 +7,7 @@ import { import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputDateRangeFieldProps } from './SingleInputDateRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; -import { validateDateRange } from '../internals/utils/validation/validateDateRange'; +import { validateDateRange } from '../validation'; import { RangeFieldSection, DateRange } from '../models'; export const useSingleInputDateRangeField = < @@ -23,10 +23,7 @@ export const useSingleInputDateRangeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseSingleInputDateRangeFieldProps - >(props, 'date'); + const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps(props, 'date'); const fieldValueManager = React.useMemo( () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.tsx b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.tsx index 57d0a57f3a91..aded6d5ac205 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.tsx @@ -263,10 +263,12 @@ SingleInputDateTimeRangeField.propTypes = { onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, onFocus: PropTypes.func, diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts index c27ab9b259b3..8b9ba5ea901f 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts @@ -7,7 +7,7 @@ import { import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputDateTimeRangeFieldProps } from './SingleInputDateTimeRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; -import { validateDateTimeRange } from '../internals/utils/validation/validateDateTimeRange'; +import { validateDateTimeRange } from '../validation'; import { RangeFieldSection, DateRange } from '../models'; export const useSingleInputDateTimeRangeField = < @@ -26,10 +26,7 @@ export const useSingleInputDateTimeRangeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseSingleInputDateTimeRangeFieldProps - >(props, 'date-time'); + const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps(props, 'date-time'); const fieldValueManager = React.useMemo( () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.tsx b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.tsx index cd37622a001e..414b36c21cf2 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.tsx @@ -245,10 +245,12 @@ SingleInputTimeRangeField.propTypes = { onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, onFocus: PropTypes.func, diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts index 98d9703e7eb8..b8a39c03e738 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts @@ -7,7 +7,7 @@ import { import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputTimeRangeFieldProps } from './SingleInputTimeRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; -import { validateTimeRange } from '../internals/utils/validation/validateTimeRange'; +import { validateTimeRange } from '../validation'; import { RangeFieldSection, DateRange } from '../models'; export const useSingleInputTimeRangeField = < @@ -23,10 +23,7 @@ export const useSingleInputTimeRangeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseSingleInputTimeRangeFieldProps - >(props, 'time'); + const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps(props, 'time'); const fieldValueManager = React.useMemo( () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), diff --git a/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.tsx b/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.tsx index 74ff932d922d..163cfddca378 100644 --- a/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.tsx @@ -7,7 +7,7 @@ import { StaticDateRangePickerProps } from './StaticDateRangePicker.types'; import { useDateRangePickerDefaultizedProps } from '../DateRangePicker/shared'; import { renderDateRangeViewCalendar } from '../dateRangeViewRenderers'; import { rangeValueManager } from '../internals/utils/valueManagers'; -import { validateDateRange } from '../internals/utils/validation/validateDateRange'; +import { validateDateRange } from '../validation'; import { DateRange } from '../models'; type StaticDateRangePickerComponent = (( @@ -197,12 +197,12 @@ StaticDateRangePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers-pro/src/index.ts b/packages/x-date-pickers-pro/src/index.ts index 55114fb14fb8..8a7bb7e61c04 100644 --- a/packages/x-date-pickers-pro/src/index.ts +++ b/packages/x-date-pickers-pro/src/index.ts @@ -35,3 +35,4 @@ export * from './MobileDateTimeRangePicker'; export * from './dateRangeViewRenderers'; export * from './models'; +export * from './validation'; diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useDesktopRangePicker/useDesktopRangePicker.tsx b/packages/x-date-pickers-pro/src/internals/hooks/useDesktopRangePicker/useDesktopRangePicker.tsx index cb635fdba2ca..55d56d9b6ca5 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useDesktopRangePicker/useDesktopRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/internals/hooks/useDesktopRangePicker/useDesktopRangePicker.tsx @@ -8,12 +8,16 @@ import { getActiveElement, usePicker, PickersPopper, - InferError, ExportedBaseToolbarProps, DateOrTimeViewWithMeridiem, ExportedBaseTabsProps, } from '@mui/x-date-pickers/internals'; -import { PickerValidDate, FieldRef, BaseSingleInputFieldProps } from '@mui/x-date-pickers/models'; +import { + PickerValidDate, + FieldRef, + BaseSingleInputFieldProps, + InferError, +} from '@mui/x-date-pickers/models'; import { DesktopRangePickerAdditionalViewProps, UseDesktopRangePickerParams, diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useMobileRangePicker/useMobileRangePicker.tsx b/packages/x-date-pickers-pro/src/internals/hooks/useMobileRangePicker/useMobileRangePicker.tsx index 8c0ff7404326..518914bdb1b5 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMobileRangePicker/useMobileRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMobileRangePicker/useMobileRangePicker.tsx @@ -6,13 +6,17 @@ import { PickersLayout, PickersLayoutSlotProps } from '@mui/x-date-pickers/Picke import { usePicker, PickersModalDialog, - InferError, ExportedBaseToolbarProps, DateOrTimeViewWithMeridiem, ExportedBaseTabsProps, } from '@mui/x-date-pickers/internals'; import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; -import { PickerValidDate, FieldRef, BaseSingleInputFieldProps } from '@mui/x-date-pickers/models'; +import { + PickerValidDate, + FieldRef, + BaseSingleInputFieldProps, + InferError, +} from '@mui/x-date-pickers/models'; import useId from '@mui/utils/useId'; import { MobileRangePickerAdditionalViewProps, diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField.ts b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField.ts index 84dfaeeb8631..f89396ebc68b 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField.ts @@ -4,23 +4,19 @@ import { UseDateFieldComponentProps, } from '@mui/x-date-pickers/DateField'; import { - useLocalizationContext, - useValidation, FieldChangeHandler, FieldChangeHandlerContext, UseFieldResponse, useControlledValueWithTimezone, useDefaultizedDateField, } from '@mui/x-date-pickers/internals'; +import { useValidation } from '@mui/x-date-pickers/validation'; import { DateValidationError, PickerValidDate } from '@mui/x-date-pickers/models'; import { UseMultiInputDateRangeFieldParams, UseMultiInputDateRangeFieldProps, } from '../../../MultiInputDateRangeField/MultiInputDateRangeField.types'; -import { - DateRangeComponentValidationProps, - validateDateRange, -} from '../../utils/validation/validateDateRange'; +import { validateDateRange } from '../../../validation'; import { rangeValueManager } from '../../utils/valueManagers'; import type { UseMultiInputRangeFieldResponse } from './useMultiInputRangeField.types'; import { DateRangeValidationError, DateRange } from '../../../models'; @@ -48,8 +44,6 @@ export const useMultiInputDateRangeField = < typeof inSharedProps >(inSharedProps); - const adapter = useLocalizationContext(); - const { value: valueProp, defaultValue, @@ -75,6 +69,14 @@ export const useMultiInputDateRangeField = < valueManager: rangeValueManager, }); + const { validationError, getValidationErrorForNewValue } = useValidation({ + props: sharedProps, + value, + timezone, + validator: validateDateRange, + onError: sharedProps.onError, + }); + // TODO: Maybe export utility from `useField` instead of copy/pasting the logic const buildChangeHandler = ( index: 0 | 1, @@ -85,11 +87,7 @@ export const useMultiInputDateRangeField = < const context: FieldChangeHandlerContext = { ...rawContext, - validationError: validateDateRange({ - adapter, - value: newDateRange, - props: { ...sharedProps, timezone }, - }), + validationError: getValidationErrorForNewValue(newDateRange), }; handleValueChange(newDateRange, context); @@ -99,18 +97,6 @@ export const useMultiInputDateRangeField = < const handleStartDateChange = useEventCallback(buildChangeHandler(0)); const handleEndDateChange = useEventCallback(buildChangeHandler(1)); - const validationError = useValidation< - DateRange, - TDate, - DateRangeValidationError, - DateRangeComponentValidationProps - >( - { ...sharedProps, value, timezone }, - validateDateRange, - rangeValueManager.isSameError, - rangeValueManager.defaultErrorState, - ); - const selectedSectionsResponse = useMultiInputFieldSelectedSections({ selectedSections, onSelectedSectionsChange, diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts index cecc16b5cc6e..60efbe608a10 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts @@ -4,8 +4,6 @@ import { UseDateTimeFieldComponentProps, } from '@mui/x-date-pickers/DateTimeField'; import { - useLocalizationContext, - useValidation, FieldChangeHandler, FieldChangeHandlerContext, UseFieldResponse, @@ -13,15 +11,13 @@ import { useDefaultizedDateTimeField, } from '@mui/x-date-pickers/internals'; import { DateTimeValidationError, PickerValidDate } from '@mui/x-date-pickers/models'; +import { useValidation } from '@mui/x-date-pickers/validation'; import type { UseMultiInputDateTimeRangeFieldParams, UseMultiInputDateTimeRangeFieldProps, } from '../../../MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.types'; import { DateTimeRangeValidationError, DateRange } from '../../../models'; -import { - DateTimeRangeComponentValidationProps, - validateDateTimeRange, -} from '../../utils/validation/validateDateTimeRange'; +import { validateDateTimeRange } from '../../../validation'; import { rangeValueManager } from '../../utils/valueManagers'; import type { UseMultiInputRangeFieldResponse } from './useMultiInputRangeField.types'; import { excludeProps } from './shared'; @@ -47,7 +43,6 @@ export const useMultiInputDateTimeRangeField = < UseMultiInputDateTimeRangeFieldProps, typeof inSharedProps >(inSharedProps); - const adapter = useLocalizationContext(); const { value: valueProp, @@ -74,6 +69,14 @@ export const useMultiInputDateTimeRangeField = < valueManager: rangeValueManager, }); + const { validationError, getValidationErrorForNewValue } = useValidation({ + props: sharedProps, + value, + timezone, + validator: validateDateTimeRange, + onError: sharedProps.onError, + }); + // TODO: Maybe export utility from `useField` instead of copy/pasting the logic const buildChangeHandler = ( index: 0 | 1, @@ -84,11 +87,7 @@ export const useMultiInputDateTimeRangeField = < const context: FieldChangeHandlerContext = { ...rawContext, - validationError: validateDateTimeRange({ - adapter, - value: newDateRange, - props: { ...sharedProps, timezone }, - }), + validationError: getValidationErrorForNewValue(newDateRange), }; handleValueChange(newDateRange, context); @@ -98,18 +97,6 @@ export const useMultiInputDateTimeRangeField = < const handleStartDateChange = useEventCallback(buildChangeHandler(0)); const handleEndDateChange = useEventCallback(buildChangeHandler(1)); - const validationError = useValidation< - DateRange, - TDate, - DateTimeRangeValidationError, - DateTimeRangeComponentValidationProps - >( - { ...sharedProps, value, timezone }, - validateDateTimeRange, - rangeValueManager.isSameError, - rangeValueManager.defaultErrorState, - ); - const selectedSectionsResponse = useMultiInputFieldSelectedSections({ selectedSections, onSelectedSectionsChange, diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts index a27dcb41a897..86db843894f5 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts @@ -4,19 +4,15 @@ import { UseTimeFieldComponentProps, } from '@mui/x-date-pickers/TimeField'; import { - useLocalizationContext, - useValidation, FieldChangeHandler, FieldChangeHandlerContext, UseFieldResponse, useControlledValueWithTimezone, useDefaultizedTimeField, } from '@mui/x-date-pickers/internals'; +import { useValidation } from '@mui/x-date-pickers/validation'; import { PickerValidDate, TimeValidationError } from '@mui/x-date-pickers/models'; -import { - validateTimeRange, - TimeRangeComponentValidationProps, -} from '../../utils/validation/validateTimeRange'; +import { validateTimeRange } from '../../../validation'; import { TimeRangeValidationError, DateRange } from '../../../models'; import type { UseMultiInputTimeRangeFieldParams, @@ -47,7 +43,6 @@ export const useMultiInputTimeRangeField = < UseMultiInputTimeRangeFieldProps, typeof inSharedProps >(inSharedProps); - const adapter = useLocalizationContext(); const { value: valueProp, @@ -74,6 +69,14 @@ export const useMultiInputTimeRangeField = < valueManager: rangeValueManager, }); + const { validationError, getValidationErrorForNewValue } = useValidation({ + props: sharedProps, + validator: validateTimeRange, + value, + timezone, + onError: sharedProps.onError, + }); + // TODO: Maybe export utility from `useField` instead of copy/pasting the logic const buildChangeHandler = ( index: 0 | 1, @@ -84,11 +87,7 @@ export const useMultiInputTimeRangeField = < const context: FieldChangeHandlerContext = { ...rawContext, - validationError: validateTimeRange({ - adapter, - value: newDateRange, - props: { ...sharedProps, timezone }, - }), + validationError: getValidationErrorForNewValue(newDateRange), }; handleValueChange(newDateRange, context); @@ -98,18 +97,6 @@ export const useMultiInputTimeRangeField = < const handleStartDateChange = useEventCallback(buildChangeHandler(0)); const handleEndDateChange = useEventCallback(buildChangeHandler(1)); - const validationError = useValidation< - DateRange, - TDate, - TimeRangeValidationError, - TimeRangeComponentValidationProps - >( - { ...sharedProps, value, timezone }, - validateTimeRange, - rangeValueManager.isSameError, - rangeValueManager.defaultErrorState, - ); - const selectedSectionsResponse = useMultiInputFieldSelectedSections({ selectedSections, onSelectedSectionsChange, diff --git a/packages/x-date-pickers-pro/src/validation/index.ts b/packages/x-date-pickers-pro/src/validation/index.ts new file mode 100644 index 000000000000..9b7737a17ed2 --- /dev/null +++ b/packages/x-date-pickers-pro/src/validation/index.ts @@ -0,0 +1,8 @@ +export { validateDateRange } from './validateDateRange'; +export type { ValidateDateRangeProps } from './validateDateRange'; + +export { validateTimeRange } from './validateTimeRange'; +export type { ValidateTimeRangeProps } from './validateTimeRange'; + +export { validateDateTimeRange } from './validateDateTimeRange'; +export type { ValidateDateTimeRangeProps } from './validateDateTimeRange'; diff --git a/packages/x-date-pickers-pro/src/internals/utils/validation/validateDateRange.ts b/packages/x-date-pickers-pro/src/validation/validateDateRange.ts similarity index 55% rename from packages/x-date-pickers-pro/src/internals/utils/validation/validateDateRange.ts rename to packages/x-date-pickers-pro/src/validation/validateDateRange.ts index bb138c82f438..125449ca9a6f 100644 --- a/packages/x-date-pickers-pro/src/internals/utils/validation/validateDateRange.ts +++ b/packages/x-date-pickers-pro/src/validation/validateDateRange.ts @@ -1,25 +1,21 @@ -import { PickerValidDate, TimezoneProps } from '@mui/x-date-pickers/models'; -import { - Validator, - validateDate, - BaseDateValidationProps, - DefaultizedProps, -} from '@mui/x-date-pickers/internals'; -import { isRangeValid } from '../date-utils'; -import { DayRangeValidationProps } from '../../models/dateRange'; -import { DateRangeValidationError, DateRange } from '../../../models'; - -export interface DateRangeComponentValidationProps +import { PickerValidDate } from '@mui/x-date-pickers/models'; +import { validateDate, Validator } from '@mui/x-date-pickers/validation'; +import { BaseDateValidationProps } from '@mui/x-date-pickers/internals'; +import { isRangeValid } from '../internals/utils/date-utils'; +import { DayRangeValidationProps } from '../internals/models/dateRange'; +import { DateRangeValidationError, DateRange } from '../models'; +import { rangeValueManager } from '../internals/utils/valueManagers'; + +export interface ValidateDateRangeProps extends DayRangeValidationProps, - Required>, - DefaultizedProps {} + Required> {} export const validateDateRange: Validator< DateRange, any, DateRangeValidationError, - DateRangeComponentValidationProps -> = ({ props, value, adapter }) => { + ValidateDateRangeProps +> = ({ adapter, value, timezone, props }) => { const [start, end] = value; const { shouldDisableDate, ...otherProps } = props; @@ -28,6 +24,7 @@ export const validateDateRange: Validator< validateDate({ adapter, value: start, + timezone, props: { ...otherProps, shouldDisableDate: (day) => !!shouldDisableDate?.(day, 'start'), @@ -36,6 +33,7 @@ export const validateDateRange: Validator< validateDate({ adapter, value: end, + timezone, props: { ...otherProps, shouldDisableDate: (day) => !!shouldDisableDate?.(day, 'end'), @@ -58,3 +56,5 @@ export const validateDateRange: Validator< return [null, null]; }; + +validateDateRange.valueManager = rangeValueManager; diff --git a/packages/x-date-pickers-pro/src/internals/utils/validation/validateDateTimeRange.ts b/packages/x-date-pickers-pro/src/validation/validateDateTimeRange.ts similarity index 55% rename from packages/x-date-pickers-pro/src/internals/utils/validation/validateDateTimeRange.ts rename to packages/x-date-pickers-pro/src/validation/validateDateTimeRange.ts index 2eae3041a2e4..d86d65e8d3b3 100644 --- a/packages/x-date-pickers-pro/src/internals/utils/validation/validateDateTimeRange.ts +++ b/packages/x-date-pickers-pro/src/validation/validateDateTimeRange.ts @@ -1,27 +1,22 @@ -import { PickerValidDate, TimezoneProps } from '@mui/x-date-pickers/models'; -import { - Validator, - validateDateTime, - BaseDateValidationProps, - TimeValidationProps, - DefaultizedProps, -} from '@mui/x-date-pickers/internals'; -import { isRangeValid } from '../date-utils'; -import { DayRangeValidationProps } from '../../models/dateRange'; -import { DateTimeRangeValidationError, DateRange } from '../../../models'; - -export interface DateTimeRangeComponentValidationProps +import { PickerValidDate } from '@mui/x-date-pickers/models'; +import { validateDateTime, Validator } from '@mui/x-date-pickers/validation'; +import { BaseDateValidationProps, TimeValidationProps } from '@mui/x-date-pickers/internals'; +import { isRangeValid } from '../internals/utils/date-utils'; +import { DayRangeValidationProps } from '../internals/models/dateRange'; +import { DateTimeRangeValidationError, DateRange } from '../models'; +import { rangeValueManager } from '../internals/utils/valueManagers'; + +export interface ValidateDateTimeRangeProps extends DayRangeValidationProps, TimeValidationProps, - Required>, - DefaultizedProps {} + Required> {} export const validateDateTimeRange: Validator< DateRange, any, DateTimeRangeValidationError, - DateTimeRangeComponentValidationProps -> = ({ props, value, adapter }) => { + ValidateDateTimeRangeProps +> = ({ adapter, value, timezone, props }) => { const [start, end] = value; const { shouldDisableDate, ...otherProps } = props; @@ -30,6 +25,7 @@ export const validateDateTimeRange: Validator< validateDateTime({ adapter, value: start, + timezone, props: { ...otherProps, shouldDisableDate: (day) => !!shouldDisableDate?.(day, 'start'), @@ -38,6 +34,7 @@ export const validateDateTimeRange: Validator< validateDateTime({ adapter, value: end, + timezone, props: { ...otherProps, shouldDisableDate: (day) => !!shouldDisableDate?.(day, 'end'), @@ -60,3 +57,5 @@ export const validateDateTimeRange: Validator< return [null, null]; }; + +validateDateTimeRange.valueManager = rangeValueManager; diff --git a/packages/x-date-pickers-pro/src/internals/utils/validation/validateTimeRange.ts b/packages/x-date-pickers-pro/src/validation/validateTimeRange.ts similarity index 52% rename from packages/x-date-pickers-pro/src/internals/utils/validation/validateTimeRange.ts rename to packages/x-date-pickers-pro/src/validation/validateTimeRange.ts index 15b4a2bc2cd6..483523a4b499 100644 --- a/packages/x-date-pickers-pro/src/internals/utils/validation/validateTimeRange.ts +++ b/packages/x-date-pickers-pro/src/validation/validateTimeRange.ts @@ -1,34 +1,30 @@ -import { TimezoneProps } from '@mui/x-date-pickers/models'; -import { - Validator, - validateTime, - BaseTimeValidationProps, - DefaultizedProps, -} from '@mui/x-date-pickers/internals'; -import { isRangeValid } from '../date-utils'; -import { TimeRangeValidationError, DateRange } from '../../../models'; - -export interface TimeRangeComponentValidationProps - extends Required, - DefaultizedProps {} +import { validateTime, Validator } from '@mui/x-date-pickers/validation'; +import { BaseTimeValidationProps } from '@mui/x-date-pickers/internals'; +import { isRangeValid } from '../internals/utils/date-utils'; +import { TimeRangeValidationError, DateRange } from '../models'; +import { rangeValueManager } from '../internals/utils/valueManagers'; + +export interface ValidateTimeRangeProps extends Required {} export const validateTimeRange: Validator< DateRange, any, TimeRangeValidationError, - TimeRangeComponentValidationProps -> = ({ props, value, adapter }) => { + ValidateTimeRangeProps +> = ({ adapter, value, timezone, props }) => { const [start, end] = value; const dateTimeValidations: TimeRangeValidationError = [ validateTime({ adapter, value: start, + timezone, props, }), validateTime({ adapter, value: end, + timezone, props, }), ]; @@ -48,3 +44,5 @@ export const validateTimeRange: Validator< return [null, null]; }; + +validateTimeRange.valueManager = rangeValueManager; diff --git a/packages/x-date-pickers/src/DateCalendar/useIsDateDisabled.ts b/packages/x-date-pickers/src/DateCalendar/useIsDateDisabled.ts index 7fbde8e84772..2c677f6f7653 100644 --- a/packages/x-date-pickers/src/DateCalendar/useIsDateDisabled.ts +++ b/packages/x-date-pickers/src/DateCalendar/useIsDateDisabled.ts @@ -1,10 +1,8 @@ import * as React from 'react'; -import { - DateComponentValidationProps, - validateDate, -} from '../internals/utils/validation/validateDate'; +import { ValidateDateProps, validateDate } from '../validation'; import { useLocalizationContext } from '../internals/hooks/useUtils'; -import { PickerValidDate } from '../models'; +import { PickerValidDate, TimezoneProps } from '../models'; +import { DefaultizedProps } from '../internals/models/helpers'; export const useIsDateDisabled = ({ shouldDisableDate, @@ -15,7 +13,7 @@ export const useIsDateDisabled = ({ disableFuture, disablePast, timezone, -}: DateComponentValidationProps) => { +}: ValidateDateProps & DefaultizedProps) => { const adapter = useLocalizationContext(); return React.useCallback( @@ -23,6 +21,7 @@ export const useIsDateDisabled = ({ validateDate({ adapter, value: day, + timezone, props: { shouldDisableDate, shouldDisableMonth, @@ -31,7 +30,6 @@ export const useIsDateDisabled = ({ maxDate, disableFuture, disablePast, - timezone, }, }) !== null, [ diff --git a/packages/x-date-pickers/src/DateField/DateField.tsx b/packages/x-date-pickers/src/DateField/DateField.tsx index 5f707a99d31a..9a8b2f4d5bb1 100644 --- a/packages/x-date-pickers/src/DateField/DateField.tsx +++ b/packages/x-date-pickers/src/DateField/DateField.tsx @@ -222,10 +222,12 @@ DateField.propTypes = { onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, onFocus: PropTypes.func, diff --git a/packages/x-date-pickers/src/DateField/DateField.types.ts b/packages/x-date-pickers/src/DateField/DateField.types.ts index cf1bdfcc800a..57ab1e1830ae 100644 --- a/packages/x-date-pickers/src/DateField/DateField.types.ts +++ b/packages/x-date-pickers/src/DateField/DateField.types.ts @@ -11,9 +11,10 @@ import { FieldSection, PickerValidDate, BuiltInFieldTextFieldProps, + BaseSingleInputFieldProps, } from '../models'; import { UseFieldInternalProps } from '../internals/hooks/useField'; -import { MakeOptional } from '../internals/models/helpers'; +import { MakeOptional, DefaultizedProps } from '../internals/models/helpers'; import { BaseDateValidationProps, DayValidationProps, @@ -40,6 +41,19 @@ export interface UseDateFieldProps< BaseDateValidationProps, ExportedUseClearableFieldProps {} +/** + * Props the field can receive when used inside a date picker. + * (`DatePicker`, `DesktopDatePicker` or `MobileDatePicker` component). + */ +export type DateFieldInPickerProps< + TDate extends PickerValidDate, + TEnableAccessibleFieldDOMStructure extends boolean, +> = DefaultizedProps< + UseDateFieldProps, + 'format' | 'timezone' | keyof BaseDateValidationProps +> & + BaseSingleInputFieldProps; + export type UseDateFieldComponentProps< TDate extends PickerValidDate, TEnableAccessibleFieldDOMStructure extends boolean, diff --git a/packages/x-date-pickers/src/DateField/index.ts b/packages/x-date-pickers/src/DateField/index.ts index cd6119e98a25..e5f8fe21dcb2 100644 --- a/packages/x-date-pickers/src/DateField/index.ts +++ b/packages/x-date-pickers/src/DateField/index.ts @@ -4,4 +4,5 @@ export type { UseDateFieldProps, UseDateFieldComponentProps, DateFieldProps, + DateFieldInPickerProps, } from './DateField.types'; diff --git a/packages/x-date-pickers/src/DateField/useDateField.ts b/packages/x-date-pickers/src/DateField/useDateField.ts index a6ea87980fdd..6c8e1408f7d5 100644 --- a/packages/x-date-pickers/src/DateField/useDateField.ts +++ b/packages/x-date-pickers/src/DateField/useDateField.ts @@ -4,7 +4,7 @@ import { } from '../internals/utils/valueManagers'; import { useField } from '../internals/hooks/useField'; import { UseDateFieldProps } from './DateField.types'; -import { validateDate } from '../internals/utils/validation/validateDate'; +import { validateDate } from '../validation'; import { splitFieldInternalAndForwardedProps } from '../internals/utils/fields'; import { FieldSection, PickerValidDate } from '../models'; import { useDefaultizedDateField } from '../internals/hooks/defaultizedFieldProps'; @@ -22,10 +22,7 @@ export const useDateField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseDateFieldProps - >(props, 'date'); + const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps(props, 'date'); return useField< TDate | null, diff --git a/packages/x-date-pickers/src/DatePicker/DatePicker.tsx b/packages/x-date-pickers/src/DatePicker/DatePicker.tsx index e93c88833ba4..15836ef4d4c1 100644 --- a/packages/x-date-pickers/src/DatePicker/DatePicker.tsx +++ b/packages/x-date-pickers/src/DatePicker/DatePicker.tsx @@ -194,12 +194,12 @@ DatePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/DateTimeField/DateTimeField.tsx b/packages/x-date-pickers/src/DateTimeField/DateTimeField.tsx index 44db7bb3fb50..1b56a21d24e3 100644 --- a/packages/x-date-pickers/src/DateTimeField/DateTimeField.tsx +++ b/packages/x-date-pickers/src/DateTimeField/DateTimeField.tsx @@ -255,10 +255,12 @@ DateTimeField.propTypes = { onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, onFocus: PropTypes.func, diff --git a/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts b/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts index 625f70532e55..e19e41a6345a 100644 --- a/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts +++ b/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts @@ -6,9 +6,10 @@ import { FieldSection, PickerValidDate, BuiltInFieldTextFieldProps, + BaseSingleInputFieldProps, } from '../models'; import { UseFieldInternalProps } from '../internals/hooks/useField'; -import { MakeOptional } from '../internals/models/helpers'; +import { DefaultizedProps, MakeOptional } from '../internals/models/helpers'; import { BaseDateValidationProps, BaseTimeValidationProps, @@ -52,6 +53,23 @@ export interface UseDateTimeFieldProps< ampm?: boolean; } +/** + * Props the field can receive when used inside a date time picker. + * (`DateTimePicker`, `DesktopDateTimePicker` or `MobileDateTimePicker` component). + */ +export type DateTimeFieldInPickerProps< + TDate extends PickerValidDate, + TEnableAccessibleFieldDOMStructure extends boolean, +> = DefaultizedProps< + UseDateTimeFieldProps, + | 'format' + | 'timezone' + | 'ampm' + | keyof BaseDateValidationProps + | keyof BaseTimeValidationProps +> & + BaseSingleInputFieldProps; + export type UseDateTimeFieldComponentProps< TDate extends PickerValidDate, TEnableAccessibleFieldDOMStructure extends boolean, diff --git a/packages/x-date-pickers/src/DateTimeField/index.ts b/packages/x-date-pickers/src/DateTimeField/index.ts index 95952dde9474..212ce42432f5 100644 --- a/packages/x-date-pickers/src/DateTimeField/index.ts +++ b/packages/x-date-pickers/src/DateTimeField/index.ts @@ -4,4 +4,5 @@ export type { UseDateTimeFieldProps, UseDateTimeFieldComponentProps, DateTimeFieldProps, + DateTimeFieldInPickerProps, } from './DateTimeField.types'; diff --git a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts index b92124fe9373..adef7f79de0b 100644 --- a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts +++ b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts @@ -4,7 +4,7 @@ import { } from '../internals/utils/valueManagers'; import { useField } from '../internals/hooks/useField'; import { UseDateTimeFieldProps } from './DateTimeField.types'; -import { validateDateTime } from '../internals/utils/validation/validateDateTime'; +import { validateDateTime } from '../validation'; import { splitFieldInternalAndForwardedProps } from '../internals/utils/fields'; import { FieldSection, PickerValidDate } from '../models'; import { useDefaultizedDateTimeField } from '../internals/hooks/defaultizedFieldProps'; @@ -22,10 +22,7 @@ export const useDateTimeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseDateTimeFieldProps - >(props, 'date-time'); + const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps(props, 'date-time'); return useField< TDate | null, diff --git a/packages/x-date-pickers/src/DateTimePicker/DateTimePicker.tsx b/packages/x-date-pickers/src/DateTimePicker/DateTimePicker.tsx index a8126e9c5474..6008984bf9b9 100644 --- a/packages/x-date-pickers/src/DateTimePicker/DateTimePicker.tsx +++ b/packages/x-date-pickers/src/DateTimePicker/DateTimePicker.tsx @@ -232,12 +232,12 @@ DateTimePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/DesktopDatePicker/DesktopDatePicker.tsx b/packages/x-date-pickers/src/DesktopDatePicker/DesktopDatePicker.tsx index 5e0c6e75ae8a..df305d499291 100644 --- a/packages/x-date-pickers/src/DesktopDatePicker/DesktopDatePicker.tsx +++ b/packages/x-date-pickers/src/DesktopDatePicker/DesktopDatePicker.tsx @@ -7,12 +7,11 @@ import { DesktopDatePickerProps } from './DesktopDatePicker.types'; import { DatePickerViewRenderers, useDatePickerDefaultizedProps } from '../DatePicker/shared'; import { usePickersTranslations } from '../hooks/usePickersTranslations'; import { useUtils } from '../internals/hooks/useUtils'; -import { validateDate } from '../internals/utils/validation/validateDate'; import { DateView, PickerValidDate } from '../models'; import { useDesktopPicker } from '../internals/hooks/useDesktopPicker'; import { CalendarIcon } from '../icons'; import { DateField } from '../DateField'; -import { extractValidationProps } from '../internals/utils/validation/extractValidationProps'; +import { extractValidationProps, validateDate } from '../validation'; import { renderDateViewCalendar } from '../dateViewRenderers'; import { resolveDateFormat } from '../internals/utils/date-utils'; @@ -239,12 +238,12 @@ DesktopDatePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx index f728453aa5ae..cdc5ab894cb5 100644 --- a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx +++ b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx @@ -13,11 +13,10 @@ import { import { renderDateViewCalendar } from '../dateViewRenderers/dateViewRenderers'; import { usePickersTranslations } from '../hooks/usePickersTranslations'; import { useUtils } from '../internals/hooks/useUtils'; -import { validateDateTime } from '../internals/utils/validation/validateDateTime'; import { DateOrTimeViewWithMeridiem } from '../internals/models'; import { CalendarIcon } from '../icons'; import { UseDesktopPickerProps, useDesktopPicker } from '../internals/hooks/useDesktopPicker'; -import { extractValidationProps } from '../internals/utils/validation/extractValidationProps'; +import { extractValidationProps, validateDateTime } from '../validation'; import { PickerViewsRendererProps } from '../internals/hooks/usePicker'; import { resolveDateTimeFormat, @@ -413,12 +412,12 @@ DesktopDateTimePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/DesktopTimePicker/DesktopTimePicker.tsx b/packages/x-date-pickers/src/DesktopTimePicker/DesktopTimePicker.tsx index 31232c0cfb7e..aecc9706b9df 100644 --- a/packages/x-date-pickers/src/DesktopTimePicker/DesktopTimePicker.tsx +++ b/packages/x-date-pickers/src/DesktopTimePicker/DesktopTimePicker.tsx @@ -8,10 +8,9 @@ import { DesktopTimePickerProps } from './DesktopTimePicker.types'; import { TimePickerViewRenderers, useTimePickerDefaultizedProps } from '../TimePicker/shared'; import { usePickersTranslations } from '../hooks/usePickersTranslations'; import { useUtils } from '../internals/hooks/useUtils'; -import { validateTime } from '../internals/utils/validation/validateTime'; import { ClockIcon } from '../icons'; import { useDesktopPicker } from '../internals/hooks/useDesktopPicker'; -import { extractValidationProps } from '../internals/utils/validation/extractValidationProps'; +import { extractValidationProps, validateTime } from '../validation'; import { renderDigitalClockTimeView, renderMultiSectionDigitalClockTimeView, @@ -265,12 +264,12 @@ DesktopTimePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/MobileDatePicker/MobileDatePicker.tsx b/packages/x-date-pickers/src/MobileDatePicker/MobileDatePicker.tsx index 5f33b9a15dcf..bfe87f5b6f3c 100644 --- a/packages/x-date-pickers/src/MobileDatePicker/MobileDatePicker.tsx +++ b/packages/x-date-pickers/src/MobileDatePicker/MobileDatePicker.tsx @@ -7,10 +7,9 @@ import { MobileDatePickerProps } from './MobileDatePicker.types'; import { DatePickerViewRenderers, useDatePickerDefaultizedProps } from '../DatePicker/shared'; import { usePickersTranslations } from '../hooks/usePickersTranslations'; import { useUtils } from '../internals/hooks/useUtils'; -import { validateDate } from '../internals/utils/validation/validateDate'; import { DateView, PickerValidDate } from '../models'; import { DateField } from '../DateField'; -import { extractValidationProps } from '../internals/utils/validation/extractValidationProps'; +import { extractValidationProps, validateDate } from '../validation'; import { singleItemValueManager } from '../internals/utils/valueManagers'; import { renderDateViewCalendar } from '../dateViewRenderers'; import { resolveDateFormat } from '../internals/utils/date-utils'; @@ -236,12 +235,12 @@ MobileDatePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/MobileDateTimePicker/MobileDateTimePicker.tsx b/packages/x-date-pickers/src/MobileDateTimePicker/MobileDateTimePicker.tsx index 50ab45e2b37f..24ede5a090c7 100644 --- a/packages/x-date-pickers/src/MobileDateTimePicker/MobileDateTimePicker.tsx +++ b/packages/x-date-pickers/src/MobileDateTimePicker/MobileDateTimePicker.tsx @@ -11,10 +11,9 @@ import { } from '../DateTimePicker/shared'; import { usePickersTranslations } from '../hooks/usePickersTranslations'; import { useUtils } from '../internals/hooks/useUtils'; -import { validateDateTime } from '../internals/utils/validation/validateDateTime'; import { DateOrTimeView, PickerValidDate } from '../models'; import { useMobilePicker } from '../internals/hooks/useMobilePicker'; -import { extractValidationProps } from '../internals/utils/validation/extractValidationProps'; +import { extractValidationProps, validateDateTime } from '../validation'; import { renderDateViewCalendar } from '../dateViewRenderers'; import { renderTimeViewClock } from '../timeViewRenderers'; import { resolveDateTimeFormat } from '../internals/utils/date-time-utils'; @@ -289,12 +288,12 @@ MobileDateTimePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/MobileTimePicker/MobileTimePicker.tsx b/packages/x-date-pickers/src/MobileTimePicker/MobileTimePicker.tsx index 021ec100c680..d0c69b038c5b 100644 --- a/packages/x-date-pickers/src/MobileTimePicker/MobileTimePicker.tsx +++ b/packages/x-date-pickers/src/MobileTimePicker/MobileTimePicker.tsx @@ -8,10 +8,9 @@ import { MobileTimePickerProps } from './MobileTimePicker.types'; import { TimePickerViewRenderers, useTimePickerDefaultizedProps } from '../TimePicker/shared'; import { usePickersTranslations } from '../hooks/usePickersTranslations'; import { useUtils } from '../internals/hooks/useUtils'; -import { validateTime } from '../internals/utils/validation/validateTime'; import { PickerValidDate, TimeView } from '../models'; import { useMobilePicker } from '../internals/hooks/useMobilePicker'; -import { extractValidationProps } from '../internals/utils/validation/extractValidationProps'; +import { extractValidationProps, validateTime } from '../validation'; import { renderTimeViewClock } from '../timeViewRenderers'; import { resolveTimeFormat } from '../internals/utils/time-utils'; @@ -228,12 +227,12 @@ MobileTimePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/StaticDatePicker/StaticDatePicker.tsx b/packages/x-date-pickers/src/StaticDatePicker/StaticDatePicker.tsx index 7482205b4b95..a17c01f09a79 100644 --- a/packages/x-date-pickers/src/StaticDatePicker/StaticDatePicker.tsx +++ b/packages/x-date-pickers/src/StaticDatePicker/StaticDatePicker.tsx @@ -4,7 +4,7 @@ import { StaticDatePickerProps } from './StaticDatePicker.types'; import { DatePickerViewRenderers, useDatePickerDefaultizedProps } from '../DatePicker/shared'; import { renderDateViewCalendar } from '../dateViewRenderers'; import { useStaticPicker } from '../internals/hooks/useStaticPicker'; -import { validateDate } from '../internals/utils/validation/validateDate'; +import { validateDate } from '../validation'; import { DateView, PickerValidDate } from '../models'; import { singleItemValueManager } from '../internals/utils/valueManagers'; @@ -175,12 +175,12 @@ StaticDatePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/StaticDateTimePicker/StaticDateTimePicker.tsx b/packages/x-date-pickers/src/StaticDateTimePicker/StaticDateTimePicker.tsx index 01dd868201d1..50cab5e65883 100644 --- a/packages/x-date-pickers/src/StaticDateTimePicker/StaticDateTimePicker.tsx +++ b/packages/x-date-pickers/src/StaticDateTimePicker/StaticDateTimePicker.tsx @@ -10,7 +10,7 @@ import { renderDateViewCalendar } from '../dateViewRenderers'; import { singleItemValueManager } from '../internals/utils/valueManagers'; import { useStaticPicker } from '../internals/hooks/useStaticPicker'; import { DateOrTimeView, PickerValidDate } from '../models'; -import { validateDateTime } from '../internals/utils/validation/validateDateTime'; +import { validateDateTime } from '../validation'; type StaticDateTimePickerComponent = (( props: StaticDateTimePickerProps & React.RefAttributes, @@ -227,12 +227,12 @@ StaticDateTimePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/StaticTimePicker/StaticTimePicker.tsx b/packages/x-date-pickers/src/StaticTimePicker/StaticTimePicker.tsx index b3b2b27047a0..14a4a493badd 100644 --- a/packages/x-date-pickers/src/StaticTimePicker/StaticTimePicker.tsx +++ b/packages/x-date-pickers/src/StaticTimePicker/StaticTimePicker.tsx @@ -6,7 +6,7 @@ import { TimePickerViewRenderers, useTimePickerDefaultizedProps } from '../TimeP import { renderTimeViewClock } from '../timeViewRenderers'; import { singleItemValueManager } from '../internals/utils/valueManagers'; import { useStaticPicker } from '../internals/hooks/useStaticPicker'; -import { validateTime } from '../internals/utils/validation/validateTime'; +import { validateTime } from '../validation'; type StaticTimePickerComponent = (( props: StaticTimePickerProps & React.RefAttributes, @@ -166,12 +166,12 @@ StaticTimePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/TimeField/TimeField.tsx b/packages/x-date-pickers/src/TimeField/TimeField.tsx index 10d4918133ed..e11d67c90237 100644 --- a/packages/x-date-pickers/src/TimeField/TimeField.tsx +++ b/packages/x-date-pickers/src/TimeField/TimeField.tsx @@ -237,10 +237,12 @@ TimeField.propTypes = { onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, onFocus: PropTypes.func, diff --git a/packages/x-date-pickers/src/TimeField/TimeField.types.ts b/packages/x-date-pickers/src/TimeField/TimeField.types.ts index 478cf08ee9ee..0ce1a53d6e40 100644 --- a/packages/x-date-pickers/src/TimeField/TimeField.types.ts +++ b/packages/x-date-pickers/src/TimeField/TimeField.types.ts @@ -2,13 +2,14 @@ import * as React from 'react'; import { SlotComponentProps } from '@mui/utils'; import TextField from '@mui/material/TextField'; import { UseFieldInternalProps } from '../internals/hooks/useField'; -import { MakeOptional } from '../internals/models/helpers'; +import { DefaultizedProps, MakeOptional } from '../internals/models/helpers'; import { BaseTimeValidationProps, TimeValidationProps } from '../internals/models/validation'; import { FieldSection, PickerValidDate, TimeValidationError, BuiltInFieldTextFieldProps, + BaseSingleInputFieldProps, } from '../models'; import { ExportedUseClearableFieldProps, @@ -39,6 +40,19 @@ export interface UseTimeFieldProps< ampm?: boolean; } +/** + * Props the field can receive when used inside a time picker. + * (`TimePicker`, `DesktopTimePicker` or `MobileTimePicker` component). + */ +export type TimeFieldInPickerProps< + TDate extends PickerValidDate, + TEnableAccessibleFieldDOMStructure extends boolean, +> = DefaultizedProps< + UseTimeFieldProps, + 'format' | 'timezone' | 'ampm' | keyof BaseTimeValidationProps +> & + BaseSingleInputFieldProps; + export type UseTimeFieldComponentProps< TDate extends PickerValidDate, TEnableAccessibleFieldDOMStructure extends boolean, diff --git a/packages/x-date-pickers/src/TimeField/index.ts b/packages/x-date-pickers/src/TimeField/index.ts index f335f0f8fd76..cf9c1e6a5881 100644 --- a/packages/x-date-pickers/src/TimeField/index.ts +++ b/packages/x-date-pickers/src/TimeField/index.ts @@ -4,4 +4,5 @@ export type { UseTimeFieldProps, UseTimeFieldComponentProps, TimeFieldProps, + TimeFieldInPickerProps, } from './TimeField.types'; diff --git a/packages/x-date-pickers/src/TimeField/useTimeField.ts b/packages/x-date-pickers/src/TimeField/useTimeField.ts index bd81134e599f..5d7041c6c35a 100644 --- a/packages/x-date-pickers/src/TimeField/useTimeField.ts +++ b/packages/x-date-pickers/src/TimeField/useTimeField.ts @@ -4,7 +4,7 @@ import { } from '../internals/utils/valueManagers'; import { useField } from '../internals/hooks/useField'; import { UseTimeFieldProps } from './TimeField.types'; -import { validateTime } from '../internals/utils/validation/validateTime'; +import { validateTime } from '../validation'; import { splitFieldInternalAndForwardedProps } from '../internals/utils/fields'; import { PickerValidDate, FieldSection } from '../models'; import { useDefaultizedTimeField } from '../internals/hooks/defaultizedFieldProps'; @@ -22,10 +22,7 @@ export const useTimeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseTimeFieldProps - >(props, 'time'); + const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps(props, 'time'); return useField< TDate | null, diff --git a/packages/x-date-pickers/src/TimePicker/TimePicker.tsx b/packages/x-date-pickers/src/TimePicker/TimePicker.tsx index 2883b0d1d45b..ffdf2a060257 100644 --- a/packages/x-date-pickers/src/TimePicker/TimePicker.tsx +++ b/packages/x-date-pickers/src/TimePicker/TimePicker.tsx @@ -182,12 +182,12 @@ TimePicker.propTypes = { onClose: PropTypes.func, /** * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error */ onError: PropTypes.func, /** diff --git a/packages/x-date-pickers/src/index.ts b/packages/x-date-pickers/src/index.ts index cd2e4e9586e5..f0987002adb1 100644 --- a/packages/x-date-pickers/src/index.ts +++ b/packages/x-date-pickers/src/index.ts @@ -53,7 +53,6 @@ export * from './PickersSectionList'; export { DEFAULT_DESKTOP_MODE_MEDIA_QUERY } from './internals/utils/utils'; export * from './models'; - export * from './icons'; - export * from './hooks'; +export * from './validation'; diff --git a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx index 56e943302f79..0e9097ef1eae 100644 --- a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx +++ b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx @@ -14,12 +14,12 @@ import { useUtils } from '../useUtils'; import { usePicker } from '../usePicker'; import { LocalizationProvider } from '../../../LocalizationProvider'; import { PickersLayout } from '../../../PickersLayout'; -import { InferError } from '../useValidation'; import { FieldSection, PickerValidDate, FieldRef, BaseSingleInputFieldProps, + InferError, } from '../../../models'; import { DateOrTimeViewWithMeridiem } from '../../models'; diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useField.ts b/packages/x-date-pickers/src/internals/hooks/useField/useField.ts index 1d8bc5fdcffb..2ad8363212a9 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useField.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useField.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; import useEventCallback from '@mui/utils/useEventCallback'; import { useRtl } from '@mui/system/RtlProvider'; -import { useValidation } from '../useValidation'; +import { useValidation } from '../../../validation'; import { useUtils } from '../useUtils'; import { UseFieldParams, @@ -226,12 +226,13 @@ export const useField = < interactions.syncSelectionToDOM(); }); - const validationError = useValidation( - { ...internalProps, value: state.value, timezone }, + const { hasValidationError } = useValidation({ + props: internalProps, validator, - valueManager.isSameError, - valueManager.defaultErrorState, - ); + timezone, + value: state.value, + onError: internalProps.onError, + }); const inputError = React.useMemo(() => { // only override when `error` is undefined. @@ -240,8 +241,8 @@ export const useField = < return error; } - return valueManager.hasError(validationError); - }, [valueManager, validationError, error]); + return hasValidationError; + }, [hasValidationError, error]); React.useEffect(() => { if (!inputError && activeSectionIndex == null) { diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useField.types.ts b/packages/x-date-pickers/src/internals/hooks/useField/useField.types.ts index df0915e71b7f..2d4d0c292e12 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useField.types.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useField.types.ts @@ -7,12 +7,13 @@ import { TimezoneProps, FieldSectionContentType, FieldValueType, - PickersTimezone, PickerValidDate, FieldRef, + OnErrorProps, + InferError, } from '../../../models'; import type { PickerValueManager } from '../usePicker'; -import { InferError, Validator } from '../useValidation'; +import type { Validator } from '../../../validation'; import type { UseFieldStateResponse } from './useFieldState'; import type { UseFieldCharacterEditingResponse } from './useFieldCharacterEditing'; import { PickersSectionElement, PickersSectionListRef } from '../../../PickersSectionList'; @@ -37,12 +38,7 @@ export interface UseFieldParams< internalProps: TInternalProps; valueManager: PickerValueManager>; fieldValueManager: FieldValueManager; - validator: Validator< - TValue, - TDate, - InferError, - UseFieldValidationProps - >; + validator: Validator, TInternalProps>; valueType: FieldValueType; } @@ -52,7 +48,8 @@ export interface UseFieldInternalProps< TSection extends FieldSection, TEnableAccessibleFieldDOMStructure extends boolean, TError, -> extends TimezoneProps { +> extends TimezoneProps, + OnErrorProps { /** * The selected value. * Used when the component is controlled. @@ -76,14 +73,6 @@ export interface UseFieldInternalProps< * @param {FieldChangeHandlerContext} context The context containing the validation result of the current value. */ onChange?: FieldChangeHandler; - /** - * Callback fired when the error associated to the current value changes. - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. - * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error. - * @param {TValue} value The value associated to the error. - */ - onError?: (error: TError, value: TValue) => void; /** * Format of the date when rendered in the input(s). */ @@ -396,14 +385,6 @@ export interface UseFieldState { tempValueStrAndroid: string | null; } -export type UseFieldValidationProps< - TValue, - TInternalProps extends { value?: TValue; defaultValue?: TValue; timezone?: PickersTimezone }, -> = Omit & { - value: TValue; - timezone: PickersTimezone; -}; - export type AvailableAdjustKeyCode = | 'ArrowUp' | 'ArrowDown' diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts b/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts index 23e6bbc66900..846ab4be676d 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts @@ -21,12 +21,12 @@ import { getLocalizedDigits, } from './useField.utils'; import { buildSectionsFromFormat } from './buildSectionsFromFormat'; -import { InferError } from '../useValidation'; import { FieldSection, FieldSelectedSections, PickersTimezone, PickerValidDate, + InferError, } from '../../../models'; import { useValueWithTimezone } from '../useValueWithTimezone'; import { @@ -228,7 +228,8 @@ export const useFieldState = < validationError: validator({ adapter, value, - props: { ...internalProps, value, timezone }, + timezone, + props: internalProps, }), }; diff --git a/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.tsx b/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.tsx index b98cf417300b..69f3f1d2644f 100644 --- a/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.tsx +++ b/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.tsx @@ -13,12 +13,12 @@ import { onSpaceOrEnter } from '../../utils/utils'; import { useUtils } from '../useUtils'; import { LocalizationProvider } from '../../../LocalizationProvider'; import { PickersLayout } from '../../../PickersLayout'; -import { InferError } from '../useValidation'; import { FieldSection, BaseSingleInputFieldProps, PickerValidDate, FieldRef, + InferError, } from '../../../models'; import { DateOrTimeViewWithMeridiem } from '../../models'; diff --git a/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.ts b/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.ts index b150b8fe3dee..cb5b46ae746d 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.ts @@ -2,9 +2,8 @@ import { UsePickerParams, UsePickerProps, UsePickerResponse } from './usePicker. import { usePickerValue } from './usePickerValue'; import { usePickerViews } from './usePickerViews'; import { usePickerLayoutProps } from './usePickerLayoutProps'; -import { InferError } from '../useValidation'; import { warnOnce } from '../../utils/warning'; -import { FieldSection, PickerValidDate } from '../../../models'; +import { FieldSection, PickerValidDate, InferError } from '../../../models'; import { DateOrTimeViewWithMeridiem } from '../../models'; export const usePicker = < diff --git a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.ts b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.ts index 3bd7a5eb08a2..8d6255b5f562 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.ts @@ -3,8 +3,13 @@ import useEventCallback from '@mui/utils/useEventCallback'; import { useOpenState } from '../useOpenState'; import { useLocalizationContext, useUtils } from '../useUtils'; import { FieldChangeHandlerContext } from '../useField'; -import { InferError, useValidation } from '../useValidation'; -import { FieldSection, PickerChangeHandlerContext, PickerValidDate } from '../../../models'; +import { useValidation } from '../../../validation'; +import { + FieldSection, + PickerChangeHandlerContext, + PickerValidDate, + InferError, +} from '../../../models'; import { PickerShortcutChangeImportance, PickersShortcutsItemContext, @@ -241,12 +246,13 @@ export const usePickerValue = < }; }); - useValidation( - { ...props, value: dateState.draft, timezone }, + const { getValidationErrorForNewValue } = useValidation({ + props, validator, - valueManager.isSameError, - valueManager.defaultErrorState, - ); + timezone, + value: dateState.draft, + onError: props.onError, + }); const updateDate = useEventCallback((action: PickerValueUpdateAction) => { const updaterParams: PickerValueUpdaterParams = { @@ -275,11 +281,7 @@ export const usePickerValue = < const validationError = action.name === 'setValueFromField' ? action.context.validationError - : validator({ - adapter, - value: action.value, - props: { ...props, value: action.value, timezone }, - }); + : getValidationErrorForNewValue(action.value); cachedContext = { validationError, @@ -440,7 +442,8 @@ export const usePickerValue = < const error = validator({ adapter, value: testedValue, - props: { ...props, value: testedValue, timezone }, + timezone, + props, }); return !valueManager.hasError(error); diff --git a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.types.ts b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.types.ts index 9372640881c4..94c43c8c3c1b 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.types.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.types.ts @@ -1,6 +1,5 @@ import { FieldChangeHandlerContext, UseFieldInternalProps } from '../useField'; -import { InferError, Validator } from '../useValidation'; -import { UseFieldValidationProps } from '../useField/useField.types'; +import { Validator } from '../../../validation'; import { WrapperVariant } from '../../models/common'; import { FieldSection, @@ -10,6 +9,8 @@ import { PickersTimezone, PickerChangeHandlerContext, PickerValidDate, + OnErrorProps, + InferError, } from '../../../models'; import { GetDefaultReferenceDateProps } from '../../utils/getDefaultReferenceDate'; import { @@ -207,7 +208,7 @@ export type PickerValueUpdateAction = /** * Props used to handle the value that are common to all pickers. */ -export interface UsePickerValueBaseProps { +export interface UsePickerValueBaseProps extends OnErrorProps { /** * The selected value. * Used when the component is controlled. @@ -234,16 +235,6 @@ export interface UsePickerValueBaseProps { * @param {FieldChangeHandlerContext} context The context containing the validation result of the current value. */ onAccept?: (value: TValue, context: PickerChangeHandlerContext) => void; - /** - * Callback fired when the error associated to the current value changes. - * If the error has a non-null value, then the `TextField` will be rendered in `error` state. - * - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. - * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} error The new error describing why the current value is not valid. - * @param {TValue} value The value associated to the error. - */ - onError?: (error: TError, value: TValue) => void; } /** @@ -289,12 +280,7 @@ export interface UsePickerValueParams< valueManager: PickerValueManager>; valueType: FieldValueType; wrapperVariant: WrapperVariant; - validator: Validator< - TValue, - TDate, - InferError, - UseFieldValidationProps - >; + validator: Validator, TExternalProps>; } export interface UsePickerValueActions { diff --git a/packages/x-date-pickers/src/internals/hooks/useValidation.ts b/packages/x-date-pickers/src/internals/hooks/useValidation.ts deleted file mode 100644 index 406dcf61d0db..000000000000 --- a/packages/x-date-pickers/src/internals/hooks/useValidation.ts +++ /dev/null @@ -1,63 +0,0 @@ -import * as React from 'react'; -import { useLocalizationContext } from './useUtils'; -import { MuiPickersAdapterContextValue } from '../../LocalizationProvider/LocalizationProvider'; -import { PickerValidDate } from '../../models'; - -interface ValidationCommonProps { - /** - * Callback that fired when input value or new `value` prop validation returns **new** validation error (or value is valid after error). - * In case of validation error detected `reason` prop return non-null value and `TextField` must be displayed in `error` state. - * This can be used to render appropriate form error. - * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. - * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. - * @param {TError} reason The reason why the current value is not valid. - * @param {TValue} value The invalid value. - */ - onError?: (reason: TError, value: TValue) => void; - value: TValue; -} - -export type ValidationProps = ValidationCommonProps< - TError, - TValue -> & - TValidationProps; - -export type InferError = - TProps extends Pick, 'onError'> - ? Parameters>[0] - : never; - -export type Validator = (params: { - adapter: MuiPickersAdapterContextValue; - value: TValue; - props: Omit; -}) => TError; - -export function useValidation< - TValue, - TDate extends PickerValidDate, - TError, - TValidationProps extends {}, ->( - props: ValidationProps, - validate: Validator, - isSameError: (a: TError, b: TError | null) => boolean, - defaultErrorState: TError, -): TError { - const { value, onError } = props; - const adapter = useLocalizationContext(); - const previousValidationErrorRef = React.useRef(defaultErrorState); - - const validationError = validate({ adapter, value, props }); - - React.useEffect(() => { - if (onError && !isSameError(validationError, previousValidationErrorRef.current)) { - onError(validationError, value); - } - - previousValidationErrorRef.current = validationError; - }, [isSameError, onError, previousValidationErrorRef, validationError, value]); - - return validationError; -} diff --git a/packages/x-date-pickers/src/internals/index.ts b/packages/x-date-pickers/src/internals/index.ts index bf9c07dd4c1f..af32e690905c 100644 --- a/packages/x-date-pickers/src/internals/index.ts +++ b/packages/x-date-pickers/src/internals/index.ts @@ -92,8 +92,6 @@ export type { export { useLocalizationContext, useDefaultDates, useUtils, useNow } from './hooks/useUtils'; export type { ExportedUseViewsOptions, UseViewsOptions } from './hooks/useViews'; export { useViews } from './hooks/useViews'; -export { useValidation } from './hooks/useValidation'; -export type { ValidationProps, Validator, InferError } from './hooks/useValidation'; export { usePreviousMonthDisabled, useNextMonthDisabled } from './hooks/date-helpers-hooks'; export type { BaseFieldProps } from './models/fields'; @@ -146,10 +144,6 @@ export { useDefaultizedDateTimeField, } from './hooks/defaultizedFieldProps'; export { useDefaultReduceAnimations } from './hooks/useDefaultReduceAnimations'; -export { extractValidationProps } from './utils/validation/extractValidationProps'; -export { validateDate } from './utils/validation/validateDate'; -export { validateDateTime } from './utils/validation/validateDateTime'; -export { validateTime } from './utils/validation/validateTime'; export { applyDefaultViewProps } from './utils/views'; export { warnOnce } from './utils/warning'; diff --git a/packages/x-date-pickers/src/internals/utils/fields.ts b/packages/x-date-pickers/src/internals/utils/fields.ts index ef5e19e58f08..15ff128cad86 100644 --- a/packages/x-date-pickers/src/internals/utils/fields.ts +++ b/packages/x-date-pickers/src/internals/utils/fields.ts @@ -3,7 +3,7 @@ import { DATE_TIME_VALIDATION_PROP_NAMES, DATE_VALIDATION_PROP_NAMES, TIME_VALIDATION_PROP_NAMES, -} from './validation/extractValidationProps'; +} from '../../validation/extractValidationProps'; const SHARED_FIELD_INTERNAL_PROP_NAMES = [ 'value', @@ -24,15 +24,21 @@ const SHARED_FIELD_INTERNAL_PROP_NAMES = [ 'dateSeparator', ] as const; +type InternalPropNames = + | (typeof SHARED_FIELD_INTERNAL_PROP_NAMES)[number] + | (TValueType extends 'date' | 'date-time' ? (typeof DATE_VALIDATION_PROP_NAMES)[number] : never) + | (TValueType extends 'time' | 'date-time' ? (typeof TIME_VALIDATION_PROP_NAMES)[number] : never) + | (TValueType extends 'date-time' ? (typeof DATE_TIME_VALIDATION_PROP_NAMES)[number] : never); + export const splitFieldInternalAndForwardedProps = < - TProps extends {}, - TInternalPropNames extends keyof TProps, + TValueType extends FieldValueType, + TProps extends { [key in InternalPropNames]?: any }, >( props: TProps, - valueType: FieldValueType, + valueType: TValueType, ) => { - const forwardedProps = { ...props } as Omit; - const internalProps = {} as Pick; + const forwardedProps = { ...props } as Omit>; + const internalProps = {} as Pick>; const extractProp = (propName: string) => { if (forwardedProps.hasOwnProperty(propName)) { diff --git a/packages/x-date-pickers/src/internals/utils/validation/validateDateTime.ts b/packages/x-date-pickers/src/internals/utils/validation/validateDateTime.ts deleted file mode 100644 index ff14f93ac1eb..000000000000 --- a/packages/x-date-pickers/src/internals/utils/validation/validateDateTime.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Validator } from '../../hooks/useValidation'; -import { validateDate, DateComponentValidationProps } from './validateDate'; -import { validateTime, TimeComponentValidationProps } from './validateTime'; -import { DateTimeValidationError, PickerValidDate } from '../../../models'; - -export interface DateTimeComponentValidationProps - extends DateComponentValidationProps, - TimeComponentValidationProps {} - -export const validateDateTime: Validator< - any | null, - any, - DateTimeValidationError, - DateTimeComponentValidationProps -> = ({ props, value, adapter }) => { - const dateValidationResult = validateDate({ - adapter, - value, - props, - }); - - if (dateValidationResult !== null) { - return dateValidationResult; - } - - return validateTime({ - adapter, - value, - props, - }); -}; diff --git a/packages/x-date-pickers/src/models/validation.ts b/packages/x-date-pickers/src/models/validation.ts index 397ea4334d03..6d25a672e0f6 100644 --- a/packages/x-date-pickers/src/models/validation.ts +++ b/packages/x-date-pickers/src/models/validation.ts @@ -21,3 +21,21 @@ export type TimeValidationError = | 'shouldDisableTime-seconds'; export type DateTimeValidationError = DateValidationError | TimeValidationError; + +export interface OnErrorProps { + /** + * Callback fired when the error associated to the current value changes. + * When a validation error is detected, the `error` parameter contains a non-null value. + * This can be used to render an appropriate form error. + * @template TError The validation error type. Will be either `string` or a `null`. Can be in `[start, end]` format in case of range value. + * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. + * @param {TError} error The reason why the current value is not valid. + * @param {TValue} value The value associated to the error + */ + onError?: (error: TError, value: TValue) => void; +} + +export type InferError = + TProps extends Pick, 'onError'> + ? Parameters>[0] + : never; diff --git a/packages/x-date-pickers/src/internals/utils/validation/extractValidationProps.ts b/packages/x-date-pickers/src/validation/extractValidationProps.ts similarity index 97% rename from packages/x-date-pickers/src/internals/utils/validation/extractValidationProps.ts rename to packages/x-date-pickers/src/validation/extractValidationProps.ts index a2d90cde1510..3b2bd180137e 100644 --- a/packages/x-date-pickers/src/internals/utils/validation/extractValidationProps.ts +++ b/packages/x-date-pickers/src/validation/extractValidationProps.ts @@ -6,7 +6,7 @@ import { MonthValidationProps, TimeValidationProps, YearValidationProps, -} from '../../models/validation'; +} from '../internals/models/validation'; export const DATE_VALIDATION_PROP_NAMES: ( | keyof BaseDateValidationProps diff --git a/packages/x-date-pickers/src/validation/index.ts b/packages/x-date-pickers/src/validation/index.ts new file mode 100644 index 000000000000..b3f964c143f8 --- /dev/null +++ b/packages/x-date-pickers/src/validation/index.ts @@ -0,0 +1,13 @@ +export { validateDate } from './validateDate'; +export type { ValidateDateProps } from './validateDate'; + +export { validateTime } from './validateTime'; +export type { ValidateTimeProps } from './validateTime'; + +export { validateDateTime } from './validateDateTime'; +export type { ValidateDateTimeProps } from './validateDateTime'; + +export { extractValidationProps } from './extractValidationProps'; + +export { useValidation } from './useValidation'; +export type { Validator } from './useValidation'; diff --git a/packages/x-date-pickers/src/validation/useValidation.ts b/packages/x-date-pickers/src/validation/useValidation.ts new file mode 100644 index 000000000000..284e36d4860d --- /dev/null +++ b/packages/x-date-pickers/src/validation/useValidation.ts @@ -0,0 +1,99 @@ +import * as React from 'react'; +import useEventCallback from '@mui/utils/useEventCallback'; +import { useLocalizationContext } from '../internals/hooks/useUtils'; +import { MuiPickersAdapterContextValue } from '../LocalizationProvider/LocalizationProvider'; +import { OnErrorProps, PickersTimezone, PickerValidDate } from '../models'; +import type { PickerValueManager } from '../internals/hooks/usePicker'; + +export type Validator = { + (params: { + adapter: MuiPickersAdapterContextValue; + value: TValue; + timezone: PickersTimezone; + props: TValidationProps; + }): TError; + valueManager: PickerValueManager; +}; + +interface UseValidationOptions< + TValue, + TDate extends PickerValidDate, + TError, + TValidationProps extends {}, +> extends OnErrorProps { + /** + * The value to validate. + */ + value: TValue; + /** + * The timezone to use for the validation. + */ + timezone: PickersTimezone; + /** + * The validator function to use. + * They can be imported from `@mui/x-date-pickers/validation` and `@mui/x-date-pickers-pro/validation`. + */ + validator: Validator; + /** + * The validation props, they differ depending on the component. + * For example, the `validateTime` function supports `minTime`, `maxTime`, etc. + */ + props: TValidationProps; +} + +interface UseValidationReturnValue { + /** + * The validation error associated to the value passed to the `useValidation` hook. + */ + validationError: TError; + /** + * `true` if the current error is not null. + * For single value components, it means that the value is invalid. + * For range components, it means that either start or end value is invalid. + */ + hasValidationError: boolean; + /** + * Get the validation error for a new value. + * This can be used to validate the value in a change handler before updating the state. + * @template TValue The value type. + * @param {TValue} newValue The value to validate. + * @returns {TError} The validation error associated to the new value. + */ + getValidationErrorForNewValue: (newValue: TValue) => TError; +} + +export function useValidation< + TValue, + TDate extends PickerValidDate, + TError, + TValidationProps extends {}, +>( + options: UseValidationOptions, +): UseValidationReturnValue { + const { props, validator, value, timezone, onError } = options; + + const adapter = useLocalizationContext(); + const previousValidationErrorRef = React.useRef( + validator.valueManager.defaultErrorState, + ); + + const validationError = validator({ adapter, value, timezone, props }); + const hasValidationError = validator.valueManager.hasError(validationError); + + React.useEffect(() => { + if ( + onError && + !validator.valueManager.isSameError(validationError, previousValidationErrorRef.current) + ) { + onError(validationError, value); + } + + previousValidationErrorRef.current = validationError; + }, [validator, onError, validationError, value]); + + const getValidationErrorForNewValue = useEventCallback((newValue: TValue) => { + return validator({ adapter, value: newValue, timezone, props }); + }); + + return { validationError, hasValidationError, getValidationErrorForNewValue }; +} diff --git a/packages/x-date-pickers/src/internals/utils/validation/validateDate.ts b/packages/x-date-pickers/src/validation/validateDate.ts similarity index 67% rename from packages/x-date-pickers/src/internals/utils/validation/validateDate.ts rename to packages/x-date-pickers/src/validation/validateDate.ts index 363b13a96f70..e3bf707969aa 100644 --- a/packages/x-date-pickers/src/internals/utils/validation/validateDate.ts +++ b/packages/x-date-pickers/src/validation/validateDate.ts @@ -1,39 +1,32 @@ -import { Validator } from '../../hooks/useValidation'; +import { Validator } from './useValidation'; import { BaseDateValidationProps, DayValidationProps, MonthValidationProps, YearValidationProps, -} from '../../models/validation'; -import { DateValidationError, PickerValidDate, TimezoneProps } from '../../../models'; -import { applyDefaultDate } from '../date-utils'; -import { DefaultizedProps } from '../../models/helpers'; +} from '../internals/models/validation'; +import { DateValidationError, PickerValidDate } from '../models'; +import { applyDefaultDate } from '../internals/utils/date-utils'; +import { singleItemValueManager } from '../internals/utils/valueManagers'; -export interface DateComponentValidationProps +export interface ValidateDateProps extends DayValidationProps, MonthValidationProps, YearValidationProps, - Required>, - DefaultizedProps {} + Required> {} export const validateDate: Validator< any | null, any, DateValidationError, - DateComponentValidationProps -> = ({ props, value, adapter }): DateValidationError => { + ValidateDateProps +> = ({ props, value, timezone, adapter }): DateValidationError => { if (value === null) { return null; } - const { - shouldDisableDate, - shouldDisableMonth, - shouldDisableYear, - disablePast, - disableFuture, - timezone, - } = props; + const { shouldDisableDate, shouldDisableMonth, shouldDisableYear, disablePast, disableFuture } = + props; const now = adapter.utils.date(undefined, timezone); const minDate = applyDefaultDate(adapter.utils, props.minDate, adapter.defaultDates.minDate); @@ -68,3 +61,5 @@ export const validateDate: Validator< return null; } }; + +validateDate.valueManager = singleItemValueManager; diff --git a/packages/x-date-pickers/src/validation/validateDateTime.ts b/packages/x-date-pickers/src/validation/validateDateTime.ts new file mode 100644 index 000000000000..1e4824635532 --- /dev/null +++ b/packages/x-date-pickers/src/validation/validateDateTime.ts @@ -0,0 +1,36 @@ +import { Validator } from './useValidation'; +import { validateDate, ValidateDateProps } from './validateDate'; +import { validateTime, ValidateTimeProps } from './validateTime'; +import { DateTimeValidationError, PickerValidDate } from '../models'; +import { singleItemValueManager } from '../internals/utils/valueManagers'; + +export interface ValidateDateTimeProps + extends ValidateDateProps, + ValidateTimeProps {} + +export const validateDateTime: Validator< + any | null, + any, + DateTimeValidationError, + ValidateDateTimeProps +> = ({ adapter, value, timezone, props }) => { + const dateValidationResult = validateDate({ + adapter, + value, + timezone, + props, + }); + + if (dateValidationResult !== null) { + return dateValidationResult; + } + + return validateTime({ + adapter, + value, + timezone, + props, + }); +}; + +validateDateTime.valueManager = singleItemValueManager; diff --git a/packages/x-date-pickers/src/internals/utils/validation/validateTime.ts b/packages/x-date-pickers/src/validation/validateTime.ts similarity index 73% rename from packages/x-date-pickers/src/internals/utils/validation/validateTime.ts rename to packages/x-date-pickers/src/validation/validateTime.ts index c3d109e7ec0f..2124913a3c14 100644 --- a/packages/x-date-pickers/src/internals/utils/validation/validateTime.ts +++ b/packages/x-date-pickers/src/validation/validateTime.ts @@ -1,20 +1,19 @@ -import { createIsAfterIgnoreDatePart } from '../time-utils'; -import { Validator } from '../../hooks/useValidation'; -import { BaseTimeValidationProps, TimeValidationProps } from '../../models/validation'; -import { PickerValidDate, TimeValidationError, TimezoneProps } from '../../../models'; -import { DefaultizedProps } from '../../models/helpers'; +import { createIsAfterIgnoreDatePart } from '../internals/utils/time-utils'; +import { Validator } from './useValidation'; +import { BaseTimeValidationProps, TimeValidationProps } from '../internals/models/validation'; +import { PickerValidDate, TimeValidationError } from '../models'; +import { singleItemValueManager } from '../internals/utils/valueManagers'; -export interface TimeComponentValidationProps +export interface ValidateTimeProps extends Required, - TimeValidationProps, - DefaultizedProps {} + TimeValidationProps {} export const validateTime: Validator< any | null, any, TimeValidationError, - TimeComponentValidationProps -> = ({ adapter, value, props }): TimeValidationError => { + ValidateTimeProps +> = ({ adapter, value, timezone, props }): TimeValidationError => { if (value === null) { return null; } @@ -27,7 +26,6 @@ export const validateTime: Validator< disableIgnoringDatePartForTimeValidation = false, disablePast, disableFuture, - timezone, } = props; const now = adapter.utils.date(undefined, timezone); @@ -68,3 +66,5 @@ export const validateTime: Validator< return null; } }; + +validateTime.valueManager = singleItemValueManager; diff --git a/scripts/x-date-pickers-pro.exports.json b/scripts/x-date-pickers-pro.exports.json index 809ccdd38ed4..f50b211610e9 100644 --- a/scripts/x-date-pickers-pro.exports.json +++ b/scripts/x-date-pickers-pro.exports.json @@ -34,6 +34,7 @@ { "name": "DateCalendarSlotProps", "kind": "Interface" }, { "name": "DateCalendarSlots", "kind": "Interface" }, { "name": "DateField", "kind": "Variable" }, + { "name": "DateFieldInPickerProps", "kind": "TypeAlias" }, { "name": "DateFieldProps", "kind": "TypeAlias" }, { "name": "DateOrTimeView", "kind": "TypeAlias" }, { "name": "DatePicker", "kind": "Variable" }, @@ -71,6 +72,7 @@ { "name": "DateRangeValidationError", "kind": "TypeAlias" }, { "name": "DateRangeViewRendererProps", "kind": "Interface" }, { "name": "DateTimeField", "kind": "Variable" }, + { "name": "DateTimeFieldInPickerProps", "kind": "TypeAlias" }, { "name": "DateTimeFieldProps", "kind": "TypeAlias" }, { "name": "DateTimePicker", "kind": "Variable" }, { "name": "DateTimePickerProps", "kind": "Interface" }, @@ -154,6 +156,7 @@ { "name": "ExportedPickersYearProps", "kind": "Interface" }, { "name": "ExportedSlideTransitionProps", "kind": "Interface" }, { "name": "ExportedUseClearableFieldProps", "kind": "Interface" }, + { "name": "extractValidationProps", "kind": "Variable" }, { "name": "FieldFormatTokenMap", "kind": "TypeAlias" }, { "name": "FieldRef", "kind": "Interface" }, { "name": "FieldSection", "kind": "Interface" }, @@ -184,6 +187,7 @@ { "name": "getPickersTextFieldUtilityClass", "kind": "Function" }, { "name": "getTimeClockUtilityClass", "kind": "Function" }, { "name": "getYearCalendarUtilityClass", "kind": "Function" }, + { "name": "InferError", "kind": "TypeAlias" }, { "name": "LicenseInfo", "kind": "Class" }, { "name": "LocalizationProvider", "kind": "Variable" }, { "name": "LocalizationProviderProps", "kind": "Interface" }, @@ -242,6 +246,7 @@ { "name": "MultiSectionDigitalClockSlotProps", "kind": "Interface" }, { "name": "MultiSectionDigitalClockSlots", "kind": "Interface" }, { "name": "NonEmptyDateRange", "kind": "TypeAlias" }, + { "name": "OnErrorProps", "kind": "Interface" }, { "name": "PickerChangeHandlerContext", "kind": "Interface" }, { "name": "PickersActionBar", "kind": "Function" }, { "name": "PickersActionBarAction", "kind": "TypeAlias" }, @@ -366,6 +371,7 @@ { "name": "TimeClockSlotProps", "kind": "Interface" }, { "name": "TimeClockSlots", "kind": "Interface" }, { "name": "TimeField", "kind": "Variable" }, + { "name": "TimeFieldInPickerProps", "kind": "TypeAlias" }, { "name": "TimeFieldProps", "kind": "TypeAlias" }, { "name": "TimeIcon", "kind": "Variable" }, { "name": "TimePicker", "kind": "Variable" }, @@ -419,6 +425,20 @@ { "name": "UseSingleInputTimeRangeFieldProps", "kind": "Interface" }, { "name": "UseTimeFieldComponentProps", "kind": "TypeAlias" }, { "name": "UseTimeFieldProps", "kind": "Interface" }, + { "name": "useValidation", "kind": "Function" }, + { "name": "validateDate", "kind": "Variable" }, + { "name": "ValidateDateProps", "kind": "Interface" }, + { "name": "validateDateRange", "kind": "Variable" }, + { "name": "ValidateDateRangeProps", "kind": "Interface" }, + { "name": "validateDateTime", "kind": "Variable" }, + { "name": "ValidateDateTimeProps", "kind": "Interface" }, + { "name": "validateDateTimeRange", "kind": "Variable" }, + { "name": "ValidateDateTimeRangeProps", "kind": "Interface" }, + { "name": "validateTime", "kind": "Variable" }, + { "name": "ValidateTimeProps", "kind": "Interface" }, + { "name": "validateTimeRange", "kind": "Variable" }, + { "name": "ValidateTimeRangeProps", "kind": "Interface" }, + { "name": "Validator", "kind": "TypeAlias" }, { "name": "YearCalendar", "kind": "Variable" }, { "name": "yearCalendarClasses", "kind": "Variable" }, { "name": "YearCalendarClasses", "kind": "Interface" }, diff --git a/scripts/x-date-pickers.exports.json b/scripts/x-date-pickers.exports.json index f816e70b63e6..a3e10847b48a 100644 --- a/scripts/x-date-pickers.exports.json +++ b/scripts/x-date-pickers.exports.json @@ -31,6 +31,7 @@ { "name": "DateCalendarSlotProps", "kind": "Interface" }, { "name": "DateCalendarSlots", "kind": "Interface" }, { "name": "DateField", "kind": "Variable" }, + { "name": "DateFieldInPickerProps", "kind": "TypeAlias" }, { "name": "DateFieldProps", "kind": "TypeAlias" }, { "name": "DateOrTimeView", "kind": "TypeAlias" }, { "name": "DatePicker", "kind": "Variable" }, @@ -44,6 +45,7 @@ { "name": "DatePickerToolbarProps", "kind": "Interface" }, { "name": "DateRangeIcon", "kind": "Variable" }, { "name": "DateTimeField", "kind": "Variable" }, + { "name": "DateTimeFieldInPickerProps", "kind": "TypeAlias" }, { "name": "DateTimeFieldProps", "kind": "TypeAlias" }, { "name": "DateTimePicker", "kind": "Variable" }, { "name": "DateTimePickerProps", "kind": "Interface" }, @@ -102,6 +104,7 @@ { "name": "ExportedPickersYearProps", "kind": "Interface" }, { "name": "ExportedSlideTransitionProps", "kind": "Interface" }, { "name": "ExportedUseClearableFieldProps", "kind": "Interface" }, + { "name": "extractValidationProps", "kind": "Variable" }, { "name": "FieldFormatTokenMap", "kind": "TypeAlias" }, { "name": "FieldRef", "kind": "Interface" }, { "name": "FieldSection", "kind": "Interface" }, @@ -123,6 +126,7 @@ { "name": "getPickersTextFieldUtilityClass", "kind": "Function" }, { "name": "getTimeClockUtilityClass", "kind": "Function" }, { "name": "getYearCalendarUtilityClass", "kind": "Function" }, + { "name": "InferError", "kind": "TypeAlias" }, { "name": "LocalizationProvider", "kind": "Variable" }, { "name": "LocalizationProviderProps", "kind": "Interface" }, { "name": "LocalizedComponent", "kind": "TypeAlias" }, @@ -157,6 +161,7 @@ { "name": "MultiSectionDigitalClockSectionClassKey", "kind": "TypeAlias" }, { "name": "MultiSectionDigitalClockSlotProps", "kind": "Interface" }, { "name": "MultiSectionDigitalClockSlots", "kind": "Interface" }, + { "name": "OnErrorProps", "kind": "Interface" }, { "name": "PickerChangeHandlerContext", "kind": "Interface" }, { "name": "PickersActionBar", "kind": "Function" }, { "name": "PickersActionBarAction", "kind": "TypeAlias" }, @@ -265,6 +270,7 @@ { "name": "TimeClockSlotProps", "kind": "Interface" }, { "name": "TimeClockSlots", "kind": "Interface" }, { "name": "TimeField", "kind": "Variable" }, + { "name": "TimeFieldInPickerProps", "kind": "TypeAlias" }, { "name": "TimeFieldProps", "kind": "TypeAlias" }, { "name": "TimeIcon", "kind": "Variable" }, { "name": "TimePicker", "kind": "Variable" }, @@ -301,6 +307,14 @@ { "name": "usePickersTranslations", "kind": "Variable" }, { "name": "UseTimeFieldComponentProps", "kind": "TypeAlias" }, { "name": "UseTimeFieldProps", "kind": "Interface" }, + { "name": "useValidation", "kind": "Function" }, + { "name": "validateDate", "kind": "Variable" }, + { "name": "ValidateDateProps", "kind": "Interface" }, + { "name": "validateDateTime", "kind": "Variable" }, + { "name": "ValidateDateTimeProps", "kind": "Interface" }, + { "name": "validateTime", "kind": "Variable" }, + { "name": "ValidateTimeProps", "kind": "Interface" }, + { "name": "Validator", "kind": "TypeAlias" }, { "name": "YearCalendar", "kind": "Variable" }, { "name": "yearCalendarClasses", "kind": "Variable" }, { "name": "YearCalendarClasses", "kind": "Interface" }, From 0b57b8cab432da56dcdbce86a9c5b3b8e1e93a60 Mon Sep 17 00:00:00 2001 From: delangle Date: Thu, 5 Sep 2024 13:45:38 +0200 Subject: [PATCH 2/8] Work --- .../x-date-pickers/src/validation/useValidation.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/x-date-pickers/src/validation/useValidation.ts b/packages/x-date-pickers/src/validation/useValidation.ts index 284e36d4860d..392d6780725a 100644 --- a/packages/x-date-pickers/src/validation/useValidation.ts +++ b/packages/x-date-pickers/src/validation/useValidation.ts @@ -32,6 +32,8 @@ interface UseValidationOptions< /** * The validator function to use. * They can be imported from `@mui/x-date-pickers/validation` and `@mui/x-date-pickers-pro/validation`. + * It is recommended to only use the validator exported by the MUI X packages, + * otherwise you may have inconsistent behaviors between the field and the views. */ validator: Validator; /** @@ -62,6 +64,18 @@ interface UseValidationReturnValue { getValidationErrorForNewValue: (newValue: TValue) => TError; } +/** + * Utility hook to check if a given value is valid based on the provided validation props. + * @template TDate + * @template TValue The value type. It will be either the same type as `value` or `null`. It can be in `[start, end]` format in case of range value. + * @template TError The validation error type. It will be either `string` or a `null`. It can be in `[start, end]` format in case of range value. + * @param {UseValidationOptions} options The options to configure the hook. + * @param {TValue} options.value The value to validate. + * @param {PickersTimezone} options.timezone The timezone to use for the validation. + * @param {Validator} options.validator The validator function to use. + * @param {TValidationProps} options.props The validation props, they differ depending on the component. + * @param {(error: TError, value: TValue) => void} options.onError Callback fired when the error associated with the current value changes. + */ export function useValidation< TValue, TDate extends PickerValidDate, From 238bfcca1634e8de0efaad48a5845ee1af16c36e Mon Sep 17 00:00:00 2001 From: delangle Date: Thu, 5 Sep 2024 15:13:41 +0200 Subject: [PATCH 3/8] Fix --- .../MultiInputDateRangeField.tsx | 7 ++----- .../MultiInputDateTimeRangeField.tsx | 9 ++++----- .../MultiInputTimeRangeField.tsx | 6 +----- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx index 24417abcd17f..f5bd262347fe 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx @@ -22,7 +22,7 @@ import { MultiInputDateRangeFieldSlotProps, } from './MultiInputDateRangeField.types'; import { useMultiInputDateRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField'; -import { MultiInputRangeFieldClasses, RangePosition, UseDateRangeFieldProps } from '../models'; +import { MultiInputRangeFieldClasses, RangePosition } from '../models'; export const multiInputDateRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses( 'MuiMultiInputDateRangeField', @@ -91,10 +91,7 @@ const MultiInputDateRangeField = React.forwardRef(function MultiInputDateRangeFi name: 'MuiMultiInputDateRangeField', }); - const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps< - typeof themeProps, - keyof Omit, 'clearable' | 'onClear'> - >(themeProps, 'date'); + const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps(themeProps, 'date'); const { slots, diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx index 3b4cdd1aa864..c118f0b00b45 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx @@ -22,7 +22,6 @@ import { MultiInputDateTimeRangeFieldSlotProps, } from './MultiInputDateTimeRangeField.types'; import { useMultiInputDateTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField'; -import { UseDateTimeRangeFieldProps } from '../internals/models/dateTimeRange'; import { MultiInputRangeFieldClasses, RangePosition } from '../models'; export const multiInputDateTimeRangeFieldClasses: MultiInputRangeFieldClasses = @@ -90,10 +89,10 @@ const MultiInputDateTimeRangeField = React.forwardRef(function MultiInputDateTim name: 'MuiMultiInputDateTimeRangeField', }); - const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps< - typeof themeProps, - keyof Omit, 'clearable' | 'onClear'> - >(themeProps, 'date-time'); + const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps( + themeProps, + 'date-time', + ); const { slots, diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx index 16344a101382..0f2783b2a475 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx @@ -22,7 +22,6 @@ import { MultiInputTimeRangeFieldSlotProps, } from './MultiInputTimeRangeField.types'; import { useMultiInputTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField'; -import { UseTimeRangeFieldProps } from '../internals/models/timeRange'; import { MultiInputRangeFieldClasses, RangePosition } from '../models'; export const multiInputTimeRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses( @@ -92,10 +91,7 @@ const MultiInputTimeRangeField = React.forwardRef(function MultiInputTimeRangeFi name: 'MuiMultiInputTimeRangeField', }); - const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps< - typeof themeProps, - keyof Omit, 'clearable' | 'onClear'> - >(themeProps, 'time'); + const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps(themeProps, 'time'); const { slots, From a5a6d79faff235e27655d46f5e2c95a94c530bf7 Mon Sep 17 00:00:00 2001 From: delangle Date: Fri, 6 Sep 2024 10:50:55 +0200 Subject: [PATCH 4/8] [pickers] Improve useSplitFieldInternalAndForwardedProps and make it public --- .../MultiInputDateRangeField.tsx | 16 ++-- .../MultiInputDateTimeRangeField.tsx | 14 ++-- .../MultiInputTimeRangeField.tsx | 15 ++-- .../useSingleInputDateRangeField.ts | 12 +-- .../useSingleInputDateTimeRangeField.ts | 15 ++-- .../useSingleInputTimeRangeField.ts | 12 +-- .../src/DateField/useDateField.ts | 7 +- .../src/DateTimeField/useDateTimeField.ts | 10 +-- .../src/TimeField/useTimeField.ts | 7 +- packages/x-date-pickers/src/hooks/index.tsx | 2 + .../useSplitFieldInternalAndForwardedProps.ts | 77 +++++++++++++++++++ .../x-date-pickers/src/internals/index.ts | 1 - .../src/internals/utils/fields.ts | 58 -------------- scripts/x-date-pickers-pro.exports.json | 1 + scripts/x-date-pickers.exports.json | 1 + 15 files changed, 121 insertions(+), 127 deletions(-) create mode 100644 packages/x-date-pickers/src/hooks/useSplitFieldInternalAndForwardedProps.ts delete mode 100644 packages/x-date-pickers/src/internals/utils/fields.ts diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx index 24417abcd17f..18985fc472fc 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx @@ -11,10 +11,8 @@ import { unstable_generateUtilityClass as generateUtilityClass, unstable_generateUtilityClasses as generateUtilityClasses, } from '@mui/utils'; -import { - splitFieldInternalAndForwardedProps, - convertFieldResponseIntoMuiTextFieldProps, -} from '@mui/x-date-pickers/internals'; +import { convertFieldResponseIntoMuiTextFieldProps } from '@mui/x-date-pickers/internals'; +import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { @@ -22,7 +20,7 @@ import { MultiInputDateRangeFieldSlotProps, } from './MultiInputDateRangeField.types'; import { useMultiInputDateRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField'; -import { MultiInputRangeFieldClasses, RangePosition, UseDateRangeFieldProps } from '../models'; +import { MultiInputRangeFieldClasses, RangePosition } from '../models'; export const multiInputDateRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses( 'MuiMultiInputDateRangeField', @@ -91,10 +89,10 @@ const MultiInputDateRangeField = React.forwardRef(function MultiInputDateRangeFi name: 'MuiMultiInputDateRangeField', }); - const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps< - typeof themeProps, - keyof Omit, 'clearable' | 'onClear'> - >(themeProps, 'date'); + const { internalProps, forwardedProps } = useSplitFieldInternalAndForwardedProps( + themeProps, + 'date', + ); const { slots, diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx index 3b4cdd1aa864..9e835c2b9dfa 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx @@ -11,10 +11,8 @@ import { unstable_generateUtilityClass as generateUtilityClass, unstable_generateUtilityClasses as generateUtilityClasses, } from '@mui/utils'; -import { - splitFieldInternalAndForwardedProps, - convertFieldResponseIntoMuiTextFieldProps, -} from '@mui/x-date-pickers/internals'; +import { convertFieldResponseIntoMuiTextFieldProps } from '@mui/x-date-pickers/internals'; +import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { @@ -90,10 +88,10 @@ const MultiInputDateTimeRangeField = React.forwardRef(function MultiInputDateTim name: 'MuiMultiInputDateTimeRangeField', }); - const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps< - typeof themeProps, - keyof Omit, 'clearable' | 'onClear'> - >(themeProps, 'date-time'); + const { internalProps, forwardedProps } = useSplitFieldInternalAndForwardedProps( + themeProps, + 'date-time', + ); const { slots, diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx index 16344a101382..e8627f5dbd6b 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx @@ -11,10 +11,8 @@ import { unstable_generateUtilityClass as generateUtilityClass, unstable_generateUtilityClasses as generateUtilityClasses, } from '@mui/utils'; -import { - splitFieldInternalAndForwardedProps, - convertFieldResponseIntoMuiTextFieldProps, -} from '@mui/x-date-pickers/internals'; +import { convertFieldResponseIntoMuiTextFieldProps } from '@mui/x-date-pickers/internals'; +import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { @@ -22,7 +20,6 @@ import { MultiInputTimeRangeFieldSlotProps, } from './MultiInputTimeRangeField.types'; import { useMultiInputTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField'; -import { UseTimeRangeFieldProps } from '../internals/models/timeRange'; import { MultiInputRangeFieldClasses, RangePosition } from '../models'; export const multiInputTimeRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses( @@ -92,10 +89,10 @@ const MultiInputTimeRangeField = React.forwardRef(function MultiInputTimeRangeFi name: 'MuiMultiInputTimeRangeField', }); - const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps< - typeof themeProps, - keyof Omit, 'clearable' | 'onClear'> - >(themeProps, 'time'); + const { internalProps, forwardedProps } = useSplitFieldInternalAndForwardedProps( + themeProps, + 'time', + ); const { slots, diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts index acd9177c5fa6..da597fc85e41 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts @@ -1,9 +1,6 @@ import * as React from 'react'; -import { - useField, - splitFieldInternalAndForwardedProps, - useDefaultizedDateField, -} from '@mui/x-date-pickers/internals'; +import { useField, useDefaultizedDateField } from '@mui/x-date-pickers/internals'; +import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputDateRangeFieldProps } from './SingleInputDateRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; @@ -23,10 +20,7 @@ export const useSingleInputDateRangeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseSingleInputDateRangeFieldProps - >(props, 'date'); + const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps(props, 'date'); const fieldValueManager = React.useMemo( () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts index c27ab9b259b3..cd15fe7d7498 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts @@ -1,9 +1,6 @@ import * as React from 'react'; -import { - useField, - splitFieldInternalAndForwardedProps, - useDefaultizedDateTimeField, -} from '@mui/x-date-pickers/internals'; +import { useField, useDefaultizedDateTimeField } from '@mui/x-date-pickers/internals'; +import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputDateTimeRangeFieldProps } from './SingleInputDateTimeRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; @@ -26,10 +23,10 @@ export const useSingleInputDateTimeRangeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseSingleInputDateTimeRangeFieldProps - >(props, 'date-time'); + const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps( + props, + 'date-time', + ); const fieldValueManager = React.useMemo( () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts index 98d9703e7eb8..91bbad42aea6 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts @@ -1,9 +1,6 @@ import * as React from 'react'; -import { - useField, - splitFieldInternalAndForwardedProps, - useDefaultizedTimeField, -} from '@mui/x-date-pickers/internals'; +import { useField, useDefaultizedTimeField } from '@mui/x-date-pickers/internals'; +import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputTimeRangeFieldProps } from './SingleInputTimeRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; @@ -23,10 +20,7 @@ export const useSingleInputTimeRangeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseSingleInputTimeRangeFieldProps - >(props, 'time'); + const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps(props, 'time'); const fieldValueManager = React.useMemo( () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), diff --git a/packages/x-date-pickers/src/DateField/useDateField.ts b/packages/x-date-pickers/src/DateField/useDateField.ts index a6ea87980fdd..96b3c0575308 100644 --- a/packages/x-date-pickers/src/DateField/useDateField.ts +++ b/packages/x-date-pickers/src/DateField/useDateField.ts @@ -5,7 +5,7 @@ import { import { useField } from '../internals/hooks/useField'; import { UseDateFieldProps } from './DateField.types'; import { validateDate } from '../internals/utils/validation/validateDate'; -import { splitFieldInternalAndForwardedProps } from '../internals/utils/fields'; +import { useSplitFieldInternalAndForwardedProps } from '../hooks'; import { FieldSection, PickerValidDate } from '../models'; import { useDefaultizedDateField } from '../internals/hooks/defaultizedFieldProps'; @@ -22,10 +22,7 @@ export const useDateField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseDateFieldProps - >(props, 'date'); + const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps(props, 'date'); return useField< TDate | null, diff --git a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts index b92124fe9373..0765bbf4d799 100644 --- a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts +++ b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts @@ -5,7 +5,7 @@ import { import { useField } from '../internals/hooks/useField'; import { UseDateTimeFieldProps } from './DateTimeField.types'; import { validateDateTime } from '../internals/utils/validation/validateDateTime'; -import { splitFieldInternalAndForwardedProps } from '../internals/utils/fields'; +import { useSplitFieldInternalAndForwardedProps } from '../hooks'; import { FieldSection, PickerValidDate } from '../models'; import { useDefaultizedDateTimeField } from '../internals/hooks/defaultizedFieldProps'; @@ -22,10 +22,10 @@ export const useDateTimeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseDateTimeFieldProps - >(props, 'date-time'); + const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps( + props, + 'date-time', + ); return useField< TDate | null, diff --git a/packages/x-date-pickers/src/TimeField/useTimeField.ts b/packages/x-date-pickers/src/TimeField/useTimeField.ts index bd81134e599f..38d01e3de116 100644 --- a/packages/x-date-pickers/src/TimeField/useTimeField.ts +++ b/packages/x-date-pickers/src/TimeField/useTimeField.ts @@ -5,7 +5,7 @@ import { import { useField } from '../internals/hooks/useField'; import { UseTimeFieldProps } from './TimeField.types'; import { validateTime } from '../internals/utils/validation/validateTime'; -import { splitFieldInternalAndForwardedProps } from '../internals/utils/fields'; +import { useSplitFieldInternalAndForwardedProps } from '../hooks'; import { PickerValidDate, FieldSection } from '../models'; import { useDefaultizedTimeField } from '../internals/hooks/defaultizedFieldProps'; @@ -22,10 +22,7 @@ export const useTimeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps< - typeof props, - keyof UseTimeFieldProps - >(props, 'time'); + const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps(props, 'time'); return useField< TDate | null, diff --git a/packages/x-date-pickers/src/hooks/index.tsx b/packages/x-date-pickers/src/hooks/index.tsx index 99cde931f0f5..4742cecac399 100644 --- a/packages/x-date-pickers/src/hooks/index.tsx +++ b/packages/x-date-pickers/src/hooks/index.tsx @@ -7,3 +7,5 @@ export type { } from './useClearableField'; export { usePickersTranslations } from './usePickersTranslations'; + +export { useSplitFieldInternalAndForwardedProps } from './useSplitFieldInternalAndForwardedProps'; diff --git a/packages/x-date-pickers/src/hooks/useSplitFieldInternalAndForwardedProps.ts b/packages/x-date-pickers/src/hooks/useSplitFieldInternalAndForwardedProps.ts new file mode 100644 index 000000000000..3b3beafac4a7 --- /dev/null +++ b/packages/x-date-pickers/src/hooks/useSplitFieldInternalAndForwardedProps.ts @@ -0,0 +1,77 @@ +import * as React from 'react'; +import { FieldValueType } from '../models'; +import { + DATE_TIME_VALIDATION_PROP_NAMES, + DATE_VALIDATION_PROP_NAMES, + TIME_VALIDATION_PROP_NAMES, +} from '../internals/utils/validation/extractValidationProps'; + +const SHARED_FIELD_INTERNAL_PROP_NAMES = [ + 'value', + 'defaultValue', + 'referenceDate', + 'format', + 'formatDensity', + 'onChange', + 'timezone', + 'onError', + 'shouldRespectLeadingZeros', + 'selectedSections', + 'onSelectedSectionsChange', + 'unstableFieldRef', + 'enableAccessibleFieldDOMStructure', + 'disabled', + 'readOnly', + 'dateSeparator', +] as const; + +type InternalPropNames = + | (typeof SHARED_FIELD_INTERNAL_PROP_NAMES)[number] + | (TValueType extends 'date' | 'date-time' ? (typeof DATE_VALIDATION_PROP_NAMES)[number] : never) + | (TValueType extends 'time' | 'date-time' ? (typeof TIME_VALIDATION_PROP_NAMES)[number] : never) + | (TValueType extends 'date-time' ? (typeof DATE_TIME_VALIDATION_PROP_NAMES)[number] : never); + +/** + * Split the props received by the field component into: + * - `internalProps` which are used by the various hooks called by the field component. + * - `forwardedProps` which are passed to the underlying component. + * Note that some forwarded props might be used by the hooks as well. + * For instance, hooks like `useDateField` need props like `autoFocus` to know how to behave. + * @template TProps, TValueType + * @param {TProps} props The props received by the field component. + * @param {TValueType} valueType The type of the field value ('date', 'time', or 'date-time'). + */ +export const useSplitFieldInternalAndForwardedProps = < + TValueType extends FieldValueType, + TProps extends { [key in InternalPropNames]?: any }, +>( + props: TProps, + valueType: TValueType, +) => { + return React.useMemo(() => { + const forwardedProps = { ...props } as Omit>; + const internalProps = {} as Pick>; + + const extractProp = (propName: string) => { + if (forwardedProps.hasOwnProperty(propName)) { + // @ts-ignore + internalProps[propName] = forwardedProps[propName]; + delete forwardedProps[propName as keyof typeof forwardedProps]; + } + }; + + SHARED_FIELD_INTERNAL_PROP_NAMES.forEach(extractProp); + + if (valueType === 'date') { + DATE_VALIDATION_PROP_NAMES.forEach(extractProp); + } else if (valueType === 'time') { + TIME_VALIDATION_PROP_NAMES.forEach(extractProp); + } else if (valueType === 'date-time') { + DATE_VALIDATION_PROP_NAMES.forEach(extractProp); + TIME_VALIDATION_PROP_NAMES.forEach(extractProp); + DATE_TIME_VALIDATION_PROP_NAMES.forEach(extractProp); + } + + return { forwardedProps, internalProps }; + }, [props, valueType]); +}; diff --git a/packages/x-date-pickers/src/internals/index.ts b/packages/x-date-pickers/src/internals/index.ts index bf9c07dd4c1f..7942fd78cf76 100644 --- a/packages/x-date-pickers/src/internals/index.ts +++ b/packages/x-date-pickers/src/internals/index.ts @@ -132,7 +132,6 @@ export { formatMeridiem, } from './utils/date-utils'; export { resolveTimeViewsResponse, resolveDateTimeFormat } from './utils/date-time-utils'; -export { splitFieldInternalAndForwardedProps } from './utils/fields'; export { getDefaultReferenceDate } from './utils/getDefaultReferenceDate'; export { executeInTheNextEventLoopTick, diff --git a/packages/x-date-pickers/src/internals/utils/fields.ts b/packages/x-date-pickers/src/internals/utils/fields.ts deleted file mode 100644 index ef5e19e58f08..000000000000 --- a/packages/x-date-pickers/src/internals/utils/fields.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { FieldValueType } from '../../models'; -import { - DATE_TIME_VALIDATION_PROP_NAMES, - DATE_VALIDATION_PROP_NAMES, - TIME_VALIDATION_PROP_NAMES, -} from './validation/extractValidationProps'; - -const SHARED_FIELD_INTERNAL_PROP_NAMES = [ - 'value', - 'defaultValue', - 'referenceDate', - 'format', - 'formatDensity', - 'onChange', - 'timezone', - 'onError', - 'shouldRespectLeadingZeros', - 'selectedSections', - 'onSelectedSectionsChange', - 'unstableFieldRef', - 'enableAccessibleFieldDOMStructure', - 'disabled', - 'readOnly', - 'dateSeparator', -] as const; - -export const splitFieldInternalAndForwardedProps = < - TProps extends {}, - TInternalPropNames extends keyof TProps, ->( - props: TProps, - valueType: FieldValueType, -) => { - const forwardedProps = { ...props } as Omit; - const internalProps = {} as Pick; - - const extractProp = (propName: string) => { - if (forwardedProps.hasOwnProperty(propName)) { - // @ts-ignore - internalProps[propName] = forwardedProps[propName]; - delete forwardedProps[propName as keyof typeof forwardedProps]; - } - }; - - SHARED_FIELD_INTERNAL_PROP_NAMES.forEach(extractProp); - - if (valueType === 'date') { - DATE_VALIDATION_PROP_NAMES.forEach(extractProp); - } else if (valueType === 'time') { - TIME_VALIDATION_PROP_NAMES.forEach(extractProp); - } else if (valueType === 'date-time') { - DATE_VALIDATION_PROP_NAMES.forEach(extractProp); - TIME_VALIDATION_PROP_NAMES.forEach(extractProp); - DATE_TIME_VALIDATION_PROP_NAMES.forEach(extractProp); - } - - return { forwardedProps, internalProps }; -}; diff --git a/scripts/x-date-pickers-pro.exports.json b/scripts/x-date-pickers-pro.exports.json index 2c71d64e476b..fd3804e2fe8a 100644 --- a/scripts/x-date-pickers-pro.exports.json +++ b/scripts/x-date-pickers-pro.exports.json @@ -418,6 +418,7 @@ { "name": "UseSingleInputDateRangeFieldProps", "kind": "Interface" }, { "name": "UseSingleInputDateTimeRangeFieldProps", "kind": "Interface" }, { "name": "UseSingleInputTimeRangeFieldProps", "kind": "Interface" }, + { "name": "useSplitFieldInternalAndForwardedProps", "kind": "Variable" }, { "name": "UseTimeFieldComponentProps", "kind": "TypeAlias" }, { "name": "UseTimeFieldProps", "kind": "Interface" }, { "name": "YearCalendar", "kind": "Variable" }, diff --git a/scripts/x-date-pickers.exports.json b/scripts/x-date-pickers.exports.json index db45cedd262a..4b8228600b6a 100644 --- a/scripts/x-date-pickers.exports.json +++ b/scripts/x-date-pickers.exports.json @@ -300,6 +300,7 @@ { "name": "UseDateTimeFieldProps", "kind": "Interface" }, { "name": "usePickerLayout", "kind": "ExportAssignment" }, { "name": "usePickersTranslations", "kind": "Variable" }, + { "name": "useSplitFieldInternalAndForwardedProps", "kind": "Variable" }, { "name": "UseTimeFieldComponentProps", "kind": "TypeAlias" }, { "name": "UseTimeFieldProps", "kind": "Interface" }, { "name": "YearCalendar", "kind": "Variable" }, From e57c8e96becb8dbfd6a650bc2aebb68bacad0546 Mon Sep 17 00:00:00 2001 From: delangle Date: Fri, 6 Sep 2024 11:07:52 +0200 Subject: [PATCH 5/8] Fix --- docs/data/date-pickers/experimentation/CustomField.js | 4 ++-- docs/data/date-pickers/experimentation/CustomField.tsx | 4 ++-- .../SingleInputDateRangeField/useSingleInputDateRangeField.ts | 2 +- .../useSingleInputDateTimeRangeField.ts | 2 +- .../SingleInputTimeRangeField/useSingleInputTimeRangeField.ts | 2 +- packages/x-date-pickers/src/DateField/useDateField.ts | 2 +- packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts | 2 +- packages/x-date-pickers/src/TimeField/useTimeField.ts | 2 +- .../src/hooks/useSplitFieldInternalAndForwardedProps.ts | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/data/date-pickers/experimentation/CustomField.js b/docs/data/date-pickers/experimentation/CustomField.js index 376159d6793a..004575882af5 100644 --- a/docs/data/date-pickers/experimentation/CustomField.js +++ b/docs/data/date-pickers/experimentation/CustomField.js @@ -7,10 +7,10 @@ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { useValidation, validateDate } from '@mui/x-date-pickers/validation'; -import { splitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/internals'; +import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; function ReadOnlyField(props) { - const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps( + const { internalProps, forwardedProps } = useSplitFieldInternalAndForwardedProps( props, 'date', ); diff --git a/docs/data/date-pickers/experimentation/CustomField.tsx b/docs/data/date-pickers/experimentation/CustomField.tsx index 7cd411931895..a48cb3112dee 100644 --- a/docs/data/date-pickers/experimentation/CustomField.tsx +++ b/docs/data/date-pickers/experimentation/CustomField.tsx @@ -7,10 +7,10 @@ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { useValidation, validateDate } from '@mui/x-date-pickers/validation'; import { DateFieldInPickerProps } from '@mui/x-date-pickers/DateField'; -import { splitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/internals'; +import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; function ReadOnlyField(props: DateFieldInPickerProps) { - const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps( + const { internalProps, forwardedProps } = useSplitFieldInternalAndForwardedProps( props, 'date', ); diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts index da597fc85e41..53f69e5d4cf7 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts @@ -4,7 +4,7 @@ import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hook import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputDateRangeFieldProps } from './SingleInputDateRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; -import { validateDateRange } from '../internals/utils/validation/validateDateRange'; +import { validateDateRange } from '../validation'; import { RangeFieldSection, DateRange } from '../models'; export const useSingleInputDateRangeField = < diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts index cd15fe7d7498..c55b12900ace 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts @@ -4,7 +4,7 @@ import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hook import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputDateTimeRangeFieldProps } from './SingleInputDateTimeRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; -import { validateDateTimeRange } from '../internals/utils/validation/validateDateTimeRange'; +import { validateDateTimeRange } from '../validation'; import { RangeFieldSection, DateRange } from '../models'; export const useSingleInputDateTimeRangeField = < diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts index 91bbad42aea6..5a92cc02e7ca 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts @@ -4,7 +4,7 @@ import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hook import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputTimeRangeFieldProps } from './SingleInputTimeRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; -import { validateTimeRange } from '../internals/utils/validation/validateTimeRange'; +import { validateTimeRange } from '../validation'; import { RangeFieldSection, DateRange } from '../models'; export const useSingleInputTimeRangeField = < diff --git a/packages/x-date-pickers/src/DateField/useDateField.ts b/packages/x-date-pickers/src/DateField/useDateField.ts index 96b3c0575308..899ddb71230c 100644 --- a/packages/x-date-pickers/src/DateField/useDateField.ts +++ b/packages/x-date-pickers/src/DateField/useDateField.ts @@ -4,7 +4,7 @@ import { } from '../internals/utils/valueManagers'; import { useField } from '../internals/hooks/useField'; import { UseDateFieldProps } from './DateField.types'; -import { validateDate } from '../internals/utils/validation/validateDate'; +import { validateDate } from '../validation'; import { useSplitFieldInternalAndForwardedProps } from '../hooks'; import { FieldSection, PickerValidDate } from '../models'; import { useDefaultizedDateField } from '../internals/hooks/defaultizedFieldProps'; diff --git a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts index 0765bbf4d799..9c706458cb53 100644 --- a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts +++ b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts @@ -4,7 +4,7 @@ import { } from '../internals/utils/valueManagers'; import { useField } from '../internals/hooks/useField'; import { UseDateTimeFieldProps } from './DateTimeField.types'; -import { validateDateTime } from '../internals/utils/validation/validateDateTime'; +import { validateDateTime } from '../validation'; import { useSplitFieldInternalAndForwardedProps } from '../hooks'; import { FieldSection, PickerValidDate } from '../models'; import { useDefaultizedDateTimeField } from '../internals/hooks/defaultizedFieldProps'; diff --git a/packages/x-date-pickers/src/TimeField/useTimeField.ts b/packages/x-date-pickers/src/TimeField/useTimeField.ts index 38d01e3de116..1c1b3c81721f 100644 --- a/packages/x-date-pickers/src/TimeField/useTimeField.ts +++ b/packages/x-date-pickers/src/TimeField/useTimeField.ts @@ -4,7 +4,7 @@ import { } from '../internals/utils/valueManagers'; import { useField } from '../internals/hooks/useField'; import { UseTimeFieldProps } from './TimeField.types'; -import { validateTime } from '../internals/utils/validation/validateTime'; +import { validateTime } from '../validation'; import { useSplitFieldInternalAndForwardedProps } from '../hooks'; import { PickerValidDate, FieldSection } from '../models'; import { useDefaultizedTimeField } from '../internals/hooks/defaultizedFieldProps'; diff --git a/packages/x-date-pickers/src/hooks/useSplitFieldInternalAndForwardedProps.ts b/packages/x-date-pickers/src/hooks/useSplitFieldInternalAndForwardedProps.ts index 3b3beafac4a7..d03b5f96489a 100644 --- a/packages/x-date-pickers/src/hooks/useSplitFieldInternalAndForwardedProps.ts +++ b/packages/x-date-pickers/src/hooks/useSplitFieldInternalAndForwardedProps.ts @@ -4,7 +4,7 @@ import { DATE_TIME_VALIDATION_PROP_NAMES, DATE_VALIDATION_PROP_NAMES, TIME_VALIDATION_PROP_NAMES, -} from '../internals/utils/validation/extractValidationProps'; +} from '../validation/extractValidationProps'; const SHARED_FIELD_INTERNAL_PROP_NAMES = [ 'value', From 7450d24f11b8977c8f92c00ad5e1041007adf3d0 Mon Sep 17 00:00:00 2001 From: delangle Date: Fri, 6 Sep 2024 11:12:52 +0200 Subject: [PATCH 6/8] Fix --- .../MultiInputDateTimeRangeField.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx index 9e835c2b9dfa..c376a30140a7 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx @@ -20,7 +20,6 @@ import { MultiInputDateTimeRangeFieldSlotProps, } from './MultiInputDateTimeRangeField.types'; import { useMultiInputDateTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField'; -import { UseDateTimeRangeFieldProps } from '../internals/models/dateTimeRange'; import { MultiInputRangeFieldClasses, RangePosition } from '../models'; export const multiInputDateTimeRangeFieldClasses: MultiInputRangeFieldClasses = From 2135d08b153b1b8abb6b8c714d6b81e2b596ed6d Mon Sep 17 00:00:00 2001 From: delangle Date: Wed, 11 Sep 2024 12:00:18 +0200 Subject: [PATCH 7/8] Review Lukas --- .../MultiInputDateRangeField/MultiInputDateRangeField.tsx | 7 ++----- .../MultiInputDateTimeRangeField.tsx | 7 ++----- .../MultiInputTimeRangeField/MultiInputTimeRangeField.tsx | 7 ++----- .../useSingleInputDateRangeField.ts | 4 ++-- .../useSingleInputDateTimeRangeField.ts | 7 ++----- .../useSingleInputTimeRangeField.ts | 4 ++-- packages/x-date-pickers/src/DateField/useDateField.ts | 4 ++-- .../x-date-pickers/src/DateTimeField/useDateTimeField.ts | 7 ++----- packages/x-date-pickers/src/TimeField/useTimeField.ts | 4 ++-- packages/x-date-pickers/src/hooks/index.tsx | 2 +- ...dInternalAndForwardedProps.ts => useSplitFieldProps.ts} | 2 +- scripts/x-date-pickers-pro.exports.json | 2 +- scripts/x-date-pickers.exports.json | 2 +- 13 files changed, 22 insertions(+), 37 deletions(-) rename packages/x-date-pickers/src/hooks/{useSplitFieldInternalAndForwardedProps.ts => useSplitFieldProps.ts} (98%) diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx index 18985fc472fc..8057f8a77ec4 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx @@ -12,7 +12,7 @@ import { unstable_generateUtilityClasses as generateUtilityClasses, } from '@mui/utils'; import { convertFieldResponseIntoMuiTextFieldProps } from '@mui/x-date-pickers/internals'; -import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { @@ -89,10 +89,7 @@ const MultiInputDateRangeField = React.forwardRef(function MultiInputDateRangeFi name: 'MuiMultiInputDateRangeField', }); - const { internalProps, forwardedProps } = useSplitFieldInternalAndForwardedProps( - themeProps, - 'date', - ); + const { internalProps, forwardedProps } = useSplitFieldProps(themeProps, 'date'); const { slots, diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx index c376a30140a7..dad5102db3d6 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx @@ -12,7 +12,7 @@ import { unstable_generateUtilityClasses as generateUtilityClasses, } from '@mui/utils'; import { convertFieldResponseIntoMuiTextFieldProps } from '@mui/x-date-pickers/internals'; -import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { @@ -87,10 +87,7 @@ const MultiInputDateTimeRangeField = React.forwardRef(function MultiInputDateTim name: 'MuiMultiInputDateTimeRangeField', }); - const { internalProps, forwardedProps } = useSplitFieldInternalAndForwardedProps( - themeProps, - 'date-time', - ); + const { internalProps, forwardedProps } = useSplitFieldProps(themeProps, 'date-time'); const { slots, diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx index e8627f5dbd6b..b4f3706e6696 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx @@ -12,7 +12,7 @@ import { unstable_generateUtilityClasses as generateUtilityClasses, } from '@mui/utils'; import { convertFieldResponseIntoMuiTextFieldProps } from '@mui/x-date-pickers/internals'; -import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { @@ -89,10 +89,7 @@ const MultiInputTimeRangeField = React.forwardRef(function MultiInputTimeRangeFi name: 'MuiMultiInputTimeRangeField', }); - const { internalProps, forwardedProps } = useSplitFieldInternalAndForwardedProps( - themeProps, - 'time', - ); + const { internalProps, forwardedProps } = useSplitFieldProps(themeProps, 'time'); const { slots, diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts index da597fc85e41..06bcd2efd335 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import { useField, useDefaultizedDateField } from '@mui/x-date-pickers/internals'; -import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputDateRangeFieldProps } from './SingleInputDateRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; @@ -20,7 +20,7 @@ export const useSingleInputDateRangeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps(props, 'date'); + const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date'); const fieldValueManager = React.useMemo( () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts index cd15fe7d7498..62356882aa58 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import { useField, useDefaultizedDateTimeField } from '@mui/x-date-pickers/internals'; -import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputDateTimeRangeFieldProps } from './SingleInputDateTimeRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; @@ -23,10 +23,7 @@ export const useSingleInputDateTimeRangeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps( - props, - 'date-time', - ); + const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date-time'); const fieldValueManager = React.useMemo( () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts index 91bbad42aea6..2d5836c8882c 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import { useField, useDefaultizedTimeField } from '@mui/x-date-pickers/internals'; -import { useSplitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/hooks'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { UseSingleInputTimeRangeFieldProps } from './SingleInputTimeRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; @@ -20,7 +20,7 @@ export const useSingleInputTimeRangeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps(props, 'time'); + const { forwardedProps, internalProps } = useSplitFieldProps(props, 'time'); const fieldValueManager = React.useMemo( () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), diff --git a/packages/x-date-pickers/src/DateField/useDateField.ts b/packages/x-date-pickers/src/DateField/useDateField.ts index 96b3c0575308..ff4404d47421 100644 --- a/packages/x-date-pickers/src/DateField/useDateField.ts +++ b/packages/x-date-pickers/src/DateField/useDateField.ts @@ -5,7 +5,7 @@ import { import { useField } from '../internals/hooks/useField'; import { UseDateFieldProps } from './DateField.types'; import { validateDate } from '../internals/utils/validation/validateDate'; -import { useSplitFieldInternalAndForwardedProps } from '../hooks'; +import { useSplitFieldProps } from '../hooks'; import { FieldSection, PickerValidDate } from '../models'; import { useDefaultizedDateField } from '../internals/hooks/defaultizedFieldProps'; @@ -22,7 +22,7 @@ export const useDateField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps(props, 'date'); + const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date'); return useField< TDate | null, diff --git a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts index 0765bbf4d799..3b698f37a133 100644 --- a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts +++ b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts @@ -5,7 +5,7 @@ import { import { useField } from '../internals/hooks/useField'; import { UseDateTimeFieldProps } from './DateTimeField.types'; import { validateDateTime } from '../internals/utils/validation/validateDateTime'; -import { useSplitFieldInternalAndForwardedProps } from '../hooks'; +import { useSplitFieldProps } from '../hooks'; import { FieldSection, PickerValidDate } from '../models'; import { useDefaultizedDateTimeField } from '../internals/hooks/defaultizedFieldProps'; @@ -22,10 +22,7 @@ export const useDateTimeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps( - props, - 'date-time', - ); + const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date-time'); return useField< TDate | null, diff --git a/packages/x-date-pickers/src/TimeField/useTimeField.ts b/packages/x-date-pickers/src/TimeField/useTimeField.ts index 38d01e3de116..e3f97c8b4b5c 100644 --- a/packages/x-date-pickers/src/TimeField/useTimeField.ts +++ b/packages/x-date-pickers/src/TimeField/useTimeField.ts @@ -5,7 +5,7 @@ import { import { useField } from '../internals/hooks/useField'; import { UseTimeFieldProps } from './TimeField.types'; import { validateTime } from '../internals/utils/validation/validateTime'; -import { useSplitFieldInternalAndForwardedProps } from '../hooks'; +import { useSplitFieldProps } from '../hooks'; import { PickerValidDate, FieldSection } from '../models'; import { useDefaultizedTimeField } from '../internals/hooks/defaultizedFieldProps'; @@ -22,7 +22,7 @@ export const useTimeField = < TAllProps >(inProps); - const { forwardedProps, internalProps } = useSplitFieldInternalAndForwardedProps(props, 'time'); + const { forwardedProps, internalProps } = useSplitFieldProps(props, 'time'); return useField< TDate | null, diff --git a/packages/x-date-pickers/src/hooks/index.tsx b/packages/x-date-pickers/src/hooks/index.tsx index 4742cecac399..e4ca216906f0 100644 --- a/packages/x-date-pickers/src/hooks/index.tsx +++ b/packages/x-date-pickers/src/hooks/index.tsx @@ -8,4 +8,4 @@ export type { export { usePickersTranslations } from './usePickersTranslations'; -export { useSplitFieldInternalAndForwardedProps } from './useSplitFieldInternalAndForwardedProps'; +export { useSplitFieldProps } from './useSplitFieldProps'; diff --git a/packages/x-date-pickers/src/hooks/useSplitFieldInternalAndForwardedProps.ts b/packages/x-date-pickers/src/hooks/useSplitFieldProps.ts similarity index 98% rename from packages/x-date-pickers/src/hooks/useSplitFieldInternalAndForwardedProps.ts rename to packages/x-date-pickers/src/hooks/useSplitFieldProps.ts index 3b3beafac4a7..150823985f69 100644 --- a/packages/x-date-pickers/src/hooks/useSplitFieldInternalAndForwardedProps.ts +++ b/packages/x-date-pickers/src/hooks/useSplitFieldProps.ts @@ -41,7 +41,7 @@ type InternalPropNames = * @param {TProps} props The props received by the field component. * @param {TValueType} valueType The type of the field value ('date', 'time', or 'date-time'). */ -export const useSplitFieldInternalAndForwardedProps = < +export const useSplitFieldProps = < TValueType extends FieldValueType, TProps extends { [key in InternalPropNames]?: any }, >( diff --git a/scripts/x-date-pickers-pro.exports.json b/scripts/x-date-pickers-pro.exports.json index fd3804e2fe8a..9674b138dfd2 100644 --- a/scripts/x-date-pickers-pro.exports.json +++ b/scripts/x-date-pickers-pro.exports.json @@ -418,7 +418,7 @@ { "name": "UseSingleInputDateRangeFieldProps", "kind": "Interface" }, { "name": "UseSingleInputDateTimeRangeFieldProps", "kind": "Interface" }, { "name": "UseSingleInputTimeRangeFieldProps", "kind": "Interface" }, - { "name": "useSplitFieldInternalAndForwardedProps", "kind": "Variable" }, + { "name": "useSplitFieldProps", "kind": "Variable" }, { "name": "UseTimeFieldComponentProps", "kind": "TypeAlias" }, { "name": "UseTimeFieldProps", "kind": "Interface" }, { "name": "YearCalendar", "kind": "Variable" }, diff --git a/scripts/x-date-pickers.exports.json b/scripts/x-date-pickers.exports.json index 4b8228600b6a..1df3b6ad87cb 100644 --- a/scripts/x-date-pickers.exports.json +++ b/scripts/x-date-pickers.exports.json @@ -300,7 +300,7 @@ { "name": "UseDateTimeFieldProps", "kind": "Interface" }, { "name": "usePickerLayout", "kind": "ExportAssignment" }, { "name": "usePickersTranslations", "kind": "Variable" }, - { "name": "useSplitFieldInternalAndForwardedProps", "kind": "Variable" }, + { "name": "useSplitFieldProps", "kind": "Variable" }, { "name": "UseTimeFieldComponentProps", "kind": "TypeAlias" }, { "name": "UseTimeFieldProps", "kind": "Interface" }, { "name": "YearCalendar", "kind": "Variable" }, From d6cc98e9a6a5ba1c6d72a278bf1061816d58c36a Mon Sep 17 00:00:00 2001 From: delangle Date: Wed, 11 Sep 2024 13:20:18 +0200 Subject: [PATCH 8/8] Empty