From 8bb1bd418267ed3693061da09127816c4638eb0a Mon Sep 17 00:00:00 2001 From: flavien Date: Tue, 5 Nov 2024 17:45:38 +0100 Subject: [PATCH] [pickers] Replace TValue and TSection generics with TIsRange --- .../custom-field/BrowserV7Field.tsx | 10 +- .../BrowserV7MultiInputRangeField.tsx | 11 +- .../BrowserV7SingleInputRangeField.tsx | 15 +- .../date-pickers/custom-field/JoyV6Field.tsx | 10 +- .../JoyV6MultiInputRangeField.tsx | 11 +- .../JoyV6SingleInputRangeField.tsx | 20 +- .../date-pickers/custom-field/custom-field.md | 6 +- ...dSelectedSectionsSingleInputRangeField.tsx | 4 +- .../overview/mainDemo/PickerButton.tsx | 15 +- .../DateRangeCalendar/DateRangeCalendar.tsx | 4 +- .../DateRangeCalendar.types.ts | 2 +- .../DateRangePicker/DateRangePicker.types.ts | 6 +- .../DateRangePickerToolbar.tsx | 3 +- .../src/DateRangePicker/shared.tsx | 5 +- .../DateTimeRangePicker.types.ts | 15 +- .../DateTimeRangePickerToolbar.tsx | 3 +- .../src/DateTimeRangePicker/shared.tsx | 9 +- .../SingleInputDateRangeField.types.ts | 15 +- .../useSingleInputDateRangeField.ts | 6 +- .../SingleInputDateTimeRangeField.types.ts | 11 +- .../useSingleInputDateTimeRangeField.ts | 10 +- .../SingleInputTimeRangeField.types.ts | 11 +- .../useSingleInputTimeRangeField.ts | 6 +- .../internals/hooks/models/useRangePicker.ts | 16 +- .../useDesktopRangePicker.tsx | 16 +- .../hooks/useEnrichedRangePickerFieldProps.ts | 46 +---- .../useMobileRangePicker.tsx | 16 +- .../useMultiInputFieldSelectedSections.ts | 9 +- .../useMultiInputDateRangeField.ts | 16 +- .../src/internals/hooks/useRangePosition.ts | 4 +- .../useStaticRangePicker.tsx | 7 +- .../useStaticRangePicker.types.ts | 10 +- .../src/internals/models/dateTimeRange.ts | 10 +- .../src/internals/models/timeRange.ts | 15 +- .../src/internals/utils/date-fields-utils.ts | 10 +- .../src/internals/utils/valueManagers.ts | 29 +-- .../src/models/dateRange.ts | 11 +- .../x-date-pickers-pro/src/models/fields.ts | 25 +-- .../x-date-pickers-pro/src/models/index.ts | 2 + .../x-date-pickers-pro/src/models/range.ts | 2 - .../src/validation/validateDateRange.ts | 4 +- .../src/validation/validateDateTimeRange.ts | 4 +- .../src/validation/validateTimeRange.ts | 8 +- .../src/DateCalendar/DateCalendar.tsx | 4 +- .../src/DateCalendar/DateCalendar.types.ts | 2 +- .../src/DateField/DateField.types.ts | 14 +- .../src/DateField/useDateField.ts | 4 +- .../src/DatePicker/DatePicker.types.ts | 9 +- .../src/DatePicker/DatePickerToolbar.tsx | 4 +- .../x-date-pickers/src/DatePicker/shared.tsx | 9 +- .../src/DateTimeField/DateTimeField.types.ts | 14 +- .../src/DateTimeField/useDateTimeField.ts | 4 +- .../DateTimePicker/DateTimePicker.types.ts | 9 +- .../DateTimePicker/DateTimePickerToolbar.tsx | 2 +- .../src/DateTimePicker/shared.tsx | 6 +- .../DesktopDateTimePickerLayout.tsx | 11 +- .../MultiSectionDigitalClock.tsx | 5 +- .../MultiSectionDigitalClock.types.ts | 14 +- .../MultiSectionDigitalClockSection.tsx | 15 +- .../src/PickersLayout/PickersLayout.tsx | 8 +- .../src/PickersLayout/PickersLayout.types.ts | 47 +++-- .../src/PickersLayout/usePickerLayout.tsx | 27 +-- .../src/PickersShortcuts/PickersShortcuts.tsx | 25 +-- .../src/TimeClock/TimeClock.tsx | 9 +- .../src/TimeField/TimeField.types.ts | 14 +- .../src/TimeField/useTimeField.ts | 4 +- .../src/TimePicker/TimePicker.types.ts | 9 +- .../src/TimePicker/TimePickerToolbar.tsx | 2 +- .../x-date-pickers/src/TimePicker/shared.tsx | 6 +- .../src/hooks/useParsedFormat.ts | 2 +- .../internals/components/PickersToolbar.tsx | 17 +- .../internals/hooks/useClockReferenceDate.ts | 2 +- .../useDesktopPicker/useDesktopPicker.tsx | 16 +- .../useDesktopPicker.types.ts | 26 +-- .../src/internals/hooks/useField/useField.ts | 12 +- .../hooks/useField/useField.types.ts | 145 +++++++-------- .../hooks/useField/useField.utils.ts | 9 +- .../useField/useFieldCharacterEditing.ts | 37 ++-- .../internals/hooks/useField/useFieldState.ts | 44 +++-- .../hooks/useField/useFieldV6TextField.ts | 12 +- .../hooks/useMobilePicker/useMobilePicker.tsx | 16 +- .../useMobilePicker/useMobilePicker.types.ts | 24 +-- .../internals/hooks/usePicker/usePicker.ts | 22 +-- .../hooks/usePicker/usePicker.types.ts | 36 ++-- .../hooks/usePicker/usePickerLayoutProps.ts | 30 ++- .../hooks/usePicker/usePickerOwnerState.ts | 14 +- .../hooks/usePicker/usePickerProvider.ts | 10 +- .../hooks/usePicker/usePickerValue.ts | 47 +++-- .../hooks/usePicker/usePickerValue.types.ts | 175 ++++++++++-------- .../hooks/usePicker/usePickerViews.ts | 51 +++-- .../hooks/useStaticPicker/useStaticPicker.tsx | 4 +- .../useStaticPicker/useStaticPicker.types.ts | 11 +- .../internals/hooks/useValueWithTimezone.ts | 45 +++-- .../src/internals/hooks/useViews.tsx | 37 ++-- .../x-date-pickers/src/internals/index.ts | 3 +- .../src/internals/models/fields.ts | 7 +- .../src/internals/models/pickers.ts | 1 + .../models/props/basePickerProps.tsx | 17 +- .../src/internals/models/props/time.ts | 2 +- .../src/internals/models/props/toolbar.ts | 11 +- .../src/internals/models/value.ts | 14 ++ .../src/internals/utils/date-utils.ts | 6 +- .../src/internals/utils/valueManagers.ts | 14 +- packages/x-date-pickers/src/models/fields.ts | 22 ++- .../x-date-pickers/src/models/validation.ts | 10 +- .../src/themeAugmentation/props.d.ts | 4 +- .../src/validation/useValidation.ts | 41 ++-- .../src/validation/validateDate.ts | 13 +- .../src/validation/validateDateTime.ts | 13 +- .../src/validation/validateTime.ts | 13 +- .../pickers/describeValue/describeValue.tsx | 20 +- test/utils/pickers/fields.tsx | 6 +- 112 files changed, 802 insertions(+), 1004 deletions(-) create mode 100644 packages/x-date-pickers/src/internals/models/pickers.ts diff --git a/docs/data/date-pickers/custom-field/BrowserV7Field.tsx b/docs/data/date-pickers/custom-field/BrowserV7Field.tsx index 00e3b3388d57..8dde2eaf5cb4 100644 --- a/docs/data/date-pickers/custom-field/BrowserV7Field.tsx +++ b/docs/data/date-pickers/custom-field/BrowserV7Field.tsx @@ -13,8 +13,6 @@ import { BaseSingleInputPickersTextFieldProps, BaseSingleInputFieldProps, DateValidationError, - FieldSection, - PickerValidDate, } from '@mui/x-date-pickers/models'; import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-pickers/PickersSectionList'; @@ -106,13 +104,7 @@ const BrowserTextField = React.forwardRef( interface BrowserDateFieldProps extends UseDateFieldProps, - BaseSingleInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - PickerValidDate | null, - FieldSection, - true, - DateValidationError - > {} + BaseSingleInputFieldProps {} const BrowserDateField = React.forwardRef( (props: BrowserDateFieldProps, ref: React.Ref) => { diff --git a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx index 725a629ce03f..1aef1765678f 100644 --- a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx +++ b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx @@ -5,7 +5,6 @@ import { styled } from '@mui/material/styles'; import Stack from '@mui/material/Stack'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import { PickerValidDate } from '@mui/x-date-pickers/models'; import { DateRangePicker, DateRangePickerProps, @@ -13,12 +12,10 @@ import { import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-pickers/PickersSectionList'; import { - RangeFieldSection, BaseMultiInputFieldProps, BasePickersTextFieldProps, MultiInputFieldSlotTextFieldProps, DateRangeValidationError, - DateRange, UseDateRangeFieldProps, } from '@mui/x-date-pickers-pro/models'; @@ -109,13 +106,7 @@ const BrowserTextField = React.forwardRef( interface BrowserMultiInputDateRangeFieldProps extends UseDateRangeFieldProps, - BaseMultiInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - DateRange, - RangeFieldSection, - true, - DateRangeValidationError - > {} + BaseMultiInputFieldProps {} type BrowserMultiInputDateRangeFieldComponent = (( props: BrowserMultiInputDateRangeFieldProps & React.RefAttributes, diff --git a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx index adfe26146591..645ad6a40d3e 100644 --- a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx +++ b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx @@ -20,14 +20,9 @@ import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-p import { BasePickersTextFieldProps, DateRangeValidationError, - RangeFieldSection, - DateRange, FieldType, } from '@mui/x-date-pickers-pro/models'; -import { - BaseSingleInputFieldProps, - PickerValidDate, -} from '@mui/x-date-pickers/models'; +import { BaseSingleInputFieldProps } from '@mui/x-date-pickers/models'; const BrowserFieldRoot = styled('div', { name: 'BrowserField', slot: 'Root' })({ display: 'flex', @@ -117,13 +112,7 @@ const BrowserTextField = React.forwardRef( interface BrowserSingleInputDateRangeFieldProps extends UseSingleInputDateRangeFieldProps, - BaseSingleInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - DateRange, - RangeFieldSection, - true, - DateRangeValidationError - > { + BaseSingleInputFieldProps { onAdornmentClick?: () => void; } diff --git a/docs/data/date-pickers/custom-field/JoyV6Field.tsx b/docs/data/date-pickers/custom-field/JoyV6Field.tsx index a2dfdebe9255..3e6fe512b018 100644 --- a/docs/data/date-pickers/custom-field/JoyV6Field.tsx +++ b/docs/data/date-pickers/custom-field/JoyV6Field.tsx @@ -24,8 +24,6 @@ import { useClearableField } from '@mui/x-date-pickers/hooks'; import { BaseSingleInputFieldProps, DateValidationError, - FieldSection, - PickerValidDate, } from '@mui/x-date-pickers/models'; const joyTheme = extendJoyTheme(); @@ -101,13 +99,7 @@ const JoyField = React.forwardRef( interface JoyDateFieldProps extends UseDateFieldProps, - BaseSingleInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - PickerValidDate | null, - FieldSection, - false, - DateValidationError - > {} + BaseSingleInputFieldProps {} const JoyDateField = React.forwardRef( (props: JoyDateFieldProps, ref: React.Ref) => { diff --git a/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx index ce976dd69843..f8bfb47aad8e 100644 --- a/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx +++ b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx @@ -19,7 +19,6 @@ import FormLabel from '@mui/joy/FormLabel'; import Typography, { TypographyProps } from '@mui/joy/Typography'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import { PickerValidDate } from '@mui/x-date-pickers/models'; import { DateRangePicker, DateRangePickerProps, @@ -27,10 +26,8 @@ import { import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; import { BaseMultiInputFieldProps, - DateRange, DateRangeValidationError, MultiInputFieldSlotTextFieldProps, - RangeFieldSection, UseDateRangeFieldProps, } from '@mui/x-date-pickers-pro/models'; @@ -133,13 +130,7 @@ const MultiInputJoyDateRangeFieldSeparator = styled( interface JoyMultiInputDateRangeFieldProps extends UseDateRangeFieldProps, - BaseMultiInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - DateRange, - RangeFieldSection, - false, - DateRangeValidationError - > {} + BaseMultiInputFieldProps {} type JoyMultiInputDateRangeFieldComponent = (( props: JoyMultiInputDateRangeFieldProps & React.RefAttributes, diff --git a/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx index e2815f70d823..f587a5760d7b 100644 --- a/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx +++ b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx @@ -27,16 +27,8 @@ import { UseSingleInputDateRangeFieldProps, } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; import { useClearableField } from '@mui/x-date-pickers/hooks'; -import { - BaseSingleInputFieldProps, - PickerValidDate, -} from '@mui/x-date-pickers/models'; -import { - RangeFieldSection, - DateRange, - DateRangeValidationError, - FieldType, -} from '@mui/x-date-pickers-pro/models'; +import { BaseSingleInputFieldProps } from '@mui/x-date-pickers/models'; +import { DateRangeValidationError, FieldType } from '@mui/x-date-pickers-pro/models'; const joyTheme = extendJoyTheme(); @@ -104,13 +96,7 @@ const JoyField = React.forwardRef( interface JoySingleInputDateRangeFieldProps extends UseSingleInputDateRangeFieldProps, - BaseSingleInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - DateRange, - RangeFieldSection, - false, - DateRangeValidationError - > { + BaseSingleInputFieldProps { onAdornmentClick?: () => void; } diff --git a/docs/data/date-pickers/custom-field/custom-field.md b/docs/data/date-pickers/custom-field/custom-field.md index 3b9459feb141..a2f66e7a004e 100644 --- a/docs/data/date-pickers/custom-field/custom-field.md +++ b/docs/data/date-pickers/custom-field/custom-field.md @@ -165,8 +165,7 @@ On the examples below, you can see that the typing of the props received by a cu interface JoyDateFieldProps extends UseDateFieldProps, // The headless field props BaseSingleInputFieldProps< - Dayjs | null, - FieldSection, + false, true, // `false` for `enableAccessibleFieldDOMStructure={false}` DateValidationError > {} // The DOM field props @@ -174,8 +173,7 @@ interface JoyDateFieldProps interface JoyDateTimeFieldProps extends UseDateTimeFieldProps, // The headless field props BaseSingleInputFieldProps< - Dayjs | null, - FieldSection, + false, true, // `false` for `enableAccessibleFieldDOMStructure={false}` DateTimeValidationError > {} // The DOM field props diff --git a/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx b/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx index 68995de41ed1..745dc885db66 100644 --- a/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx +++ b/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx @@ -9,14 +9,14 @@ import { FieldSelectedSections, FieldRef, } from '@mui/x-date-pickers/models'; -import { RangeFieldSection, RangePosition } from '@mui/x-date-pickers-pro/models'; +import { RangePosition } from '@mui/x-date-pickers-pro/models'; import { SingleInputDateRangeField } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; export default function ControlledSelectedSectionsSingleInputRangeField() { const [selectedSections, setSelectedSections] = React.useState(null); const inputRef = React.useRef(null); - const fieldRef = React.useRef>(null); + const fieldRef = React.useRef>(null); const setSelectedSectionType = ( selectedSectionType: FieldSectionType, diff --git a/docs/src/modules/components/overview/mainDemo/PickerButton.tsx b/docs/src/modules/components/overview/mainDemo/PickerButton.tsx index 7dee0bad4fed..1d973ae215e7 100644 --- a/docs/src/modules/components/overview/mainDemo/PickerButton.tsx +++ b/docs/src/modules/components/overview/mainDemo/PickerButton.tsx @@ -5,22 +5,11 @@ import Card from '@mui/material/Card'; import CalendarTodayRoundedIcon from '@mui/icons-material/CalendarTodayRounded'; import { UseDateFieldProps } from '@mui/x-date-pickers/DateField'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; -import { - BaseSingleInputFieldProps, - DateValidationError, - FieldSection, - PickerValidDate, -} from '@mui/x-date-pickers/models'; +import { BaseSingleInputFieldProps, DateValidationError } from '@mui/x-date-pickers/models'; interface ButtonFieldProps extends UseDateFieldProps, - BaseSingleInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - PickerValidDate | null, - FieldSection, - true, - DateValidationError - > { + BaseSingleInputFieldProps { setOpen?: React.Dispatch>; } diff --git a/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx b/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx index 0e7a18a2e7af..35016f1f2094 100644 --- a/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx +++ b/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx @@ -210,7 +210,7 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar( } = props; const { value, handleValueChange, timezone } = useControlledValueWithTimezone< - PickerRangeValue, + true, NonNullable >({ name: 'DateRangeCalendar', @@ -221,7 +221,7 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar( valueManager: rangeValueManager, }); - const { setValueAndGoToNextView, view } = useViews({ + const { setValueAndGoToNextView, view } = useViews({ view: inView, views, openTo, diff --git a/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.types.ts b/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.types.ts index 4bb144a7c0cb..e601478754f4 100644 --- a/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.types.ts +++ b/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.types.ts @@ -101,7 +101,7 @@ export interface ExportedDateRangeCalendarProps export interface DateRangeCalendarProps extends ExportedDateRangeCalendarProps, UseRangePositionProps, - ExportedUseViewsOptions { + ExportedUseViewsOptions { /** * The selected value. * Used when the component is controlled. diff --git a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.types.ts b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.types.ts index 326c9b650e99..d7564c8bac5f 100644 --- a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.types.ts +++ b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.types.ts @@ -1,5 +1,5 @@ import { MakeRequired } from '@mui/x-internals/types'; -import { BaseDateValidationProps, PickerRangeValue } from '@mui/x-date-pickers/internals'; +import { BaseDateValidationProps } from '@mui/x-date-pickers/internals'; import { BaseSingleInputFieldProps } from '@mui/x-date-pickers/models'; import { DesktopDateRangePickerProps, @@ -11,7 +11,7 @@ import { MobileDateRangePickerSlots, MobileDateRangePickerSlotProps, } from '../MobileDateRangePicker'; -import { DateRangeValidationError, RangeFieldSection, UseDateRangeFieldProps } from '../models'; +import { DateRangeValidationError, UseDateRangeFieldProps } from '../models'; export interface DateRangePickerSlots extends DesktopDateRangePickerSlots, @@ -50,4 +50,4 @@ export type DateRangePickerFieldProps, 'format' | 'timezone' | 'value' | keyof BaseDateValidationProps > & - BaseSingleInputFieldProps; + BaseSingleInputFieldProps; diff --git a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerToolbar.tsx b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerToolbar.tsx index 8273067b4870..9c2ccc92d091 100644 --- a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerToolbar.tsx +++ b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerToolbar.tsx @@ -11,7 +11,6 @@ import { useUtils, BaseToolbarProps, ExportedBaseToolbarProps, - PickerRangeValue, } from '@mui/x-date-pickers/internals'; import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; import { UseRangePositionResponse } from '../internals/hooks/useRangePosition'; @@ -32,7 +31,7 @@ const useUtilityClasses = (ownerState: DateRangePickerToolbarProps) => { export interface DateRangePickerToolbarProps extends ExportedDateRangePickerToolbarProps, - Omit, 'onChange' | 'isLandscape'>, + Omit, 'onChange' | 'isLandscape'>, Pick {} export interface ExportedDateRangePickerToolbarProps extends ExportedBaseToolbarProps { diff --git a/packages/x-date-pickers-pro/src/DateRangePicker/shared.tsx b/packages/x-date-pickers-pro/src/DateRangePicker/shared.tsx index b098d57cfb0f..4c44f8e7fab2 100644 --- a/packages/x-date-pickers-pro/src/DateRangePicker/shared.tsx +++ b/packages/x-date-pickers-pro/src/DateRangePicker/shared.tsx @@ -9,7 +9,6 @@ import { BaseDateValidationProps, BasePickerInputProps, PickerViewRendererLookup, - PickerRangeValue, } from '@mui/x-date-pickers/internals'; import { DateRangeValidationError } from '../models'; import { @@ -38,7 +37,7 @@ export interface BaseDateRangePickerSlotProps extends DateRangeCalendarSlotProps export interface BaseDateRangePickerProps extends Omit< - BasePickerInputProps, + BasePickerInputProps, 'view' | 'views' | 'openTo' | 'onViewChange' | 'orientation' >, ExportedDateRangeCalendarProps { @@ -58,7 +57,7 @@ export interface BaseDateRangePickerProps * If `undefined`, internally defined view will be used. */ viewRenderers?: Partial< - PickerViewRendererLookup, {}> + PickerViewRendererLookup, {}> >; } diff --git a/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePicker.types.ts b/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePicker.types.ts index 43998205dc64..7f12c8fc8a4d 100644 --- a/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePicker.types.ts +++ b/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePicker.types.ts @@ -1,9 +1,5 @@ import { MakeRequired } from '@mui/x-internals/types'; -import { - BaseDateValidationProps, - BaseTimeValidationProps, - PickerRangeValue, -} from '@mui/x-date-pickers/internals'; +import { BaseDateValidationProps, BaseTimeValidationProps } from '@mui/x-date-pickers/internals'; import { BaseSingleInputFieldProps } from '@mui/x-date-pickers/models'; import { DesktopDateTimeRangePickerProps, @@ -16,7 +12,7 @@ import { MobileDateTimeRangePickerSlotProps, } from '../MobileDateTimeRangePicker'; import { UseDateTimeRangeFieldProps } from '../internals/models'; -import { DateTimeRangeValidationError, RangeFieldSection } from '../models'; +import { DateTimeRangeValidationError } from '../models'; export interface DateTimeRangePickerSlots extends DesktopDateTimeRangePickerSlots, @@ -61,9 +57,4 @@ export type DateTimeRangePickerFieldProps< | keyof BaseDateValidationProps | keyof BaseTimeValidationProps > & - BaseSingleInputFieldProps< - PickerRangeValue, - RangeFieldSection, - false, - DateTimeRangeValidationError - >; + BaseSingleInputFieldProps; diff --git a/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerToolbar.tsx b/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerToolbar.tsx index cb78335558ed..d0b75e135ee7 100644 --- a/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerToolbar.tsx +++ b/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerToolbar.tsx @@ -10,7 +10,6 @@ import { useUtils, DateOrTimeViewWithMeridiem, WrapperVariant, - PickerRangeValue, } from '@mui/x-date-pickers/internals'; import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; @@ -39,7 +38,7 @@ const useUtilityClasses = (ownerState: DateTimeRangePickerToolbarProps) => { type DateTimeRangeViews = Exclude; export interface DateTimeRangePickerToolbarProps - extends BaseToolbarProps, + extends BaseToolbarProps, Pick, ExportedDateTimeRangePickerToolbarProps { ampm?: boolean; diff --git a/packages/x-date-pickers-pro/src/DateTimeRangePicker/shared.tsx b/packages/x-date-pickers-pro/src/DateTimeRangePicker/shared.tsx index d3f2d3127fd9..575c9fd41bea 100644 --- a/packages/x-date-pickers-pro/src/DateTimeRangePicker/shared.tsx +++ b/packages/x-date-pickers-pro/src/DateTimeRangePicker/shared.tsx @@ -17,7 +17,6 @@ import { UseViewsOptions, DateTimeValidationProps, DateOrTimeViewWithMeridiem, - PickerRangeValue, } from '@mui/x-date-pickers/internals'; import { TimeViewRendererProps } from '@mui/x-date-pickers/timeViewRenderers'; import { DigitalClockSlots, DigitalClockSlotProps } from '@mui/x-date-pickers/DigitalClock'; @@ -78,7 +77,7 @@ export type DateTimeRangePickerRenderers< TView extends DateOrTimeViewWithMeridiem, TAdditionalProps extends {} = {}, > = PickerViewRendererLookup< - PickerRangeValue, + true, TView, Omit, 'view' | 'slots' | 'slotProps'> & Omit< @@ -90,15 +89,13 @@ export type DateTimeRangePickerRenderers< export interface BaseDateTimeRangePickerProps extends Omit< - BasePickerInputProps, + BasePickerInputProps, 'orientation' | 'views' | 'openTo' >, ExportedDateRangeCalendarProps, BaseDateValidationProps, DesktopOnlyTimePickerProps, - Partial< - Pick, 'openTo' | 'views'> - >, + Partial, 'openTo' | 'views'>>, DateTimeValidationProps { /** * Overridable component slots. diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts index da88995ac304..ac6817f6a3d9 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts @@ -1,30 +1,21 @@ import * as React from 'react'; import { SlotComponentProps } from '@mui/utils'; import TextField from '@mui/material/TextField'; -import { UseFieldInternalProps, PickerRangeValue } from '@mui/x-date-pickers/internals'; +import { UseFieldInternalProps } from '@mui/x-date-pickers/internals'; import { BuiltInFieldTextFieldProps } from '@mui/x-date-pickers/models'; import { ExportedUseClearableFieldProps, UseClearableFieldSlots, UseClearableFieldSlotProps, } from '@mui/x-date-pickers/hooks'; -import type { - RangeFieldSection, - DateRangeValidationError, - UseDateRangeFieldProps, -} from '../models'; +import type { DateRangeValidationError, UseDateRangeFieldProps } from '../models'; export interface UseSingleInputDateRangeFieldProps< TEnableAccessibleFieldDOMStructure extends boolean, > extends UseDateRangeFieldProps, ExportedUseClearableFieldProps, Pick< - UseFieldInternalProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure, - DateRangeValidationError - >, + UseFieldInternalProps, 'unstableFieldRef' > {} diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts index 628a548326c4..75ae6ce7b018 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts @@ -1,11 +1,10 @@ 'use client'; import * as React from 'react'; -import { useField, useDefaultizedDateField, PickerRangeValue } from '@mui/x-date-pickers/internals'; +import { useField, useDefaultizedDateField } from '@mui/x-date-pickers/internals'; import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { UseSingleInputDateRangeFieldProps } from './SingleInputDateRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; import { validateDateRange } from '../validation'; -import { RangeFieldSection } from '../models'; export const useSingleInputDateRangeField = < TEnableAccessibleFieldDOMStructure extends boolean, @@ -26,8 +25,7 @@ export const useSingleInputDateRangeField = < ); return useField< - PickerRangeValue, - RangeFieldSection, + true, TEnableAccessibleFieldDOMStructure, typeof forwardedProps, typeof internalProps diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.types.ts b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.types.ts index 6632d68fc3eb..da7292cfe120 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.types.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { SlotComponentProps } from '@mui/utils'; import TextField from '@mui/material/TextField'; -import { UseFieldInternalProps, PickerRangeValue } from '@mui/x-date-pickers/internals'; +import { UseFieldInternalProps } from '@mui/x-date-pickers/internals'; import { BuiltInFieldTextFieldProps } from '@mui/x-date-pickers/models'; import { ExportedUseClearableFieldProps, @@ -9,19 +9,14 @@ import { UseClearableFieldSlotProps, } from '@mui/x-date-pickers/hooks'; import { UseDateTimeRangeFieldProps } from '../internals/models'; -import { RangeFieldSection, DateTimeRangeValidationError } from '../models'; +import { DateTimeRangeValidationError } from '../models'; export interface UseSingleInputDateTimeRangeFieldProps< TEnableAccessibleFieldDOMStructure extends boolean, > extends UseDateTimeRangeFieldProps, ExportedUseClearableFieldProps, Pick< - UseFieldInternalProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure, - DateTimeRangeValidationError - >, + UseFieldInternalProps, 'unstableFieldRef' > {} diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts index f96bfe35fd10..2e2dc22065a5 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts @@ -1,15 +1,10 @@ 'use client'; import * as React from 'react'; -import { - useField, - useDefaultizedDateTimeField, - PickerRangeValue, -} from '@mui/x-date-pickers/internals'; +import { useField, useDefaultizedDateTimeField } from '@mui/x-date-pickers/internals'; import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { UseSingleInputDateTimeRangeFieldProps } from './SingleInputDateTimeRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; import { validateDateTimeRange } from '../validation'; -import { RangeFieldSection } from '../models'; export const useSingleInputDateTimeRangeField = < TEnableAccessibleFieldDOMStructure extends boolean, @@ -30,8 +25,7 @@ export const useSingleInputDateTimeRangeField = < ); return useField< - PickerRangeValue, - RangeFieldSection, + true, TEnableAccessibleFieldDOMStructure, typeof forwardedProps, typeof internalProps diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts index 1cc0fa3fd483..2a19d339bd14 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { SlotComponentProps } from '@mui/utils'; import TextField from '@mui/material/TextField'; -import { PickerRangeValue, UseFieldInternalProps } from '@mui/x-date-pickers/internals'; +import { UseFieldInternalProps } from '@mui/x-date-pickers/internals'; import { BuiltInFieldTextFieldProps } from '@mui/x-date-pickers/models'; import { ExportedUseClearableFieldProps, @@ -9,19 +9,14 @@ import { UseClearableFieldSlotProps, } from '@mui/x-date-pickers/hooks'; import { UseTimeRangeFieldProps } from '../internals/models'; -import { RangeFieldSection, TimeRangeValidationError } from '../models'; +import { TimeRangeValidationError } from '../models'; export interface UseSingleInputTimeRangeFieldProps< TEnableAccessibleFieldDOMStructure extends boolean, > extends UseTimeRangeFieldProps, ExportedUseClearableFieldProps, Pick< - UseFieldInternalProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure, - TimeRangeValidationError - >, + UseFieldInternalProps, 'unstableFieldRef' > {} diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts index f7a4eec521e6..2c1933eae3e6 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts @@ -1,11 +1,10 @@ 'use client'; import * as React from 'react'; -import { useField, useDefaultizedTimeField, PickerRangeValue } from '@mui/x-date-pickers/internals'; +import { useField, useDefaultizedTimeField } from '@mui/x-date-pickers/internals'; import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { UseSingleInputTimeRangeFieldProps } from './SingleInputTimeRangeField.types'; import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; import { validateTimeRange } from '../validation'; -import { RangeFieldSection } from '../models'; export const useSingleInputTimeRangeField = < TEnableAccessibleFieldDOMStructure extends boolean, @@ -26,8 +25,7 @@ export const useSingleInputTimeRangeField = < ); return useField< - PickerRangeValue, - RangeFieldSection, + true, TEnableAccessibleFieldDOMStructure, typeof forwardedProps, typeof internalProps diff --git a/packages/x-date-pickers-pro/src/internals/hooks/models/useRangePicker.ts b/packages/x-date-pickers-pro/src/internals/hooks/models/useRangePicker.ts index 53e0cd5f8b16..4b016b05104d 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/models/useRangePicker.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/models/useRangePicker.ts @@ -8,7 +8,6 @@ import { UsePickerViewsNonStaticProps, DateOrTimeViewWithMeridiem, ExportedBaseTabsProps, - PickerRangeValue, } from '@mui/x-date-pickers/internals'; import { ExportedPickersLayoutSlots, @@ -20,16 +19,15 @@ import { RangePickerFieldSlots, RangePickerFieldSlotProps, } from '../useEnrichedRangePickerFieldProps'; -import { RangeFieldSection } from '../../../models'; export interface UseRangePickerSlots - extends ExportedPickersLayoutSlots, + extends ExportedPickersLayoutSlots, RangePickerFieldSlots {} export interface UseRangePickerSlotProps< TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean, -> extends ExportedPickersLayoutSlotProps, +> extends ExportedPickersLayoutSlotProps, RangePickerFieldSlotProps { tabs?: ExportedBaseTabsProps; toolbar?: ExportedBaseToolbarProps; @@ -48,7 +46,7 @@ export interface UseRangePickerProps< TExternalProps extends UsePickerViewsProps, TAdditionalViewProps extends {}, > extends RangeOnlyPickerProps, - BasePickerProps {} + BasePickerProps {} export interface RangePickerAdditionalViewProps extends Pick {} @@ -58,13 +56,7 @@ export interface UseRangePickerParams< TExternalProps extends UseRangePickerProps, TAdditionalViewProps extends {}, > extends Pick< - UsePickerParams< - PickerRangeValue, - TView, - RangeFieldSection, - TExternalProps, - TAdditionalViewProps - >, + UsePickerParams, 'valueManager' | 'valueType' | 'validator' | 'rendererInterceptor' > { props: TExternalProps; 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 a5d29869d304..74006d15f5a9 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 @@ -11,7 +11,6 @@ import { DateOrTimeViewWithMeridiem, ExportedBaseTabsProps, PickersProvider, - PickerRangeValue, } from '@mui/x-date-pickers/internals'; import { FieldRef, InferError, PickerOwnerState } from '@mui/x-date-pickers/models'; import { @@ -25,7 +24,6 @@ import { useEnrichedRangePickerFieldProps, } from '../useEnrichedRangePickerFieldProps'; import { getReleaseInfo } from '../../utils/releaseInfo'; -import { RangeFieldSection } from '../../../models'; import { useRangePosition } from '../useRangePosition'; const releaseInfo = getReleaseInfo(); @@ -70,8 +68,8 @@ export const useDesktopRangePicker = < const fieldContainerRef = React.useRef(null); const anchorRef = React.useRef(null); const popperRef = React.useRef(null); - const startFieldRef = React.useRef>(null); - const endFieldRef = React.useRef>(null); + const startFieldRef = React.useRef>(null); + const endFieldRef = React.useRef>(null); const initialView = React.useRef(props.openTo ?? null); const fieldType = (slots.field as any).fieldType ?? 'multi-input'; @@ -89,13 +87,7 @@ export const useDesktopRangePicker = < shouldRestoreFocus, fieldProps: pickerFieldProps, ownerState, - } = usePicker< - PickerRangeValue, - TView, - RangeFieldSection, - TExternalProps, - DesktopRangePickerAdditionalViewProps - >({ + } = usePicker({ ...pickerParams, props, wrapperVariant: 'desktop', @@ -187,7 +179,7 @@ export const useDesktopRangePicker = < onViewChange: layoutProps.onViewChange, }); - const slotPropsForLayout: PickersLayoutSlotProps = { + const slotPropsForLayout: PickersLayoutSlotProps = { ...slotProps, tabs: { ...slotProps?.tabs, diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts b/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts index efe41c95ec79..010bb3b564b8 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts @@ -24,13 +24,11 @@ import { UsePickerResponse, WrapperVariant, DateOrTimeViewWithMeridiem, - PickerRangeValue, } from '@mui/x-date-pickers/internals'; import { BaseMultiInputFieldProps, MultiInputFieldSlotRootProps, MultiInputFieldSlotTextFieldProps, - RangeFieldSection, RangePosition, FieldType, UseDateRangeFieldProps, @@ -60,12 +58,7 @@ export interface RangePickerFieldSlots extends UseClearableFieldSlots { export interface RangePickerFieldSlotProps extends UseClearableFieldSlotProps { field?: SlotComponentPropsFromProps< - BaseMultiInputFieldProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure, - unknown - >, + BaseMultiInputFieldProps, {}, PickerOwnerState >; @@ -84,20 +77,10 @@ export type RangePickerPropsForFieldSlot< TError, > = | (TIsSingleInput extends true - ? BaseSingleInputFieldProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure, - TError - > + ? BaseSingleInputFieldProps : never) | (TIsSingleInput extends false - ? BaseMultiInputFieldProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure, - TError - > + ? BaseMultiInputFieldProps : never); export interface UseEnrichedRangePickerFieldPropsParams< @@ -105,10 +88,7 @@ export interface UseEnrichedRangePickerFieldPropsParams< TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean, TError, -> extends Pick< - UsePickerResponse, - 'open' | 'actions' - >, +> extends Pick, 'open' | 'actions'>, UseRangePositionResponse { wrapperVariant: WrapperVariant; fieldType: FieldType; @@ -129,8 +109,8 @@ export interface UseEnrichedRangePickerFieldPropsParams< currentView?: TView | null; initialView?: TView; onViewChange?: (view: TView) => void; - startFieldRef: React.RefObject>; - endFieldRef: React.RefObject>; + startFieldRef: React.RefObject>; + endFieldRef: React.RefObject>; } const useMultiInputFieldSlotProps = < @@ -163,12 +143,7 @@ const useMultiInputFieldSlotProps = < TEnableAccessibleFieldDOMStructure, TError >) => { - type ReturnType = BaseMultiInputFieldProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure, - TError - >; + type ReturnType = BaseMultiInputFieldProps; const translations = usePickersTranslations(); const handleStartFieldRef = useForkRef(fieldProps.unstableStartFieldRef, startFieldRef); @@ -339,12 +314,7 @@ const useSingleInputFieldSlotProps = < TEnableAccessibleFieldDOMStructure, TError >) => { - type ReturnType = BaseSingleInputFieldProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure, - TError - >; + type ReturnType = BaseSingleInputFieldProps; const handleFieldRef = useForkRef(fieldProps.unstableFieldRef, startFieldRef, endFieldRef); 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 aa9ab1b34b53..98a14b34a6e5 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 @@ -9,7 +9,6 @@ import { DateOrTimeViewWithMeridiem, ExportedBaseTabsProps, PickersProvider, - PickerRangeValue, } from '@mui/x-date-pickers/internals'; import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; import { FieldRef, InferError, PickerOwnerState } from '@mui/x-date-pickers/models'; @@ -25,7 +24,6 @@ import { useEnrichedRangePickerFieldProps, } from '../useEnrichedRangePickerFieldProps'; import { getReleaseInfo } from '../../utils/releaseInfo'; -import { RangeFieldSection } from '../../../models'; import { useRangePosition } from '../useRangePosition'; const releaseInfo = getReleaseInfo(); @@ -65,8 +63,8 @@ export const useMobileRangePicker = < localeText, } = props; - const startFieldRef = React.useRef>(null); - const endFieldRef = React.useRef>(null); + const startFieldRef = React.useRef>(null); + const endFieldRef = React.useRef>(null); const fieldType = (slots.field as any).fieldType ?? 'multi-input'; const { rangePosition, onRangePositionChange } = useRangePosition( @@ -84,13 +82,7 @@ export const useMobileRangePicker = < renderCurrentView, fieldProps: pickerFieldProps, ownerState, - } = usePicker< - PickerRangeValue, - TView, - RangeFieldSection, - TExternalProps, - MobileRangePickerAdditionalViewProps - >({ + } = usePicker({ ...pickerParams, props, wrapperVariant: 'mobile', @@ -159,7 +151,7 @@ export const useMobileRangePicker = < endFieldRef, }); - const slotPropsForLayout: PickersLayoutSlotProps = { + const slotPropsForLayout: PickersLayoutSlotProps = { ...innerSlotProps, tabs: { ...innerSlotProps?.tabs, diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputFieldSelectedSections.ts b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputFieldSelectedSections.ts index 68e10d651b1a..5fcb8ec37ccd 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputFieldSelectedSections.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputFieldSelectedSections.ts @@ -3,21 +3,20 @@ import useForkRef from '@mui/utils/useForkRef'; import useEventCallback from '@mui/utils/useEventCallback'; import { UseFieldInternalProps } from '@mui/x-date-pickers/internals'; import { FieldRef, FieldSelectedSections } from '@mui/x-date-pickers/models'; -import { RangeFieldSection } from '../../models'; interface UseMultiInputFieldSelectedSectionsParams extends Pick< - UseFieldInternalProps, + UseFieldInternalProps, 'selectedSections' | 'onSelectedSectionsChange' > { - unstableStartFieldRef?: React.Ref>; - unstableEndFieldRef?: React.Ref>; + unstableStartFieldRef?: React.Ref>; + unstableEndFieldRef?: React.Ref>; } export const useMultiInputFieldSelectedSections = ( params: UseMultiInputFieldSelectedSectionsParams, ) => { - const unstableEndFieldRef = React.useRef>(null); + const unstableEndFieldRef = React.useRef>(null); const handleUnstableEndFieldRef = useForkRef(params.unstableEndFieldRef, unstableEndFieldRef); const [startSelectedSection, setStartSelectedSection] = React.useState( 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 5aecc79b1600..e6cc51bc4378 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 @@ -9,11 +9,8 @@ import { 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 { DateValidationError } from '@mui/x-date-pickers/models'; +import { UseMultiInputDateRangeFieldParams } from '../../../MultiInputDateRangeField/MultiInputDateRangeField.types'; import { validateDateRange } from '../../../validation'; import { rangeValueManager } from '../../utils/valueManagers'; import type { UseMultiInputRangeFieldResponse } from './useMultiInputRangeField.types'; @@ -34,10 +31,7 @@ export const useMultiInputDateRangeField = < TEnableAccessibleFieldDOMStructure, TTextFieldSlotProps >): UseMultiInputRangeFieldResponse => { - const sharedProps = useDefaultizedDateField< - UseMultiInputDateRangeFieldProps, - typeof inSharedProps - >(inSharedProps); + const sharedProps = useDefaultizedDateField(inSharedProps); const { value: valueProp, @@ -73,9 +67,7 @@ export const useMultiInputDateRangeField = < }); // TODO: Maybe export utility from `useField` instead of copy/pasting the logic - const buildChangeHandler = ( - index: 0 | 1, - ): FieldChangeHandler => { + const buildChangeHandler = (index: 0 | 1): FieldChangeHandler => { return (newDate, rawContext) => { const newDateRange: PickerRangeValue = index === 0 ? [newDate, value[1]] : [value[0], newDate]; diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useRangePosition.ts b/packages/x-date-pickers-pro/src/internals/hooks/useRangePosition.ts index c5029471e4e8..898bf1253a07 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useRangePosition.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useRangePosition.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import useControlled from '@mui/utils/useControlled'; import useEventCallback from '@mui/utils/useEventCallback'; import { FieldRef } from '@mui/x-date-pickers/models'; -import { RangePosition, RangeFieldSection } from '../../models'; +import { RangePosition } from '../../models'; export interface UseRangePositionProps { /** @@ -30,7 +30,7 @@ export interface UseRangePositionResponse { export const useRangePosition = ( props: UseRangePositionProps, - singleInputFieldRef?: React.RefObject>, + singleInputFieldRef?: React.RefObject>, ): UseRangePositionResponse => { const [rangePosition, setRangePosition] = useControlled({ name: 'useRangePosition', diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useStaticRangePicker/useStaticRangePicker.tsx b/packages/x-date-pickers-pro/src/internals/hooks/useStaticRangePicker/useStaticRangePicker.tsx index 7fdd442279fc..7355e9f4c17b 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useStaticRangePicker/useStaticRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/internals/hooks/useStaticRangePicker/useStaticRangePicker.tsx @@ -8,13 +8,11 @@ import { ExportedBaseToolbarProps, DateOrTimeViewWithMeridiem, PickersProvider, - PickerRangeValue, } from '@mui/x-date-pickers/internals'; import { UseStaticRangePickerParams, UseStaticRangePickerProps, } from './useStaticRangePicker.types'; -import { RangeFieldSection } from '../../../models'; import { useRangePosition } from '../useRangePosition'; const PickerStaticLayout = styled(PickersLayout)(({ theme }) => ({ @@ -40,9 +38,8 @@ export const useStaticRangePicker = < const { rangePosition, onRangePositionChange } = useRangePosition(props); const { layoutProps, providerProps, renderCurrentView } = usePicker< - PickerRangeValue, + true, TView, - RangeFieldSection, TExternalProps, {} >({ @@ -59,7 +56,7 @@ export const useStaticRangePicker = < }); const Layout = slots?.layout ?? PickerStaticLayout; - const slotPropsForLayout: PickersLayoutSlotProps = { + const slotPropsForLayout: PickersLayoutSlotProps = { ...slotProps, toolbar: { ...slotProps?.toolbar, diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useStaticRangePicker/useStaticRangePicker.types.ts b/packages/x-date-pickers-pro/src/internals/hooks/useStaticRangePicker/useStaticRangePicker.types.ts index ebe5fcbf95d1..75fe7c3b9075 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useStaticRangePicker/useStaticRangePicker.types.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useStaticRangePicker/useStaticRangePicker.types.ts @@ -5,20 +5,18 @@ import { ExportedBaseToolbarProps, StaticOnlyPickerProps, DateOrTimeViewWithMeridiem, - PickerRangeValue, } from '@mui/x-date-pickers/internals'; import { ExportedPickersLayoutSlots, ExportedPickersLayoutSlotProps, } from '@mui/x-date-pickers/PickersLayout'; -import { RangeFieldSection } from '../../../models'; import { UseRangePositionProps } from '../useRangePosition'; export interface UseStaticRangePickerSlots - extends ExportedPickersLayoutSlots {} + extends ExportedPickersLayoutSlots {} export interface UseStaticRangePickerSlotProps - extends ExportedPickersLayoutSlotProps { + extends ExportedPickersLayoutSlotProps { toolbar?: ExportedBaseToolbarProps; } @@ -28,7 +26,7 @@ export interface UseStaticRangePickerProps< TView extends DateOrTimeViewWithMeridiem, TError, TExternalProps extends UseStaticRangePickerProps, -> extends BasePickerProps, +> extends BasePickerProps, StaticRangeOnlyPickerProps { /** * Overridable components. @@ -46,7 +44,7 @@ export interface UseStaticRangePickerParams< TView extends DateOrTimeViewWithMeridiem, TExternalProps extends UseStaticRangePickerProps, > extends Pick< - UsePickerParams, + UsePickerParams, 'valueManager' | 'valueType' | 'validator' > { props: TExternalProps; diff --git a/packages/x-date-pickers-pro/src/internals/models/dateTimeRange.ts b/packages/x-date-pickers-pro/src/internals/models/dateTimeRange.ts index efcd335df353..26f59a768b5d 100644 --- a/packages/x-date-pickers-pro/src/internals/models/dateTimeRange.ts +++ b/packages/x-date-pickers-pro/src/internals/models/dateTimeRange.ts @@ -3,21 +3,15 @@ import { UseFieldInternalProps, DateOrTimeViewWithMeridiem, AmPmProps, - PickerRangeValue, } from '@mui/x-date-pickers/internals'; -import { - DateTimeRangeValidationError, - RangeFieldSection, - RangeFieldSeparatorProps, -} from '../../models'; +import { DateTimeRangeValidationError, RangeFieldSeparatorProps } from '../../models'; import { ExportedValidateDateTimeRangeProps } from '../../validation/validateDateTimeRange'; export interface UseDateTimeRangeFieldProps extends MakeOptional< Omit< UseFieldInternalProps< - PickerRangeValue, - RangeFieldSection, + true, TEnableAccessibleFieldDOMStructure, DateTimeRangeValidationError >, diff --git a/packages/x-date-pickers-pro/src/internals/models/timeRange.ts b/packages/x-date-pickers-pro/src/internals/models/timeRange.ts index 129069c9df56..6bd2c88f6769 100644 --- a/packages/x-date-pickers-pro/src/internals/models/timeRange.ts +++ b/packages/x-date-pickers-pro/src/internals/models/timeRange.ts @@ -1,21 +1,12 @@ import { MakeOptional } from '@mui/x-internals/types'; -import { UseFieldInternalProps, AmPmProps, PickerRangeValue } from '@mui/x-date-pickers/internals'; -import { - TimeRangeValidationError, - RangeFieldSection, - RangeFieldSeparatorProps, -} from '../../models'; +import { UseFieldInternalProps, AmPmProps } from '@mui/x-date-pickers/internals'; +import { TimeRangeValidationError, RangeFieldSeparatorProps } from '../../models'; import type { ExportedValidateTimeRangeProps } from '../../validation/validateTimeRange'; export interface UseTimeRangeFieldProps extends MakeOptional< Omit< - UseFieldInternalProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure, - TimeRangeValidationError - >, + UseFieldInternalProps, 'unstableFieldRef' >, 'format' diff --git a/packages/x-date-pickers-pro/src/internals/utils/date-fields-utils.ts b/packages/x-date-pickers-pro/src/internals/utils/date-fields-utils.ts index 9210c310244d..76d3d080eb78 100644 --- a/packages/x-date-pickers-pro/src/internals/utils/date-fields-utils.ts +++ b/packages/x-date-pickers-pro/src/internals/utils/date-fields-utils.ts @@ -1,8 +1,8 @@ -import { RangeFieldSection } from '../../models'; +import { FieldRangeSection } from '@mui/x-date-pickers/models'; -export const splitDateRangeSections = (sections: RangeFieldSection[]) => { - const startDateSections: RangeFieldSection[] = []; - const endDateSections: RangeFieldSection[] = []; +export const splitDateRangeSections = (sections: FieldRangeSection[]) => { + const startDateSections: FieldRangeSection[] = []; + const endDateSections: FieldRangeSection[] = []; sections.forEach((section) => { if (section.dateName === 'start') { startDateSections.push(section); @@ -14,7 +14,7 @@ export const splitDateRangeSections = (sections: RangeFieldSection[]) => { return { startDate: startDateSections, endDate: endDateSections }; }; -export const removeLastSeparator = (dateSections: RangeFieldSection[]) => +export const removeLastSeparator = (dateSections: FieldRangeSection[]) => dateSections.map((section, sectionIndex) => { if (sectionIndex === dateSections.length - 1) { return { ...section, separator: null }; diff --git a/packages/x-date-pickers-pro/src/internals/utils/valueManagers.ts b/packages/x-date-pickers-pro/src/internals/utils/valueManagers.ts index f3f8200c6795..e438da2e0ba4 100644 --- a/packages/x-date-pickers-pro/src/internals/utils/valueManagers.ts +++ b/packages/x-date-pickers-pro/src/internals/utils/valueManagers.ts @@ -8,24 +8,23 @@ import { getTodayDate, getDefaultReferenceDate, PickerRangeValue, + PickerNonNullableRangeValue, } from '@mui/x-date-pickers/internals'; -import { PickerValidDate } from '@mui/x-date-pickers/models'; +import { FieldRangeSection, PickerValidDate } from '@mui/x-date-pickers/models'; import { splitDateRangeSections, removeLastSeparator } from './date-fields-utils'; import type { DateRangeValidationError, DateTimeRangeValidationError, TimeRangeValidationError, - RangeFieldSection, RangePosition, } from '../../models'; -export type RangePickerValueManager< - TValue = [any, any], +type RangePickerValueManager< TError extends | DateRangeValidationError | TimeRangeValidationError | DateTimeRangeValidationError = any, -> = PickerValueManager; +> = PickerValueManager; export const rangeValueManager: RangePickerValueManager = { emptyValue: [null, null], @@ -38,14 +37,14 @@ export const rangeValueManager: RangePickerValueManager = { const shouldKeepEndDate = value[1] != null && params.utils.isValid(value[1]); if (shouldKeepStartDate && shouldKeepEndDate) { - return value; + return value as PickerNonNullableRangeValue; } const referenceDate = referenceDateProp ?? getDefaultReferenceDate(params); return [ - shouldKeepStartDate ? value[0] : referenceDate, - shouldKeepEndDate ? value[1] : referenceDate, + shouldKeepStartDate ? value[0]! : referenceDate, + shouldKeepEndDate ? value[1]! : referenceDate, ]; }, cleanValue: (utils, value) => @@ -77,7 +76,7 @@ export const getRangeFieldValueManager = ({ dateSeparator = '–', }: { dateSeparator: string | undefined; -}): FieldValueManager => ({ +}): FieldValueManager => ({ updateReferenceValue: (utils, value, prevReferenceValue) => { const shouldKeepStartDate = value[0] != null && utils.isValid(value[0]); const shouldKeepEndDate = value[1] != null && utils.isValid(value[1]); @@ -87,14 +86,14 @@ export const getRangeFieldValueManager = ({ } if (shouldKeepStartDate && shouldKeepEndDate) { - return value; + return value as PickerNonNullableRangeValue; } if (shouldKeepStartDate) { - return [value[0], prevReferenceValue[0]]; + return [value[0]!, prevReferenceValue[0]!]; } - return [prevReferenceValue[1], value[1]]; + return [prevReferenceValue[1]!, value[1]!]; }, getSectionsFromValue: (utils, [start, end], fallbackSections, getSectionsFromDate) => { const separatedFallbackSections = @@ -104,7 +103,7 @@ export const getRangeFieldValueManager = ({ const getSections = ( newDate: PickerValidDate | null, - fallbackDateSections: RangeFieldSection[] | null, + fallbackDateSections: FieldRangeSection[] | null, position: RangePosition, ) => { const shouldReUsePrevDateSections = !utils.isValid(newDate) && !!fallbackDateSections; @@ -167,7 +166,9 @@ export const getRangeFieldValueManager = ({ const index = activeSection.dateName === 'start' ? 0 : 1; const updateDateInRange = (newDate: PickerValidDate | null, prevDateRange: PickerRangeValue) => - (index === 0 ? [newDate, prevDateRange[1]] : [prevDateRange[0], newDate]) as PickerRangeValue; + (index === 0 + ? [newDate, prevDateRange[1]] + : [prevDateRange[0], newDate]) as PickerNonNullableRangeValue; return { date: state.value[index], diff --git a/packages/x-date-pickers-pro/src/models/dateRange.ts b/packages/x-date-pickers-pro/src/models/dateRange.ts index 88511e4c0e6a..0d9c9e8e349f 100644 --- a/packages/x-date-pickers-pro/src/models/dateRange.ts +++ b/packages/x-date-pickers-pro/src/models/dateRange.ts @@ -1,18 +1,13 @@ import { MakeOptional } from '@mui/x-internals/types'; -import { UseFieldInternalProps, PickerRangeValue } from '@mui/x-date-pickers/internals'; -import { RangeFieldSection, RangeFieldSeparatorProps } from './fields'; +import { UseFieldInternalProps } from '@mui/x-date-pickers/internals'; +import { RangeFieldSeparatorProps } from './fields'; import { DateRangeValidationError } from './validation'; import type { ExportedValidateDateRangeProps } from '../validation/validateDateRange'; export interface UseDateRangeFieldProps extends MakeOptional< Omit< - UseFieldInternalProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure, - DateRangeValidationError - >, + UseFieldInternalProps, 'unstableFieldRef' >, 'format' diff --git a/packages/x-date-pickers-pro/src/models/fields.ts b/packages/x-date-pickers-pro/src/models/fields.ts index 12060a16d003..1f509627decd 100644 --- a/packages/x-date-pickers-pro/src/models/fields.ts +++ b/packages/x-date-pickers-pro/src/models/fields.ts @@ -1,19 +1,10 @@ import * as React from 'react'; import { SlotComponentProps } from '@mui/utils'; -import { BaseFieldProps, UseFieldResponse } from '@mui/x-date-pickers/internals'; -import { - BaseSingleInputPickersTextFieldProps, - FieldRef, - FieldSection, -} from '@mui/x-date-pickers/models'; +import { BaseFieldProps, RangePosition, UseFieldResponse } from '@mui/x-date-pickers/internals'; +import { BaseSingleInputPickersTextFieldProps, FieldRef } from '@mui/x-date-pickers/models'; import { UseClearableFieldResponse } from '@mui/x-date-pickers/hooks'; import { SxProps } from '@mui/material/styles'; import TextField from '@mui/material/TextField'; -import { RangePosition } from './range'; - -export interface RangeFieldSection extends FieldSection { - dateName: RangePosition; -} export type FieldType = 'single-input' | 'multi-input'; @@ -44,8 +35,8 @@ export interface MultiInputFieldSlotRootProps { } export interface MultiInputFieldRefs { - unstableStartFieldRef?: React.Ref>; - unstableEndFieldRef?: React.Ref>; + unstableStartFieldRef?: React.Ref>; + unstableEndFieldRef?: React.Ref>; } export interface RangeFieldSeparatorProps { @@ -62,18 +53,16 @@ export interface RangeFieldSeparatorProps { * not what users can pass using the `props.slotProps.field`. */ export interface BaseMultiInputFieldProps< - TValue, - TSection extends FieldSection, TEnableAccessibleFieldDOMStructure extends boolean, TError, > extends Omit< - BaseFieldProps, + BaseFieldProps, 'unstableFieldRef' >, RangeFieldSeparatorProps { sx?: SxProps; - unstableStartFieldRef?: React.Ref>; - unstableEndFieldRef?: React.Ref>; + unstableStartFieldRef?: React.Ref>; + unstableEndFieldRef?: React.Ref>; slots?: { root?: React.ElementType; separator?: React.ElementType; diff --git a/packages/x-date-pickers-pro/src/models/index.ts b/packages/x-date-pickers-pro/src/models/index.ts index f97efb2767d1..f3b7d852521c 100644 --- a/packages/x-date-pickers-pro/src/models/index.ts +++ b/packages/x-date-pickers-pro/src/models/index.ts @@ -3,3 +3,5 @@ export * from './fields'; export * from './range'; export * from './validation'; export * from './multiInputRangeFieldClasses'; + +export type { RangePosition } from '@mui/x-date-pickers/internals'; diff --git a/packages/x-date-pickers-pro/src/models/range.ts b/packages/x-date-pickers-pro/src/models/range.ts index d0a4b4de2b1d..1dc74741d76b 100644 --- a/packages/x-date-pickers-pro/src/models/range.ts +++ b/packages/x-date-pickers-pro/src/models/range.ts @@ -5,5 +5,3 @@ export type DateRange = [TDate | null, TDate | nu // TODO v8: Remove export type NonEmptyDateRange = [PickerValidDate, PickerValidDate]; - -export type RangePosition = 'start' | 'end'; diff --git a/packages/x-date-pickers-pro/src/validation/validateDateRange.ts b/packages/x-date-pickers-pro/src/validation/validateDateRange.ts index 44effa217b60..02d776903e09 100644 --- a/packages/x-date-pickers-pro/src/validation/validateDateRange.ts +++ b/packages/x-date-pickers-pro/src/validation/validateDateRange.ts @@ -1,5 +1,5 @@ import { validateDate, Validator } from '@mui/x-date-pickers/validation'; -import { BaseDateValidationProps, PickerRangeValue } from '@mui/x-date-pickers/internals'; +import { BaseDateValidationProps } from '@mui/x-date-pickers/internals'; import { isRangeValid } from '../internals/utils/date-utils'; import { DayRangeValidationProps } from '../internals/models/dateRange'; import { DateRangeValidationError } from '../models'; @@ -17,7 +17,7 @@ export interface ValidateDateRangeProps Required {} export const validateDateRange: Validator< - PickerRangeValue, + true, DateRangeValidationError, ValidateDateRangeProps > = ({ adapter, value, timezone, props }) => { diff --git a/packages/x-date-pickers-pro/src/validation/validateDateTimeRange.ts b/packages/x-date-pickers-pro/src/validation/validateDateTimeRange.ts index 743360be7d7d..25543de73599 100644 --- a/packages/x-date-pickers-pro/src/validation/validateDateTimeRange.ts +++ b/packages/x-date-pickers-pro/src/validation/validateDateTimeRange.ts @@ -1,4 +1,4 @@ -import { DateTimeValidationProps, PickerRangeValue } from '@mui/x-date-pickers/internals'; +import { DateTimeValidationProps } from '@mui/x-date-pickers/internals'; import { validateDateTime, Validator } from '@mui/x-date-pickers/validation'; import { isRangeValid } from '../internals/utils/date-utils'; import { DateTimeRangeValidationError } from '../models'; @@ -19,7 +19,7 @@ export interface ValidateDateTimeRangeProps ValidateTimeRangeProps {} export const validateDateTimeRange: Validator< - PickerRangeValue, + true, DateTimeRangeValidationError, ValidateDateTimeRangeProps > = ({ adapter, value, timezone, props }) => { diff --git a/packages/x-date-pickers-pro/src/validation/validateTimeRange.ts b/packages/x-date-pickers-pro/src/validation/validateTimeRange.ts index 2f5cd591cd86..5ced51e9309a 100644 --- a/packages/x-date-pickers-pro/src/validation/validateTimeRange.ts +++ b/packages/x-date-pickers-pro/src/validation/validateTimeRange.ts @@ -1,9 +1,5 @@ import { validateTime, Validator } from '@mui/x-date-pickers/validation'; -import { - TimeValidationProps, - BaseTimeValidationProps, - PickerRangeValue, -} from '@mui/x-date-pickers/internals'; +import { TimeValidationProps, BaseTimeValidationProps } from '@mui/x-date-pickers/internals'; import { isRangeValid } from '../internals/utils/date-utils'; import { TimeRangeValidationError } from '../models'; import { rangeValueManager } from '../internals/utils/valueManagers'; @@ -20,7 +16,7 @@ export interface ValidateTimeRangeProps TimeValidationProps {} export const validateTimeRange: Validator< - PickerRangeValue, + true, TimeRangeValidationError, ValidateTimeRangeProps > = ({ adapter, value, timezone, props }) => { diff --git a/packages/x-date-pickers/src/DateCalendar/DateCalendar.tsx b/packages/x-date-pickers/src/DateCalendar/DateCalendar.tsx index f5bd789a6862..5f9560951061 100644 --- a/packages/x-date-pickers/src/DateCalendar/DateCalendar.tsx +++ b/packages/x-date-pickers/src/DateCalendar/DateCalendar.tsx @@ -30,7 +30,7 @@ import { BaseDateValidationProps } from '../internals/models/validation'; import { useControlledValueWithTimezone } from '../internals/hooks/useValueWithTimezone'; import { singleItemValueManager } from '../internals/utils/valueManagers'; import { VIEW_HEIGHT } from '../internals/constants/dimensions'; -import { PickerValidDate } from '../models'; +import { DateView, PickerValidDate } from '../models'; const useUtilityClasses = (ownerState: DateCalendarProps) => { const { classes } = ownerState; @@ -159,7 +159,7 @@ export const DateCalendar = React.forwardRef(function DateCalendar( }); const { view, setView, focusedView, setFocusedView, goToNextView, setValueAndGoToNextView } = - useViews({ + useViews({ view: inView, views, openTo, diff --git a/packages/x-date-pickers/src/DateCalendar/DateCalendar.types.ts b/packages/x-date-pickers/src/DateCalendar/DateCalendar.types.ts index 09e7c7d3067b..ee907b34364a 100644 --- a/packages/x-date-pickers/src/DateCalendar/DateCalendar.types.ts +++ b/packages/x-date-pickers/src/DateCalendar/DateCalendar.types.ts @@ -88,7 +88,7 @@ export interface ExportedDateCalendarProps export interface DateCalendarProps extends ExportedDateCalendarProps, - ExportedUseViewsOptions { + ExportedUseViewsOptions { /** * The selected value. * Used when the component is controlled. diff --git a/packages/x-date-pickers/src/DateField/DateField.types.ts b/packages/x-date-pickers/src/DateField/DateField.types.ts index 3a7c21470f5b..21dd20cd0e5f 100644 --- a/packages/x-date-pickers/src/DateField/DateField.types.ts +++ b/packages/x-date-pickers/src/DateField/DateField.types.ts @@ -7,23 +7,13 @@ import { UseClearableFieldSlots, UseClearableFieldSlotProps, } from '../hooks/useClearableField'; -import { - DateValidationError, - FieldSection, - PickerValidDate, - BuiltInFieldTextFieldProps, -} from '../models'; +import { DateValidationError, BuiltInFieldTextFieldProps } from '../models'; import { UseFieldInternalProps } from '../internals/hooks/useField'; import { ExportedValidateDateProps } from '../validation/validateDate'; export interface UseDateFieldProps extends MakeOptional< - UseFieldInternalProps< - PickerValidDate | null, - FieldSection, - TEnableAccessibleFieldDOMStructure, - DateValidationError - >, + UseFieldInternalProps, 'format' >, ExportedValidateDateProps, diff --git a/packages/x-date-pickers/src/DateField/useDateField.ts b/packages/x-date-pickers/src/DateField/useDateField.ts index c5f7e8da6210..358c87124e48 100644 --- a/packages/x-date-pickers/src/DateField/useDateField.ts +++ b/packages/x-date-pickers/src/DateField/useDateField.ts @@ -7,7 +7,6 @@ import { useField } from '../internals/hooks/useField'; import { UseDateFieldProps } from './DateField.types'; import { validateDate } from '../validation'; import { useSplitFieldProps } from '../hooks'; -import { FieldSection, PickerValidDate } from '../models'; import { useDefaultizedDateField } from '../internals/hooks/defaultizedFieldProps'; export const useDateField = < @@ -24,8 +23,7 @@ export const useDateField = < const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date'); return useField< - PickerValidDate | null, - FieldSection, + false, TEnableAccessibleFieldDOMStructure, typeof forwardedProps, typeof internalProps diff --git a/packages/x-date-pickers/src/DatePicker/DatePicker.types.ts b/packages/x-date-pickers/src/DatePicker/DatePicker.types.ts index 3b80ff310dad..220ddbb47b3c 100644 --- a/packages/x-date-pickers/src/DatePicker/DatePicker.types.ts +++ b/packages/x-date-pickers/src/DatePicker/DatePicker.types.ts @@ -11,12 +11,7 @@ import { MobileDatePickerSlots, MobileDatePickerSlotProps, } from '../MobileDatePicker'; -import { - BaseSingleInputFieldProps, - DateValidationError, - FieldSection, - PickerValidDate, -} from '../models'; +import { BaseSingleInputFieldProps, DateValidationError } from '../models'; export interface DatePickerSlots extends DesktopDatePickerSlots, MobileDatePickerSlots {} @@ -58,4 +53,4 @@ export type DatePickerFieldProps, 'format' | 'timezone' | 'value' | keyof BaseDateValidationProps > & - BaseSingleInputFieldProps; + BaseSingleInputFieldProps; diff --git a/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx b/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx index 518a67af8914..4087992b2ccb 100644 --- a/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx +++ b/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx @@ -9,7 +9,7 @@ import { PickersToolbar } from '../internals/components/PickersToolbar'; import { usePickersTranslations } from '../hooks/usePickersTranslations'; import { useUtils } from '../internals/hooks/useUtils'; import { BaseToolbarProps, ExportedBaseToolbarProps } from '../internals/models/props/toolbar'; -import { DateView, PickerValidDate } from '../models'; +import { DateView } from '../models'; import { DatePickerToolbarClasses, getDatePickerToolbarUtilityClass, @@ -17,7 +17,7 @@ import { import { resolveDateFormat } from '../internals/utils/date-utils'; export interface DatePickerToolbarProps - extends BaseToolbarProps, + extends BaseToolbarProps, ExportedDatePickerToolbarProps {} export interface ExportedDatePickerToolbarProps extends ExportedBaseToolbarProps { diff --git a/packages/x-date-pickers/src/DatePicker/shared.tsx b/packages/x-date-pickers/src/DatePicker/shared.tsx index 05573e1cc9e2..063b8dc28698 100644 --- a/packages/x-date-pickers/src/DatePicker/shared.tsx +++ b/packages/x-date-pickers/src/DatePicker/shared.tsx @@ -36,15 +36,10 @@ export interface BaseDatePickerSlotProps extends DateCalendarSlotProps { export type DatePickerViewRenderers< TView extends DateView, TAdditionalProps extends {} = {}, -> = PickerViewRendererLookup< - PickerValidDate | null, - TView, - DateViewRendererProps, - TAdditionalProps ->; +> = PickerViewRendererLookup, TAdditionalProps>; export interface BaseDatePickerProps - extends BasePickerInputProps, + extends BasePickerInputProps, ExportedDateCalendarProps { /** * Overridable component slots. diff --git a/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts b/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts index b306ed6dbd2b..8a5ecfac9f6f 100644 --- a/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts +++ b/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts @@ -2,12 +2,7 @@ import * as React from 'react'; import { SlotComponentProps } from '@mui/utils'; import { MakeOptional } from '@mui/x-internals/types'; import TextField from '@mui/material/TextField'; -import { - DateTimeValidationError, - FieldSection, - PickerValidDate, - BuiltInFieldTextFieldProps, -} from '../models'; +import { DateTimeValidationError, BuiltInFieldTextFieldProps } from '../models'; import { UseFieldInternalProps } from '../internals/hooks/useField'; import { ExportedUseClearableFieldProps, @@ -19,12 +14,7 @@ import { AmPmProps } from '../internals/models/props/time'; export interface UseDateTimeFieldProps extends MakeOptional< - UseFieldInternalProps< - PickerValidDate | null, - FieldSection, - TEnableAccessibleFieldDOMStructure, - DateTimeValidationError - >, + UseFieldInternalProps, 'format' >, ExportedValidateDateTimeProps, diff --git a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts index 33e215fd4c7d..d95b01f4b62d 100644 --- a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts +++ b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts @@ -7,7 +7,6 @@ import { useField } from '../internals/hooks/useField'; import { UseDateTimeFieldProps } from './DateTimeField.types'; import { validateDateTime } from '../validation'; import { useSplitFieldProps } from '../hooks'; -import { FieldSection, PickerValidDate } from '../models'; import { useDefaultizedDateTimeField } from '../internals/hooks/defaultizedFieldProps'; export const useDateTimeField = < @@ -24,8 +23,7 @@ export const useDateTimeField = < const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date-time'); return useField< - PickerValidDate | null, - FieldSection, + false, TEnableAccessibleFieldDOMStructure, typeof forwardedProps, typeof internalProps diff --git a/packages/x-date-pickers/src/DateTimePicker/DateTimePicker.types.ts b/packages/x-date-pickers/src/DateTimePicker/DateTimePicker.types.ts index fd81624ee3bd..add9afcc6927 100644 --- a/packages/x-date-pickers/src/DateTimePicker/DateTimePicker.types.ts +++ b/packages/x-date-pickers/src/DateTimePicker/DateTimePicker.types.ts @@ -12,12 +12,7 @@ import { MobileDateTimePickerSlots, MobileDateTimePickerSlotProps, } from '../MobileDateTimePicker'; -import { - BaseSingleInputFieldProps, - DateTimeValidationError, - FieldSection, - PickerValidDate, -} from '../models'; +import { BaseSingleInputFieldProps, DateTimeValidationError } from '../models'; import { ExportedYearCalendarProps } from '../YearCalendar/YearCalendar.types'; export interface DateTimePickerSlots @@ -72,4 +67,4 @@ export type DateTimePickerFieldProps & - BaseSingleInputFieldProps; + BaseSingleInputFieldProps; diff --git a/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx b/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx index 760e09626006..db7bf768a208 100644 --- a/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx +++ b/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx @@ -34,7 +34,7 @@ export interface ExportedDateTimePickerToolbarProps extends ExportedBaseToolbarP export interface DateTimePickerToolbarProps extends ExportedDateTimePickerToolbarProps, - MakeOptional, 'view'> { + MakeOptional, 'view'> { toolbarVariant?: WrapperVariant; /** * If provided, it will be used instead of `dateTimePickerToolbarTitle` from localization. diff --git a/packages/x-date-pickers/src/DateTimePicker/shared.tsx b/packages/x-date-pickers/src/DateTimePicker/shared.tsx index 10bb9510bcba..02328b6e28e3 100644 --- a/packages/x-date-pickers/src/DateTimePicker/shared.tsx +++ b/packages/x-date-pickers/src/DateTimePicker/shared.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { useThemeProps } from '@mui/material/styles'; import { DefaultizedProps } from '@mui/x-internals/types'; -import { DateTimeValidationError, PickerValidDate } from '../models'; +import { DateTimeValidationError } from '../models'; import { useDefaultDates, useUtils } from '../internals/hooks/useUtils'; import { DateCalendarSlots, @@ -62,7 +62,7 @@ export type DateTimePickerViewRenderers< TView extends DateOrTimeViewWithMeridiem, TAdditionalProps extends {} = {}, > = PickerViewRendererLookup< - PickerValidDate | null, + false, TView, Omit, 'slots' | 'slotProps'> & Omit< @@ -73,7 +73,7 @@ export type DateTimePickerViewRenderers< >; export interface BaseDateTimePickerProps - extends BasePickerInputProps, + extends BasePickerInputProps, Omit, ExportedBaseClockProps, DateTimeValidationProps { diff --git a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx index 9368acefdfc7..fdd31ce64914 100644 --- a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx +++ b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx @@ -12,17 +12,20 @@ import { } from '../PickersLayout'; import { DateOrTimeViewWithMeridiem } from '../internals/models/common'; -type DesktopDateTimePickerLayoutComponent = (( - props: PickersLayoutProps & React.RefAttributes, +type DesktopDateTimePickerLayoutComponent = (< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +>( + props: PickersLayoutProps & React.RefAttributes, ) => React.JSX.Element) & { propTypes?: any }; /** * @ignore - internal component. */ const DesktopDateTimePickerLayout = React.forwardRef(function DesktopDateTimePickerLayout< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, ->(props: PickersLayoutProps, ref: React.Ref) { +>(props: PickersLayoutProps, ref: React.Ref) { const isRtl = useRtl(); const { toolbar, tabs, content, actionBar, shortcuts } = usePickerLayout(props); const { sx, className, isLandscape, classes } = props; diff --git a/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx b/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx index 5648dbcc8d88..16294499200f 100644 --- a/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx +++ b/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx @@ -153,10 +153,7 @@ export const MultiSectionDigitalClock = React.forwardRef(function MultiSectionDi return inViews.includes('meridiem') ? inViews : [...inViews, 'meridiem']; }, [ampm, inViews]); - const { view, setValueAndGoToNextView, focusedView } = useViews< - PickerValidDate | null, - TimeViewWithMeridiem - >({ + const { view, setValueAndGoToNextView, focusedView } = useViews({ view: inView, views, openTo, diff --git a/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.types.ts b/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.types.ts index ae4b27536239..d5d7dece5344 100644 --- a/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.types.ts +++ b/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.types.ts @@ -10,12 +10,12 @@ import { import { MultiSectionDigitalClockSectionProps } from './MultiSectionDigitalClockSection'; import { TimeViewWithMeridiem } from '../internals/models'; -export interface MultiSectionDigitalClockOption { - isDisabled?: (value: TValue) => boolean; - isSelected: (value: TValue) => boolean; - isFocused: (value: TValue) => boolean; +export interface MultiSectionDigitalClockOption { + isDisabled?: (value: TSectionValue) => boolean; + isSelected: (value: TSectionValue) => boolean; + isFocused: (value: TSectionValue) => boolean; label: string; - value: TValue; + value: TSectionValue; ariaLabel: string; } @@ -23,8 +23,8 @@ export interface ExportedMultiSectionDigitalClockProps extends ExportedBaseClockProps, MultiSectionDigitalClockOnlyProps {} -export interface MultiSectionDigitalClockViewProps - extends Pick, 'onChange' | 'items'> {} +export interface MultiSectionDigitalClockViewProps + extends Pick, 'onChange' | 'items'> {} export interface MultiSectionDigitalClockSlots { /** diff --git a/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClockSection.tsx b/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClockSection.tsx index bd68beaba510..1173681a3da7 100644 --- a/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClockSection.tsx +++ b/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClockSection.tsx @@ -27,13 +27,13 @@ export interface ExportedMultiSectionDigitalClockSectionProps { slotProps?: MultiSectionDigitalClockSlotProps; } -export interface MultiSectionDigitalClockSectionProps +export interface MultiSectionDigitalClockSectionProps extends ExportedMultiSectionDigitalClockSectionProps { autoFocus?: boolean; disabled?: boolean; readOnly?: boolean; - items: MultiSectionDigitalClockOption[]; - onChange: (value: TValue) => void; + items: MultiSectionDigitalClockOption[]; + onChange: (value: TSectionValue) => void; active?: boolean; skipDisabled?: boolean; role?: string; @@ -123,16 +123,17 @@ const MultiSectionDigitalClockSectionItem = styled(MenuItem, { }, })); -type MultiSectionDigitalClockSectionComponent = ( - props: MultiSectionDigitalClockSectionProps & React.RefAttributes, +type MultiSectionDigitalClockSectionComponent = ( + props: MultiSectionDigitalClockSectionProps & + React.RefAttributes, ) => React.JSX.Element & { propTypes?: any }; /** * @ignore - internal component. */ export const MultiSectionDigitalClockSection = React.forwardRef( - function MultiSectionDigitalClockSection( - inProps: MultiSectionDigitalClockSectionProps, + function MultiSectionDigitalClockSection( + inProps: MultiSectionDigitalClockSectionProps, ref: React.Ref, ) { const containerRef = React.useRef(null); diff --git a/packages/x-date-pickers/src/PickersLayout/PickersLayout.tsx b/packages/x-date-pickers/src/PickersLayout/PickersLayout.tsx index 8cdefb9500a2..578a4d6b7e4e 100644 --- a/packages/x-date-pickers/src/PickersLayout/PickersLayout.tsx +++ b/packages/x-date-pickers/src/PickersLayout/PickersLayout.tsx @@ -79,8 +79,8 @@ export const PickersLayoutContentWrapper = styled('div', { flexDirection: 'column', }); -type PickersLayoutComponent = (( - props: PickersLayoutProps & React.RefAttributes, +type PickersLayoutComponent = (( + props: PickersLayoutProps & React.RefAttributes, ) => React.JSX.Element) & { propTypes?: any }; /** @@ -93,9 +93,9 @@ type PickersLayoutComponent = ((inProps: PickersLayoutProps, ref: React.Ref) { +>(inProps: PickersLayoutProps, ref: React.Ref) { const props = useThemeProps({ props: inProps, name: 'MuiPickersLayout' }); const { toolbar, content, tabs, actionBar, shortcuts } = usePickerLayout(props); diff --git a/packages/x-date-pickers/src/PickersLayout/PickersLayout.types.ts b/packages/x-date-pickers/src/PickersLayout/PickersLayout.types.ts index 503256858729..bdbc767c50cf 100644 --- a/packages/x-date-pickers/src/PickersLayout/PickersLayout.types.ts +++ b/packages/x-date-pickers/src/PickersLayout/PickersLayout.types.ts @@ -13,8 +13,12 @@ import { PickersShortcuts, } from '../PickersShortcuts/PickersShortcuts'; import { PickerOwnerState } from '../models'; +import { InferPickerValue } from '../internals/models'; -export interface ExportedPickersLayoutSlots { +export interface ExportedPickersLayoutSlots< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> { /** * Custom component for the action bar, it is placed below the picker views. * @default PickersActionBar @@ -24,13 +28,13 @@ export interface ExportedPickersLayoutSlots>; + shortcuts?: React.JSXElementConstructor>; /** * Custom component for wrapping the layout. * It wraps the toolbar, views, action bar, and shortcuts. */ layout?: React.JSXElementConstructor< - PickersLayoutProps & React.RefAttributes + PickersLayoutProps & React.RefAttributes >; } @@ -39,7 +43,10 @@ export interface PickersLayoutOwnerState extends PickerOwnerState { isLandscape: boolean; } -export interface ExportedPickersLayoutSlotProps { +export interface ExportedPickersLayoutSlotProps< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> { /** * Props passed down to the action bar component. */ @@ -51,11 +58,13 @@ export interface ExportedPickersLayoutSlotProps>; + layout?: Partial>; } -export interface PickersLayoutSlots - extends ExportedPickersLayoutSlots { +export interface PickersLayoutSlots< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> extends ExportedPickersLayoutSlots { /** * Tabs enabling toggling between views. */ @@ -64,11 +73,13 @@ export interface PickersLayoutSlots>; + toolbar?: React.JSXElementConstructor>; } -export interface PickersLayoutSlotProps - extends ExportedPickersLayoutSlotProps { +export interface PickersLayoutSlotProps< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> extends ExportedPickersLayoutSlotProps { /** * Props passed down to the tabs component. */ @@ -79,9 +90,11 @@ export interface PickersLayoutSlotProps - extends Omit, 'value'> { - value?: TValue; +export interface PickersLayoutProps< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> extends Omit, 'value'> { + value?: InferPickerValue; className?: string; children?: React.ReactNode; /** @@ -96,22 +109,22 @@ export interface PickersLayoutProps; + slots?: PickersLayoutSlots; /** * The props used for each component slot. * @default {} */ - slotProps?: PickersLayoutSlotProps; + slotProps?: PickersLayoutSlotProps; /** * `true` if the application is in right-to-left direction. */ isRtl: boolean; } -export interface SubComponents { +export interface SubComponents { toolbar: React.ReactElement | null; content: React.ReactNode; tabs: React.ReactElement | null; actionBar: React.ReactElement; - shortcuts: React.ReactElement> | null; + shortcuts: React.ReactElement> | null; } diff --git a/packages/x-date-pickers/src/PickersLayout/usePickerLayout.tsx b/packages/x-date-pickers/src/PickersLayout/usePickerLayout.tsx index aa34a0a0c06a..56c583b6560e 100644 --- a/packages/x-date-pickers/src/PickersLayout/usePickerLayout.tsx +++ b/packages/x-date-pickers/src/PickersLayout/usePickerLayout.tsx @@ -7,12 +7,12 @@ import { PickersLayoutOwnerState, PickersLayoutProps, SubComponents } from './Pi import { getPickersLayoutUtilityClass, PickersLayoutClasses } from './pickersLayoutClasses'; import { PickersShortcuts } from '../PickersShortcuts'; import { BaseToolbarProps } from '../internals/models/props/toolbar'; -import { DateOrTimeViewWithMeridiem } from '../internals/models'; +import { DateOrTimeViewWithMeridiem, InferPickerValue } from '../internals/models'; import { usePickersPrivateContext } from '../internals/hooks/usePickersPrivateContext'; -function toolbarHasView( - toolbarProps: BaseToolbarProps | any, -): toolbarProps is BaseToolbarProps { +function toolbarHasView( + toolbarProps: BaseToolbarProps | any, +): toolbarProps is BaseToolbarProps { return toolbarProps.view !== null; } @@ -34,15 +34,18 @@ const useUtilityClasses = ( return composeClasses(slots, getPickersLayoutUtilityClass, classes); }; -interface PickersLayoutPropsWithValueRequired - extends PickersLayoutProps { - value: TValue; +interface PickersLayoutPropsWithValueRequired< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> extends PickersLayoutProps { + value: InferPickerValue; } -interface UsePickerLayoutResponse extends SubComponents {} -const usePickerLayout = ( - props: PickersLayoutProps, -): UsePickerLayoutResponse => { +interface UsePickerLayoutResponse extends SubComponents {} + +const usePickerLayout = ( + props: PickersLayoutProps, +): UsePickerLayoutResponse => { const { ownerState: pickersOwnerState } = usePickersPrivateContext(); const { @@ -69,7 +72,7 @@ const usePickerLayout = ( // The true type should be // - For pickers value: PickerValidDate | null // - For range pickers value: [PickerValidDate | null, PickerValidDate | null] - } = props as PickersLayoutPropsWithValueRequired; + } = props as PickersLayoutPropsWithValueRequired; const ownerState: PickersLayoutOwnerState = { ...pickersOwnerState, diff --git a/packages/x-date-pickers/src/PickersShortcuts/PickersShortcuts.tsx b/packages/x-date-pickers/src/PickersShortcuts/PickersShortcuts.tsx index b164341349a3..1b6c822bb444 100644 --- a/packages/x-date-pickers/src/PickersShortcuts/PickersShortcuts.tsx +++ b/packages/x-date-pickers/src/PickersShortcuts/PickersShortcuts.tsx @@ -5,14 +5,15 @@ import List, { ListProps } from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import Chip from '@mui/material/Chip'; import { VIEW_HEIGHT } from '../internals/constants/dimensions'; +import { InferPickerValue } from '../internals/models'; -interface PickersShortcutsItemGetValueParams { - isValid: (value: TValue) => boolean; +interface PickersShortcutsItemGetValueParams { + isValid: (value: InferPickerValue) => boolean; } -export interface PickersShortcutsItem { +export interface PickersShortcutsItem { label: string; - getValue: (params: PickersShortcutsItemGetValueParams) => TValue; + getValue: (params: PickersShortcutsItemGetValueParams) => InferPickerValue; /** * Identifier of the shortcut. * If provided, it will be used as the key of the shortcut. @@ -20,17 +21,18 @@ export interface PickersShortcutsItem { id?: string; } -export type PickersShortcutsItemContext = Omit, 'getValue'>; +export type PickersShortcutsItemContext = Omit, 'getValue'>; export type PickerShortcutChangeImportance = 'set' | 'accept'; -export interface ExportedPickersShortcutProps extends Omit { +export interface ExportedPickersShortcutProps + extends Omit { /** * Ordered array of shortcuts to display. * If empty, does not display the shortcuts. * @default [] */ - items?: PickersShortcutsItem[]; + items?: PickersShortcutsItem[]; /** * Importance of the change when picking a shortcut: * - "accept": fires `onChange`, fires `onAccept` and closes the picker. @@ -40,14 +42,15 @@ export interface ExportedPickersShortcutProps extends Omit extends ExportedPickersShortcutProps { +export interface PickersShortcutsProps + extends ExportedPickersShortcutProps { isLandscape: boolean; onChange: ( - newValue: TValue, + newValue: InferPickerValue, changeImportance: PickerShortcutChangeImportance, shortcut: PickersShortcutsItemContext, ) => void; - isValid: (value: TValue) => boolean; + isValid: (value: InferPickerValue) => boolean; } /** @@ -59,7 +62,7 @@ export interface PickersShortcutsProps extends ExportedPickersShortcutPr * * - [PickersShortcuts API](https://mui.com/x/api/date-pickers/pickers-shortcuts/) */ -function PickersShortcuts(props: PickersShortcutsProps) { +function PickersShortcuts(props: PickersShortcutsProps) { const { items, changeImportance = 'accept', isLandscape, onChange, isValid, ...other } = props; if (items == null || items.length === 0) { diff --git a/packages/x-date-pickers/src/TimeClock/TimeClock.tsx b/packages/x-date-pickers/src/TimeClock/TimeClock.tsx index 07e885a20193..276767b0d992 100644 --- a/packages/x-date-pickers/src/TimeClock/TimeClock.tsx +++ b/packages/x-date-pickers/src/TimeClock/TimeClock.tsx @@ -55,7 +55,7 @@ type TimeClockComponent = (( props: TimeClockProps & React.RefAttributes, ) => React.JSX.Element) & { propTypes?: any }; -const TIME_CLOCK_DEFAULT_VIEWS: TimeView[] = ['hours', 'minutes']; +const TIME_CLOCK_DEFAULT_VIEWS: readonly TimeView[] = ['hours', 'minutes']; /** * Demos: @@ -68,7 +68,7 @@ const TIME_CLOCK_DEFAULT_VIEWS: TimeView[] = ['hours', 'minutes']; * - [TimeClock API](https://mui.com/x/api/date-pickers/time-clock/) */ export const TimeClock = React.forwardRef(function TimeClock( - inProps: TimeClockProps, + inProps: TimeClockProps, ref: React.Ref, ) { const utils = useUtils(); @@ -129,7 +129,10 @@ export const TimeClock = React.forwardRef(function TimeClock( const translations = usePickersTranslations(); const now = useNow(timezone); - const { view, setView, previousView, nextView, setValueAndGoToNextView } = useViews({ + const { view, setView, previousView, nextView, setValueAndGoToNextView } = useViews< + false, + TimeView + >({ view: inView, views, openTo, diff --git a/packages/x-date-pickers/src/TimeField/TimeField.types.ts b/packages/x-date-pickers/src/TimeField/TimeField.types.ts index af41f53ee623..907332c7fd71 100644 --- a/packages/x-date-pickers/src/TimeField/TimeField.types.ts +++ b/packages/x-date-pickers/src/TimeField/TimeField.types.ts @@ -3,12 +3,7 @@ import { SlotComponentProps } from '@mui/utils'; import { MakeOptional } from '@mui/x-internals/types'; import TextField from '@mui/material/TextField'; import { UseFieldInternalProps } from '../internals/hooks/useField'; -import { - FieldSection, - PickerValidDate, - TimeValidationError, - BuiltInFieldTextFieldProps, -} from '../models'; +import { TimeValidationError, BuiltInFieldTextFieldProps } from '../models'; import { ExportedUseClearableFieldProps, UseClearableFieldSlots, @@ -19,12 +14,7 @@ import { AmPmProps } from '../internals/models/props/time'; export interface UseTimeFieldProps extends MakeOptional< - UseFieldInternalProps< - PickerValidDate | null, - FieldSection, - TEnableAccessibleFieldDOMStructure, - TimeValidationError - >, + UseFieldInternalProps, 'format' >, ExportedValidateTimeProps, diff --git a/packages/x-date-pickers/src/TimeField/useTimeField.ts b/packages/x-date-pickers/src/TimeField/useTimeField.ts index 5ec3eba335b5..601d593fe0b6 100644 --- a/packages/x-date-pickers/src/TimeField/useTimeField.ts +++ b/packages/x-date-pickers/src/TimeField/useTimeField.ts @@ -7,7 +7,6 @@ import { useField } from '../internals/hooks/useField'; import { UseTimeFieldProps } from './TimeField.types'; import { validateTime } from '../validation'; import { useSplitFieldProps } from '../hooks'; -import { PickerValidDate, FieldSection } from '../models'; import { useDefaultizedTimeField } from '../internals/hooks/defaultizedFieldProps'; export const useTimeField = < @@ -24,8 +23,7 @@ export const useTimeField = < const { forwardedProps, internalProps } = useSplitFieldProps(props, 'time'); return useField< - PickerValidDate | null, - FieldSection, + false, TEnableAccessibleFieldDOMStructure, typeof forwardedProps, typeof internalProps diff --git a/packages/x-date-pickers/src/TimePicker/TimePicker.types.ts b/packages/x-date-pickers/src/TimePicker/TimePicker.types.ts index 4a22286b2b10..82533fcaa83f 100644 --- a/packages/x-date-pickers/src/TimePicker/TimePicker.types.ts +++ b/packages/x-date-pickers/src/TimePicker/TimePicker.types.ts @@ -11,12 +11,7 @@ import { MobileTimePickerSlots, MobileTimePickerSlotProps, } from '../MobileTimePicker'; -import { - BaseSingleInputFieldProps, - FieldSection, - PickerValidDate, - TimeValidationError, -} from '../models'; +import { BaseSingleInputFieldProps, TimeValidationError } from '../models'; import { UseTimeFieldProps } from '../TimeField'; export interface TimePickerSlots @@ -57,4 +52,4 @@ export type TimePickerFieldProps, 'format' | 'timezone' | 'value' | 'ampm' | keyof BaseTimeValidationProps > & - BaseSingleInputFieldProps; + BaseSingleInputFieldProps; diff --git a/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx b/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx index bd5f40f736b8..8dd274c1391d 100644 --- a/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx +++ b/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx @@ -23,7 +23,7 @@ import { formatMeridiem } from '../internals/utils/date-utils'; import { PickerValidDate } from '../models'; export interface TimePickerToolbarProps - extends BaseToolbarProps, + extends BaseToolbarProps, ExportedTimePickerToolbarProps { ampm?: boolean; ampmInClock?: boolean; diff --git a/packages/x-date-pickers/src/TimePicker/shared.tsx b/packages/x-date-pickers/src/TimePicker/shared.tsx index e5a9a8368f29..f8660a447a9e 100644 --- a/packages/x-date-pickers/src/TimePicker/shared.tsx +++ b/packages/x-date-pickers/src/TimePicker/shared.tsx @@ -11,7 +11,7 @@ import { ExportedTimePickerToolbarProps, TimePickerToolbar, } from './TimePickerToolbar'; -import { PickerValidDate, TimeValidationError } from '../models'; +import { TimeValidationError } from '../models'; import { PickerViewRendererLookup } from '../internals/hooks/usePicker/usePickerViews'; import { TimeViewRendererProps } from '../timeViewRenderers'; import { applyDefaultViewProps } from '../internals/utils/views'; @@ -34,14 +34,14 @@ export type TimePickerViewRenderers< TView extends TimeViewWithMeridiem, TAdditionalProps extends {} = {}, > = PickerViewRendererLookup< - PickerValidDate | null, + false, TView, TimeViewRendererProps>, TAdditionalProps >; export interface BaseTimePickerProps - extends BasePickerInputProps, + extends BasePickerInputProps, ExportedBaseClockProps { /** * Display ampm controls under the clock (instead of in the toolbar). diff --git a/packages/x-date-pickers/src/hooks/useParsedFormat.ts b/packages/x-date-pickers/src/hooks/useParsedFormat.ts index a42e9c652416..0c7fbaea8452 100644 --- a/packages/x-date-pickers/src/hooks/useParsedFormat.ts +++ b/packages/x-date-pickers/src/hooks/useParsedFormat.ts @@ -9,7 +9,7 @@ import type { UseFieldInternalProps } from '../internals/hooks/useField'; interface UseParsedFormatParameters extends Pick< - UseFieldInternalProps, + UseFieldInternalProps, 'format' | 'formatDensity' | 'shouldRespectLeadingZeros' > {} diff --git a/packages/x-date-pickers/src/internals/components/PickersToolbar.tsx b/packages/x-date-pickers/src/internals/components/PickersToolbar.tsx index 47a6e0fa53da..9c868b0c81d4 100644 --- a/packages/x-date-pickers/src/internals/components/PickersToolbar.tsx +++ b/packages/x-date-pickers/src/internals/components/PickersToolbar.tsx @@ -7,8 +7,10 @@ import { BaseToolbarProps } from '../models/props/toolbar'; import { getPickersToolbarUtilityClass, PickersToolbarClasses } from './pickersToolbarClasses'; import { DateOrTimeViewWithMeridiem } from '../models'; -export interface PickersToolbarProps - extends Pick, 'isLandscape' | 'hidden' | 'titleId'> { +export interface PickersToolbarProps< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> extends Pick, 'isLandscape' | 'hidden' | 'titleId'> { className?: string; landscapeDirection?: 'row' | 'column'; toolbarTitle: React.ReactNode; @@ -84,16 +86,19 @@ const PickersToolbarContent = styled('div', { ], }); -type PickersToolbarComponent = (( - props: React.PropsWithChildren> & +type PickersToolbarComponent = (< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +>( + props: React.PropsWithChildren> & React.RefAttributes, ) => React.JSX.Element) & { propTypes?: any }; export const PickersToolbar = React.forwardRef(function PickersToolbar< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, >( - inProps: React.PropsWithChildren>, + inProps: React.PropsWithChildren>, ref: React.Ref, ) { const props = useThemeProps({ props: inProps, name: 'MuiPickersToolbar' }); diff --git a/packages/x-date-pickers/src/internals/hooks/useClockReferenceDate.ts b/packages/x-date-pickers/src/internals/hooks/useClockReferenceDate.ts index cef4af021371..782fc444900a 100644 --- a/packages/x-date-pickers/src/internals/hooks/useClockReferenceDate.ts +++ b/packages/x-date-pickers/src/internals/hooks/useClockReferenceDate.ts @@ -11,7 +11,7 @@ export const useClockReferenceDate = ({ props, timezone, }: { - value: PickerValidDate; + value: PickerValidDate | null; referenceDate: PickerValidDate | undefined; utils: MuiPickersAdapter; props: TProps; 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 9158434b71af..7895473f2111 100644 --- a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx +++ b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx @@ -12,14 +12,7 @@ import { } from './useDesktopPicker.types'; import { usePicker } from '../usePicker'; import { PickersLayout } from '../../../PickersLayout'; -import { - FieldSection, - PickerValidDate, - FieldRef, - BaseSingleInputFieldProps, - InferError, - PickerOwnerState, -} from '../../../models'; +import { FieldRef, BaseSingleInputFieldProps, InferError, PickerOwnerState } from '../../../models'; import { DateOrTimeViewWithMeridiem } from '../../models'; import { PickersProvider } from '../../components/PickersProvider'; @@ -65,7 +58,7 @@ export const useDesktopPicker = < } = props; const containerRef = React.useRef(null); - const fieldRef = React.useRef>(null); + const fieldRef = React.useRef>(null); const labelId = useId(); const isToolbarHidden = innerSlotProps?.toolbar?.hidden ?? false; @@ -80,7 +73,7 @@ export const useDesktopPicker = < shouldRestoreFocus, fieldProps: pickerFieldProps, ownerState, - } = usePicker({ + } = usePicker({ ...pickerParams, props, fieldRef, @@ -126,8 +119,7 @@ export const useDesktopPicker = < UseDesktopPickerSlotProps['field'], Partial< BaseSingleInputFieldProps< - PickerValidDate | null, - FieldSection, + false, TEnableAccessibleFieldDOMStructure, InferError > diff --git a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts index 3e207b42029a..335fcb79975d 100644 --- a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts +++ b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts @@ -11,12 +11,7 @@ import { } from '../../models/props/basePickerProps'; import { PickersPopperSlots, PickersPopperSlotProps } from '../../components/PickersPopper'; import { UsePickerParams } from '../usePicker'; -import { - BaseSingleInputFieldProps, - FieldSection, - PickerOwnerState, - PickerValidDate, -} from '../../../models'; +import { BaseSingleInputFieldProps, PickerOwnerState, PickerValidDate } from '../../../models'; import { ExportedPickersLayoutSlots, ExportedPickersLayoutSlotProps, @@ -35,7 +30,7 @@ export interface UseDesktopPickerSlots PickersPopperSlots, 'desktopPaper' | 'desktopTransition' | 'desktopTrapFocus' | 'popper' >, - ExportedPickersLayoutSlots, + ExportedPickersLayoutSlots, UseClearableFieldSlots { /** * Component used to enter the date with the keyboard. @@ -66,21 +61,16 @@ export interface UseDesktopPickerSlotProps< TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean, > extends ExportedUseDesktopPickerSlotProps, - Pick, 'toolbar'> {} + Pick, 'toolbar'> {} export interface ExportedUseDesktopPickerSlotProps< TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean, > extends PickersPopperSlotProps, - ExportedPickersLayoutSlotProps, + ExportedPickersLayoutSlotProps, UseClearableFieldSlotProps { field?: SlotComponentPropsFromProps< - BaseSingleInputFieldProps< - PickerValidDate | null, - FieldSection, - TEnableAccessibleFieldDOMStructure, - unknown - >, + BaseSingleInputFieldProps, {}, PickerOwnerState >; @@ -106,8 +96,8 @@ export interface UseDesktopPickerProps< TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean, TError, - TExternalProps extends UsePickerViewsProps, -> extends BasePickerProps, + TExternalProps extends UsePickerViewsProps, +> extends BasePickerProps, DesktopOnlyPickerProps { /** * Overridable component slots. @@ -131,7 +121,7 @@ export interface UseDesktopPickerParams< TExternalProps >, > extends Pick< - UsePickerParams, + UsePickerParams, 'valueManager' | 'valueType' | 'validator' | 'rendererInterceptor' > { props: TExternalProps; 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 d12d5263f6b0..157777b5384f 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useField.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useField.ts @@ -17,19 +17,16 @@ import { import { adjustSectionValue, getSectionOrder } from './useField.utils'; import { useFieldState } from './useFieldState'; import { useFieldCharacterEditing } from './useFieldCharacterEditing'; -import { FieldSection } from '../../../models'; import { useFieldV7TextField } from './useFieldV7TextField'; import { useFieldV6TextField } from './useFieldV6TextField'; export const useField = < - TValue, - TSection extends FieldSection, + TIsRange extends boolean, TEnableAccessibleFieldDOMStructure extends boolean, TForwardedProps extends UseFieldCommonForwardedProps & UseFieldForwardedProps, TInternalProps extends UseFieldInternalProps< - any, - any, + TIsRange, TEnableAccessibleFieldDOMStructure, any > & { @@ -37,8 +34,7 @@ export const useField = < }, >( params: UseFieldParams< - TValue, - TSection, + TIsRange, TEnableAccessibleFieldDOMStructure, TForwardedProps, TInternalProps @@ -78,7 +74,7 @@ export const useField = < timezone, } = stateResponse; - const characterEditingResponse = useFieldCharacterEditing({ + const characterEditingResponse = useFieldCharacterEditing({ sections: state.sections, updateSectionValue, sectionsValueBoundaries, 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 44be2122260a..8527e0b2c42f 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 @@ -11,6 +11,7 @@ import { FieldRef, OnErrorProps, InferError, + InferFieldSection, } from '../../../models'; import type { PickerValueManager } from '../usePicker'; import type { Validator } from '../../../validation'; @@ -18,39 +19,38 @@ import type { UseFieldStateResponse } from './useFieldState'; import type { UseFieldCharacterEditingResponse } from './useFieldCharacterEditing'; import { PickersSectionElement, PickersSectionListRef } from '../../../PickersSectionList'; import { ExportedUseClearableFieldProps } from '../../../hooks/useClearableField'; +import { InferNonNullablePickerValue, InferPickerValue } from '../../models'; export interface UseFieldParams< - TValue, - TSection extends FieldSection, + TIsRange extends boolean, TEnableAccessibleFieldDOMStructure extends boolean, TForwardedProps extends UseFieldCommonForwardedProps & UseFieldForwardedProps, - TInternalProps extends UseFieldInternalProps, + TInternalProps extends UseFieldInternalProps, > { forwardedProps: TForwardedProps; internalProps: TInternalProps; - valueManager: PickerValueManager>; - fieldValueManager: FieldValueManager; - validator: Validator, TInternalProps>; + valueManager: PickerValueManager>; + fieldValueManager: FieldValueManager; + validator: Validator, TInternalProps>; valueType: FieldValueType; } export interface UseFieldInternalProps< - TValue, - TSection extends FieldSection, + TIsRange extends boolean, TEnableAccessibleFieldDOMStructure extends boolean, TError, > extends TimezoneProps, - OnErrorProps { + OnErrorProps { /** * The selected value. * Used when the component is controlled. */ - value?: TValue; + value?: InferPickerValue; /** * The default value. Use when the component is not controlled. */ - defaultValue?: TValue; + defaultValue?: InferPickerValue; /** * The date used to generate a part of the new value that is not present in the format when both `value` and `defaultValue` are empty. * For example, on time fields it will be used to determine the date to set. @@ -59,12 +59,12 @@ export interface UseFieldInternalProps< referenceDate?: PickerValidDate; /** * Callback fired when the value changes. - * @template TValue The value type. It will be the same type as `value` or `null`. It can be in `[start, end]` format in case of range value. + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @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 {TValue} value The new value. + * @param {InferPickerValue} value The new value. * @param {FieldChangeHandlerContext} context The context containing the validation result of the current value. */ - onChange?: FieldChangeHandler; + onChange?: FieldChangeHandler; /** * Format of the date when rendered in the input(s). */ @@ -114,7 +114,7 @@ export interface UseFieldInternalProps< /** * The ref object used to imperatively interact with the field. */ - unstableFieldRef?: React.Ref>; + unstableFieldRef?: React.Ref>; /** * @default true */ @@ -132,7 +132,7 @@ export interface UseFieldInternalProps< } export interface UseFieldCommonAdditionalProps - extends Required, 'disabled' | 'readOnly'>> {} + extends Required, 'disabled' | 'readOnly'>> {} export interface UseFieldCommonForwardedProps extends ExportedUseClearableFieldProps { onKeyDown?: React.KeyboardEventHandler; @@ -215,8 +215,8 @@ export type FieldSectionsBoundaries = { }; }; -export type FieldChangeHandler = ( - value: TValue, +export type FieldChangeHandler = ( + value: InferPickerValue, context: FieldChangeHandlerContext, ) => void; @@ -228,7 +228,7 @@ export interface FieldChangeHandlerContext { * Object used to access and update the active date (i.e: the date containing the active section). * Mainly useful in the range fields where we need to update the date containing the active section without impacting the other one. */ -interface FieldActiveDateManager { +interface FieldActiveDateManager { /** * Active date from `state.value`. */ @@ -238,113 +238,113 @@ interface FieldActiveDateManager { */ referenceDate: PickerValidDate; /** - * @template TSection - * @param {TSection[]} sections The sections of the full value. - * @returns {TSection[]} The sections of the active date. + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. + * @param {InferFieldSection[]} sections The sections of the full value. + * @returns {InferFieldSection[]} The sections of the active date. * Get the sections of the active date. */ - getSections: (sections: TSection[]) => TSection[]; + getSections: (sections: InferFieldSection[]) => InferFieldSection[]; /** * Creates the new value and reference value based on the new active date and the current state. - * @template TValue + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @param {PickerValidDate | null} newActiveDate The new value of the date containing the active section. - * @returns {Pick, 'value' | 'referenceValue'>} The new value and reference value to publish and store in the state. + * @returns {Pick, 'value' | 'referenceValue'>} The new value and reference value to publish and store in the state. */ getNewValuesFromNewActiveDate: ( newActiveDate: PickerValidDate | null, - ) => Pick, 'value' | 'referenceValue'>; + ) => Pick, 'value' | 'referenceValue'>; } export type FieldParsedSelectedSections = number | 'all' | null; -export interface FieldValueManager { +export interface FieldValueManager { /** * Creates the section list from the current value. * The `prevSections` are used on the range fields to avoid losing the sections of a partially filled date when editing the other date. - * @template TValue, TSection + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @param {MuiPickersAdapter} utils The utils to manipulate the date. - * @param {TValue} value The current value to generate sections from. - * @param {TSection[] | null} fallbackSections The sections to use as a fallback if a date is null or invalid. + * @param {InferPickerValue} value The current value to generate sections from. + * @param {InferFieldSection[] | null} fallbackSections The sections to use as a fallback if a date is null or invalid. * @param {(date: PickerValidDate) => FieldSection[]} getSectionsFromDate Returns the sections of the given date. - * @returns {TSection[]} The new section list. + * @returns {InferFieldSection[]} The new section list. */ getSectionsFromValue: ( utils: MuiPickersAdapter, - value: TValue, - fallbackSections: TSection[] | null, + value: InferPickerValue, + fallbackSections: InferFieldSection[] | null, getSectionsFromDate: (date: PickerValidDate) => FieldSection[], - ) => TSection[]; + ) => InferFieldSection[]; /** * Creates the string value to render in the input based on the current section list. - * @template TSection - * @param {TSection[]} sections The current section list. + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. + * @param {InferFieldSection[]} sections The current section list. * @param {string} localizedDigits The conversion table from localized to 0-9 digits. * @param {boolean} isRtl `true` if the current orientation is "right to left" * @returns {string} The string value to render in the input. */ getV6InputValueFromSections: ( - sections: TSection[], + sections: InferFieldSection[], localizedDigits: string[], isRtl: boolean, ) => string; /** * Creates the string value to render in the input based on the current section list. - * @template TSection - * @param {TSection[]} sections The current section list. + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. + * @param {InferFieldSection[]} sections The current section list. * @returns {string} The string value to render in the input. */ - getV7HiddenInputValueFromSections: (sections: TSection[]) => string; + getV7HiddenInputValueFromSections: (sections: InferFieldSection[]) => string; /** * Returns the manager of the active date. - * @template TValue, TSection + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @param {MuiPickersAdapter} utils The utils to manipulate the date. - * @param {UseFieldState} state The current state of the field. - * @param {TSection} activeSection The active section. - * @returns {FieldActiveDateManager} The manager of the active date. + * @param {UseFieldState} state The current state of the field. + * @param {InferFieldSection} activeSection The active section. + * @returns {FieldActiveDateManager} The manager of the active date. */ getActiveDateManager: ( utils: MuiPickersAdapter, - state: UseFieldState, - activeSection: TSection, - ) => FieldActiveDateManager; + state: UseFieldState, + activeSection: InferFieldSection, + ) => FieldActiveDateManager; /** * Parses a string version (most of the time coming from the input). * This method should only be used when the change does not come from a single section. - * @template TValue + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @param {string} valueStr The string value to parse. - * @param {TValue} referenceValue The reference value currently stored in state. + * @param {InferPickerValue} referenceValue The reference value currently stored in state. * @param {(dateStr: string, referenceDate: PickerValidDate) => PickerValidDate | null} parseDate A method to convert a string date into a parsed one. - * @returns {TValue} The new parsed value. + * @returns {InferPickerValue} The new parsed value. */ parseValueStr: ( valueStr: string, - referenceValue: TValue, + referenceValue: InferNonNullablePickerValue, parseDate: (dateStr: string, referenceDate: PickerValidDate) => PickerValidDate | null, - ) => TValue; + ) => InferPickerValue; /** * Update the reference value with the new value. * This method must make sure that no date inside the returned `referenceValue` is invalid. - * @template TValue + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @param {MuiPickersAdapter} utils The utils to manipulate the date. - * @param {TValue} value The new value from which we want to take all valid dates in the `referenceValue` state. - * @param {TValue} prevReferenceValue The previous reference value. It is used as a fallback for invalid dates in the new value. - * @returns {TValue} The new reference value with no invalid date. + * @param {InferPickerValue} value The new value from which we want to take all valid dates in the `referenceValue` state. + * @param {InferPickerValue} prevReferenceValue The previous reference value. It is used as a fallback for invalid dates in the new value. + * @returns {InferPickerValue} The new reference value with no invalid date. */ updateReferenceValue: ( utils: MuiPickersAdapter, - value: TValue, - prevReferenceValue: TValue, - ) => TValue; + value: InferPickerValue, + prevReferenceValue: InferNonNullablePickerValue, + ) => InferNonNullablePickerValue; } -export interface UseFieldState { - value: TValue; +export interface UseFieldState { + value: InferPickerValue; /** * Non-nullable value used to keep trace of the timezone and the date parts not present in the format. * It is updated whenever we have a valid date (for the range picker we update only the portion of the range that is valid). */ - referenceValue: TValue; - sections: TSection[]; + referenceValue: InferNonNullablePickerValue; + sections: InferFieldSection[]; /** * Android `onChange` behavior when the input selection is not empty is quite different from a desktop behavior. * There are two `onChange` calls: @@ -423,14 +423,12 @@ export interface UseFieldTextFieldInteractions { } export type UseFieldTextField = < - TValue, - TSection extends FieldSection, + TIsRange extends boolean, TForwardedProps extends TEnableAccessibleFieldDOMStructure extends false ? UseFieldV6ForwardedProps : UseFieldV7ForwardedProps, TInternalProps extends UseFieldInternalProps< - any, - any, + TIsRange, TEnableAccessibleFieldDOMStructure, any > & { @@ -438,8 +436,7 @@ export type UseFieldTextField( params: UseFieldTextFieldParams< - TValue, - TSection, + TIsRange, TEnableAccessibleFieldDOMStructure, TForwardedProps, TInternalProps @@ -452,21 +449,19 @@ export type UseFieldTextField, + TInternalProps extends UseFieldInternalProps, > extends UseFieldParams< - TValue, - TSection, + TIsRange, TEnableAccessibleFieldDOMStructure, TForwardedProps, TInternalProps >, - UseFieldStateResponse, + UseFieldStateResponse, UseFieldCharacterEditingResponse { areAllSectionsEmpty: boolean; sectionOrder: SectionOrdering; diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useField.utils.ts b/packages/x-date-pickers/src/internals/hooks/useField/useField.utils.ts index f3d00d85af1d..de8b8eb6b894 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useField.utils.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useField.utils.ts @@ -15,6 +15,7 @@ import { PickersTimezone, PickerValidDate, FieldSelectedSections, + InferFieldSection, } from '../../../models'; import { getMonthsInYear } from '../../utils/date-utils'; @@ -230,10 +231,10 @@ export const cleanDigitSectionValue = ( return applyLocalizedDigits(valueStr, localizedDigits); }; -export const adjustSectionValue = ( +export const adjustSectionValue = ( utils: MuiPickersAdapter, timezone: PickersTimezone, - section: TSection, + section: InferFieldSection, keyCode: AvailableAdjustKeyCode, sectionsValueBoundaries: FieldSectionsValueBoundaries, localizedDigits: string[], @@ -614,8 +615,8 @@ export const getSectionsBoundaries = ( let warnedOnceInvalidSection = false; -export const validateSections = ( - sections: TSection[], +export const validateSections = ( + sections: InferFieldSection[], valueType: FieldValueType, ) => { if (process.env.NODE_ENV !== 'production') { diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useFieldCharacterEditing.ts b/packages/x-date-pickers/src/internals/hooks/useField/useFieldCharacterEditing.ts index 7e3ff21ee74f..5c890b8f4b46 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useFieldCharacterEditing.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useFieldCharacterEditing.ts @@ -1,6 +1,11 @@ import * as React from 'react'; import useEventCallback from '@mui/utils/useEventCallback'; -import { FieldSectionType, FieldSection, PickersTimezone } from '../../../models'; +import { + FieldSectionType, + FieldSection, + PickersTimezone, + InferFieldSection, +} from '../../../models'; import { useUtils } from '../useUtils'; import { FieldSectionsValueBoundaries } from './useField.types'; import { @@ -27,9 +32,9 @@ export interface ApplyCharacterEditingParams { sectionIndex: number; } -interface UseFieldCharacterEditingParams { - sections: TSection[]; - updateSectionValue: (params: UpdateSectionValueParams) => void; +interface UseFieldCharacterEditingParams { + sections: InferFieldSection[]; + updateSectionValue: (params: UpdateSectionValueParams) => void; sectionsValueBoundaries: FieldSectionsValueBoundaries; localizedDigits: string[]; setTempAndroidValueStr: (newValue: string | null) => void; @@ -65,15 +70,15 @@ type CharacterEditingApplier = ( * If it returns `{ saveQuery: false }, * Then we do nothing. */ -type QueryApplier = ( +type QueryApplier = ( queryValue: string, - activeSection: TSection, + activeSection: InferFieldSection, ) => { sectionValue: string; shouldGoToNextSection: boolean } | { saveQuery: boolean }; const QUERY_LIFE_DURATION_MS = 5000; -const isQueryResponseWithoutValue = ( - response: ReturnType>, +const isQueryResponseWithoutValue = ( + response: ReturnType>, ): response is { saveQuery: boolean } => (response as { saveQuery: boolean }).saveQuery != null; /** @@ -83,14 +88,14 @@ const isQueryResponseWithoutValue = ( * 1. The numeric editing when the user presses a digit * 2. The letter editing when the user presses another key */ -export const useFieldCharacterEditing = ({ +export const useFieldCharacterEditing = ({ sections, updateSectionValue, sectionsValueBoundaries, localizedDigits, setTempAndroidValueStr, timezone, -}: UseFieldCharacterEditingParams): UseFieldCharacterEditingResponse => { +}: UseFieldCharacterEditingParams): UseFieldCharacterEditingResponse => { const utils = useUtils(); const [query, setQuery] = React.useState(null); @@ -117,7 +122,7 @@ export const useFieldCharacterEditing = ({ const applyQuery = ( { keyPressed, sectionIndex }: ApplyCharacterEditingParams, - getFirstSectionValueMatchingWithQuery: QueryApplier, + getFirstSectionValueMatchingWithQuery: QueryApplier, isValidQueryValue?: (queryValue: string) => boolean, ): ReturnType => { const cleanKeyPressed = keyPressed.toLowerCase(); @@ -170,7 +175,7 @@ export const useFieldCharacterEditing = ({ format: string, options: string[], queryValue: string, - ): ReturnType> => { + ): ReturnType> => { const matchingValues = options.filter((option) => option.toLowerCase().startsWith(queryValue), ); @@ -187,7 +192,7 @@ export const useFieldCharacterEditing = ({ const testQueryOnFormatAndFallbackFormat = ( queryValue: string, - activeSection: TSection, + activeSection: InferFieldSection, fallbackFormat?: string, formatFallbackValue?: (fallbackValue: string, fallbackOptions: string[]) => string, ) => { @@ -225,7 +230,7 @@ export const useFieldCharacterEditing = ({ return { saveQuery: false }; }; - const getFirstSectionValueMatchingWithQuery: QueryApplier = ( + const getFirstSectionValueMatchingWithQuery: QueryApplier = ( queryValue, activeSection, ) => { @@ -284,7 +289,7 @@ export const useFieldCharacterEditing = ({ | 'hasLeadingZerosInInput' | 'maxLength' >, - ): ReturnType> => { + ): ReturnType> => { const cleanQueryValue = removeLocalizedDigits(queryValue, localizedDigits); const queryValueNumber = Number(cleanQueryValue); const sectionBoundaries = sectionsValueBoundaries[section.type]({ @@ -319,7 +324,7 @@ export const useFieldCharacterEditing = ({ return { sectionValue: newSectionValue, shouldGoToNextSection }; }; - const getFirstSectionValueMatchingWithQuery: QueryApplier = ( + const getFirstSectionValueMatchingWithQuery: QueryApplier = ( queryValue, activeSection, ) => { 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 1282c4c6b578..221658d8462f 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts @@ -22,23 +22,24 @@ import { } from './useField.utils'; import { buildSectionsFromFormat } from './buildSectionsFromFormat'; import { - FieldSection, FieldSelectedSections, PickersTimezone, PickerValidDate, InferError, + InferFieldSection, } from '../../../models'; import { useValueWithTimezone } from '../useValueWithTimezone'; import { GetDefaultReferenceDateProps, getSectionTypeGranularity, } from '../../utils/getDefaultReferenceDate'; +import { InferPickerValue } from '../../models'; -export interface UpdateSectionValueParams { +export interface UpdateSectionValueParams { /** * The section on which we want to apply the new value. */ - activeSection: TSection; + activeSection: InferFieldSection; /** * Value to apply to the active section. */ @@ -49,37 +50,38 @@ export interface UpdateSectionValueParams { shouldGoToNextSection: boolean; } -export interface UseFieldStateResponse { - state: UseFieldState; +export interface UseFieldStateResponse { + state: UseFieldState; activeSectionIndex: number | null; parsedSelectedSections: FieldParsedSelectedSections; setSelectedSections: (sections: FieldSelectedSections) => void; clearValue: () => void; clearActiveSection: () => void; - updateSectionValue: (params: UpdateSectionValueParams) => void; + updateSectionValue: (params: UpdateSectionValueParams) => void; updateValueFromValueStr: (valueStr: string) => void; setTempAndroidValueStr: (tempAndroidValueStr: string | null) => void; sectionsValueBoundaries: FieldSectionsValueBoundaries; - getSectionsFromValue: (value: TValue, fallbackSections?: TSection[] | null) => TSection[]; + getSectionsFromValue: ( + value: InferPickerValue, + fallbackSections?: InferFieldSection[] | null, + ) => InferFieldSection[]; localizedDigits: string[]; timezone: PickersTimezone; } export const useFieldState = < - TValue, - TSection extends FieldSection, + TIsRange extends boolean, TEnableAccessibleFieldDOMStructure extends boolean, TForwardedProps extends UseFieldForwardedProps, - TInternalProps extends UseFieldInternalProps, + TInternalProps extends UseFieldInternalProps, >( params: UseFieldParams< - TValue, - TSection, + TIsRange, TEnableAccessibleFieldDOMStructure, TForwardedProps, TInternalProps >, -): UseFieldStateResponse => { +): UseFieldStateResponse => { const utils = useUtils(); const translations = usePickersTranslations(); const adapter = useLocalizationContext(); @@ -126,7 +128,10 @@ export const useFieldState = < ); const getSectionsFromValue = React.useCallback( - (value: TValue, fallbackSections: TSection[] | null = null) => + ( + value: InferPickerValue, + fallbackSections: InferFieldSection[] | null = null, + ) => fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, (date) => buildSectionsFromFormat({ utils, @@ -153,14 +158,13 @@ export const useFieldState = < ], ); - const [state, setState] = React.useState>(() => { + const [state, setState] = React.useState>(() => { const sections = getSectionsFromValue(valueFromTheOutside); validateSections(sections, valueType); - const stateWithoutReferenceDate: UseFieldState = { + const stateWithoutReferenceDate: Omit, 'referenceValue'> = { sections, value: valueFromTheOutside, - referenceValue: valueManager.emptyValue, tempValueStrAndroid: null, }; @@ -203,7 +207,7 @@ export const useFieldState = < value, referenceValue, sections, - }: Pick, 'value' | 'referenceValue' | 'sections'>) => { + }: Pick, 'value' | 'referenceValue' | 'sections'>) => { setState((prevState) => ({ ...prevState, sections, @@ -309,7 +313,7 @@ export const useFieldState = < activeSection, newSectionValue, shouldGoToNextSection, - }: UpdateSectionValueParams) => { + }: UpdateSectionValueParams) => { /** * 1. Decide which section should be focused */ @@ -325,7 +329,7 @@ export const useFieldState = < const newActiveDateSections = activeDateManager.getSections(newSections); const newActiveDate = getDateFromDateSections(utils, newActiveDateSections, localizedDigits); - let values: Pick, 'value' | 'referenceValue'>; + let values: Pick, 'value' | 'referenceValue'>; let shouldPublish: boolean; /** diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useFieldV6TextField.ts b/packages/x-date-pickers/src/internals/hooks/useField/useFieldV6TextField.ts index 288b0ee44de9..5fdf2c07dfed 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useFieldV6TextField.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useFieldV6TextField.ts @@ -3,11 +3,11 @@ import { useRtl } from '@mui/system/RtlProvider'; import useEventCallback from '@mui/utils/useEventCallback'; import useForkRef from '@mui/utils/useForkRef'; import { UseFieldTextFieldInteractions, UseFieldTextField } from './useField.types'; -import { FieldSection } from '../../../models'; +import { InferFieldSection } from '../../../models'; import { getActiveElement } from '../../utils/utils'; import { getSectionVisibleValue, isAndroid } from './useField.utils'; -type FieldSectionWithPositions = TSection & { +type FieldSectionWithPositions = InferFieldSection & { /** * Start index of the section in the format */ @@ -30,14 +30,14 @@ type FieldSectionWithPositions = TSection & { const cleanString = (dirtyString: string) => dirtyString.replace(/[\u2066\u2067\u2068\u2069]/g, ''); -export const addPositionPropertiesToSections = ( - sections: TSection[], +export const addPositionPropertiesToSections = ( + sections: InferFieldSection[], localizedDigits: string[], isRtl: boolean, -): FieldSectionWithPositions[] => { +): FieldSectionWithPositions[] => { let position = 0; let positionInInput = isRtl ? 1 : 0; - const newSections: FieldSectionWithPositions[] = []; + const newSections: FieldSectionWithPositions[] = []; for (let i = 0; i < sections.length; i += 1) { const section = sections[i]; 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 917c358b6737..560b3b2cb4b5 100644 --- a/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.tsx +++ b/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.tsx @@ -11,14 +11,7 @@ import { import { usePicker } from '../usePicker'; import { onSpaceOrEnter } from '../../utils/utils'; import { PickersLayout } from '../../../PickersLayout'; -import { - FieldSection, - BaseSingleInputFieldProps, - PickerValidDate, - FieldRef, - InferError, - PickerOwnerState, -} from '../../../models'; +import { BaseSingleInputFieldProps, FieldRef, InferError, PickerOwnerState } from '../../../models'; import { DateOrTimeViewWithMeridiem } from '../../models'; import { PickersProvider } from '../../components/PickersProvider'; @@ -61,7 +54,7 @@ export const useMobilePicker = < localeText, } = props; - const fieldRef = React.useRef>(null); + const fieldRef = React.useRef>(null); const labelId = useId(); const isToolbarHidden = innerSlotProps?.toolbar?.hidden ?? false; @@ -74,7 +67,7 @@ export const useMobilePicker = < renderCurrentView, fieldProps: pickerFieldProps, ownerState, - } = usePicker({ + } = usePicker({ ...pickerParams, props, fieldRef, @@ -90,8 +83,7 @@ export const useMobilePicker = < UseMobilePickerSlotProps['field'], Partial< BaseSingleInputFieldProps< - PickerValidDate | null, - FieldSection, + false, TEnableAccessibleFieldDOMStructure, InferError > diff --git a/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.types.ts b/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.types.ts index 27824fd3df82..961ab47f87ec 100644 --- a/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.types.ts +++ b/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.types.ts @@ -12,12 +12,7 @@ import { PickersModalDialogSlotProps, } from '../../components/PickersModalDialog'; import { UsePickerParams } from '../usePicker'; -import { - BaseSingleInputFieldProps, - FieldSection, - PickerOwnerState, - PickerValidDate, -} from '../../../models'; +import { BaseSingleInputFieldProps, PickerOwnerState, PickerValidDate } from '../../../models'; import { ExportedPickersLayoutSlots, ExportedPickersLayoutSlotProps, @@ -29,7 +24,7 @@ import { DateOrTimeViewWithMeridiem } from '../../models'; export interface UseMobilePickerSlots extends PickersModalDialogSlots, - ExportedPickersLayoutSlots { + ExportedPickersLayoutSlots { /** * Component used to enter the date with the keyboard. */ @@ -45,14 +40,9 @@ export interface ExportedUseMobilePickerSlotProps< TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean, > extends PickersModalDialogSlotProps, - ExportedPickersLayoutSlotProps { + ExportedPickersLayoutSlotProps { field?: SlotComponentPropsFromProps< - BaseSingleInputFieldProps< - PickerValidDate | null, - FieldSection, - TEnableAccessibleFieldDOMStructure, - unknown - >, + BaseSingleInputFieldProps, {}, PickerOwnerState >; @@ -63,7 +53,7 @@ export interface UseMobilePickerSlotProps< TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean, > extends ExportedUseMobilePickerSlotProps, - Pick, 'toolbar'> {} + Pick, 'toolbar'> {} export interface MobileOnlyPickerProps extends BaseNonStaticPickerProps, @@ -76,7 +66,7 @@ export interface UseMobilePickerProps< TEnableAccessibleFieldDOMStructure extends boolean, TError, TExternalProps extends UsePickerViewsProps, -> extends BasePickerProps, +> extends BasePickerProps, MobileOnlyPickerProps { /** * Overridable component slots. @@ -100,7 +90,7 @@ export interface UseMobilePickerParams< TExternalProps >, > extends Pick< - UsePickerParams, + UsePickerParams, 'valueManager' | 'valueType' | 'validator' > { props: TExternalProps; 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 d9693d260b45..08fcf80e1c30 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.ts @@ -3,16 +3,15 @@ import { UsePickerParams, UsePickerProps, UsePickerResponse } from './usePicker. import { usePickerValue } from './usePickerValue'; import { usePickerViews } from './usePickerViews'; import { usePickerLayoutProps } from './usePickerLayoutProps'; -import { FieldSection, InferError } from '../../../models'; +import { InferError } from '../../../models'; import { DateOrTimeViewWithMeridiem } from '../../models'; import { usePickerOwnerState } from './usePickerOwnerState'; import { usePickerProvider } from './usePickerProvider'; export const usePicker = < - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, - TSection extends FieldSection, - TExternalProps extends UsePickerProps, + TExternalProps extends UsePickerProps, TAdditionalProps extends {}, >({ props, @@ -25,10 +24,9 @@ export const usePicker = < rendererInterceptor, fieldRef, localeText, -}: UsePickerParams): UsePickerResponse< - TValue, +}: UsePickerParams): UsePickerResponse< + TIsRange, TView, - TSection, InferError > => { if (process.env.NODE_ENV !== 'production') { @@ -40,7 +38,7 @@ export const usePicker = < ]); } } - const pickerValueResponse = usePickerValue({ + const pickerValueResponse = usePickerValue({ props, valueManager, valueType, @@ -48,13 +46,7 @@ export const usePicker = < validator, }); - const pickerViewsResponse = usePickerViews< - TValue, - TView, - TSection, - TExternalProps, - TAdditionalProps - >({ + const pickerViewsResponse = usePickerViews({ props, additionalViewProps, autoFocusView, diff --git a/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.types.ts b/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.types.ts index 7d10cee30cff..807204616ed3 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.types.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.types.ts @@ -11,7 +11,7 @@ import { UsePickerViewsBaseProps, } from './usePickerViews'; import { UsePickerLayoutProps, UsePickerLayoutPropsResponse } from './usePickerLayoutProps'; -import { FieldSection, PickerOwnerState } from '../../../models'; +import { PickerOwnerState } from '../../../models'; import { DateOrTimeViewWithMeridiem } from '../../models'; import { UsePickerProviderParameters, UsePickerProviderReturnValue } from './usePickerProvider'; @@ -19,51 +19,49 @@ import { UsePickerProviderParameters, UsePickerProviderReturnValue } from './use * Props common to all picker headless implementations. */ export interface UsePickerBaseProps< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, TError, - TExternalProps extends UsePickerViewsProps, + TExternalProps extends UsePickerViewsProps, TAdditionalProps extends {}, -> extends UsePickerValueBaseProps, - UsePickerViewsBaseProps, +> extends UsePickerValueBaseProps, + UsePickerViewsBaseProps, UsePickerLayoutProps {} export interface UsePickerProps< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, TError, - TExternalProps extends UsePickerViewsProps, + TExternalProps extends UsePickerViewsProps, TAdditionalProps extends {}, -> extends UsePickerValueProps, - UsePickerViewsProps, +> extends UsePickerValueProps, + UsePickerViewsProps, UsePickerLayoutProps {} export interface UsePickerParams< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, - TSection extends FieldSection, - TExternalProps extends UsePickerProps, + TExternalProps extends UsePickerProps, TAdditionalProps extends {}, > extends Pick< - UsePickerValueParams, + UsePickerValueParams, 'valueManager' | 'valueType' | 'wrapperVariant' | 'validator' >, Pick< - UsePickerViewParams, + UsePickerViewParams, 'additionalViewProps' | 'autoFocusView' | 'rendererInterceptor' | 'fieldRef' >, - Pick, 'localeText'> { + Pick, 'localeText'> { props: TExternalProps; } export interface UsePickerResponse< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, - TSection extends FieldSection, TError, -> extends Omit, 'viewProps' | 'layoutProps'>, +> extends Omit, 'viewProps' | 'layoutProps'>, Omit, 'layoutProps'>, - UsePickerLayoutPropsResponse { + UsePickerLayoutPropsResponse { ownerState: PickerOwnerState; providerProps: UsePickerProviderReturnValue; } diff --git a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerLayoutProps.ts b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerLayoutProps.ts index f4084f8b3222..7b33e2fb2032 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerLayoutProps.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerLayoutProps.ts @@ -3,6 +3,7 @@ import { useIsLandscape } from '../useIsLandscape'; import { UsePickerValueLayoutResponse } from './usePickerValue.types'; import { UsePickerViewsLayoutResponse } from './usePickerViews'; import { DateOrTimeViewWithMeridiem, WrapperVariant } from '../../models/common'; +import { InferPickerValue } from '../../models'; /** * Props used to create the layout of the views. @@ -18,24 +19,30 @@ export interface UsePickerLayoutProps { } export interface UsePickerLayoutPropsResponseLayoutProps< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, -> extends UsePickerValueLayoutResponse, +> extends UsePickerValueLayoutResponse, UsePickerViewsLayoutResponse, UsePickerLayoutProps { isLandscape: boolean; isRtl: boolean; wrapperVariant: WrapperVariant; - isValid: (value: TValue) => boolean; + isValid: (value: InferPickerValue) => boolean; } -export interface UsePickerLayoutPropsResponse { - layoutProps: UsePickerLayoutPropsResponseLayoutProps; +export interface UsePickerLayoutPropsResponse< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> { + layoutProps: UsePickerLayoutPropsResponseLayoutProps; } -export interface UsePickerLayoutPropsParams { +export interface UsePickerLayoutPropsParams< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> { props: UsePickerLayoutProps; - propsFromPickerValue: UsePickerValueLayoutResponse; + propsFromPickerValue: UsePickerValueLayoutResponse; propsFromPickerViews: UsePickerViewsLayoutResponse; wrapperVariant: WrapperVariant; } @@ -43,17 +50,20 @@ export interface UsePickerLayoutPropsParams({ +export const usePickerLayoutProps = < + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +>({ props, propsFromPickerValue, propsFromPickerViews, wrapperVariant, -}: UsePickerLayoutPropsParams): UsePickerLayoutPropsResponse => { +}: UsePickerLayoutPropsParams): UsePickerLayoutPropsResponse => { const { orientation } = props; const isLandscape = useIsLandscape(propsFromPickerViews.views, orientation); const isRtl = useRtl(); - const layoutProps: UsePickerLayoutPropsResponseLayoutProps = { + const layoutProps: UsePickerLayoutPropsResponseLayoutProps = { ...propsFromPickerViews, ...propsFromPickerValue, isLandscape, diff --git a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerOwnerState.ts b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerOwnerState.ts index 32da73815c61..5014acb9c999 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerOwnerState.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerOwnerState.ts @@ -1,17 +1,17 @@ import * as React from 'react'; -import { FieldSection, PickerOwnerState } from '../../../models'; +import { PickerOwnerState } from '../../../models'; import type { UsePickerProps } from './usePicker.types'; import { PickerValueManager, UsePickerValueResponse } from './usePickerValue.types'; import { useUtils } from '../useUtils'; -interface UsePickerOwnerStateParameters { - props: UsePickerProps; - pickerValueResponse: UsePickerValueResponse; - valueManager: PickerValueManager; +interface UsePickerOwnerStateParameters { + props: UsePickerProps; + pickerValueResponse: UsePickerValueResponse; + valueManager: PickerValueManager; } -export function usePickerOwnerState( - parameters: UsePickerOwnerStateParameters, +export function usePickerOwnerState( + parameters: UsePickerOwnerStateParameters, ): PickerOwnerState { const { props, pickerValueResponse, valueManager } = parameters; diff --git a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerProvider.ts b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerProvider.ts index e3bec5e1b8e1..2d3a83e6d02c 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerProvider.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerProvider.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { FieldSection, PickerOwnerState } from '../../../models'; +import { PickerOwnerState } from '../../../models'; import { UsePickerValueResponse } from './usePickerValue.types'; import { PickersProviderProps, @@ -7,16 +7,16 @@ import { PickersPrivateContextValue, } from '../../components/PickersProvider'; -export interface UsePickerProviderParameters +export interface UsePickerProviderParameters extends Pick { - pickerValueResponse: UsePickerValueResponse; + pickerValueResponse: UsePickerValueResponse; ownerState: PickerOwnerState; } export interface UsePickerProviderReturnValue extends Omit {} -export function usePickerProvider( - parameters: UsePickerProviderParameters, +export function usePickerProvider( + parameters: UsePickerProviderParameters, ): UsePickerProviderReturnValue { const { pickerValueResponse, ownerState, localeText } = parameters; 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 f24d9e11a718..0853a147a7e3 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.ts @@ -4,7 +4,7 @@ import { useOpenState } from '../useOpenState'; import { useLocalizationContext, useUtils } from '../useUtils'; import { FieldChangeHandlerContext } from '../useField'; import { useValidation } from '../../../validation'; -import { FieldSection, PickerChangeHandlerContext, InferError } from '../../../models'; +import { PickerChangeHandlerContext, InferError } from '../../../models'; import { PickerShortcutChangeImportance, PickersShortcutsItemContext, @@ -23,13 +23,14 @@ import { PickerValueUpdaterParams, } from './usePickerValue.types'; import { useValueWithTimezone } from '../useValueWithTimezone'; +import { InferPickerValue } from '../../models'; /** * Decide if the new value should be published * The published value will be passed to `onChange` if defined. */ -const shouldPublishValue = ( - params: PickerValueUpdaterParams, +const shouldPublishValue = ( + params: PickerValueUpdaterParams, ): boolean => { const { action, hasChanged, dateState, isControlled } = params; @@ -81,8 +82,8 @@ const shouldPublishValue = ( * The committed value will be passed to `onAccept` if defined. * It will also be used as a reset target when calling the `cancel` picker action (when clicking on the "Cancel" button). */ -const shouldCommitValue = ( - params: PickerValueUpdaterParams, +const shouldCommitValue = ( + params: PickerValueUpdaterParams, ): boolean => { const { action, hasChanged, dateState, isControlled, closeOnSelect } = params; @@ -121,8 +122,8 @@ const shouldCommitValue = ( /** * Decide if the picker should be closed after the value is updated. */ -const shouldClosePicker = ( - params: PickerValueUpdaterParams, +const shouldClosePicker = ( + params: PickerValueUpdaterParams, ): boolean => { const { action, closeOnSelect } = params; @@ -145,18 +146,16 @@ const shouldClosePicker = ( * Manage the value lifecycle of all the pickers. */ export const usePickerValue = < - TValue, - TSection extends FieldSection, - TExternalProps extends UsePickerValueProps, + TIsRange extends boolean, + TExternalProps extends UsePickerValueProps, >({ props, valueManager, valueType, wrapperVariant, validator, -}: UsePickerValueParams): UsePickerValueResponse< - TValue, - TSection, +}: UsePickerValueParams): UsePickerValueResponse< + TIsRange, InferError > => { type TError = InferError; @@ -221,8 +220,8 @@ export const usePickerValue = < valueManager, }); - const [dateState, setDateState] = React.useState>(() => { - let initialValue: TValue; + const [dateState, setDateState] = React.useState>(() => { + let initialValue: InferPickerValue; if (inValueWithTimezoneToRender !== undefined) { initialValue = inValueWithTimezoneToRender; } else if (defaultValue !== undefined) { @@ -248,8 +247,8 @@ export const usePickerValue = < onError: props.onError, }); - const updateDate = useEventCallback((action: PickerValueUpdateAction) => { - const updaterParams: PickerValueUpdaterParams = { + const updateDate = useEventCallback((action: PickerValueUpdateAction) => { + const updaterParams: PickerValueUpdaterParams = { action, dateState, hasChanged: (comparison) => !valueManager.areValuesEqual(utils, action.value, comparison), @@ -382,13 +381,13 @@ export const usePickerValue = < }); const handleChange = useEventCallback( - (newValue: TValue, selectionState: PickerSelectionState = 'partial') => + (newValue: InferPickerValue, selectionState: PickerSelectionState = 'partial') => updateDate({ name: 'setValueFromView', value: newValue, selectionState }), ); const handleSelectShortcut = useEventCallback( ( - newValue: TValue, + newValue: InferPickerValue, changeImportance: PickerShortcutChangeImportance, shortcut: PickersShortcutsItemContext, ) => @@ -401,7 +400,7 @@ export const usePickerValue = < ); const handleChangeFromField = useEventCallback( - (newValue: TValue, context: FieldChangeHandlerContext) => + (newValue: InferPickerValue, context: FieldChangeHandlerContext) => updateDate({ name: 'setValueFromField', value: newValue, context }), ); @@ -415,7 +414,7 @@ export const usePickerValue = < onClose: handleClose, }; - const fieldResponse: UsePickerValueFieldResponse = { + const fieldResponse: UsePickerValueFieldResponse = { value: dateState.draft, onChange: handleChangeFromField, }; @@ -425,14 +424,14 @@ export const usePickerValue = < [utils, valueManager, dateState.draft], ); - const viewResponse: UsePickerValueViewsResponse = { + const viewResponse: UsePickerValueViewsResponse = { value: viewValue, onChange: handleChange, onClose: handleClose, open: isOpen, }; - const isValid = (testedValue: TValue) => { + const isValid = (testedValue: InferPickerValue) => { const error = validator({ adapter, value: testedValue, @@ -443,7 +442,7 @@ export const usePickerValue = < return !valueManager.hasError(error); }; - const layoutResponse: UsePickerValueLayoutResponse = { + const layoutResponse: UsePickerValueLayoutResponse = { ...actions, value: viewValue, onChange: handleChange, 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 d78af26b4c96..4ff3bac4a343 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 @@ -2,7 +2,6 @@ import { FieldChangeHandlerContext, UseFieldInternalProps } from '../useField'; import { Validator } from '../../../validation'; import { WrapperVariant } from '../../models/common'; import { - FieldSection, FieldValueType, TimezoneProps, MuiPickersAdapter, @@ -17,73 +16,85 @@ import { PickerShortcutChangeImportance, PickersShortcutsItemContext, } from '../../../PickersShortcuts'; +import { InferNonNullablePickerValue, InferPickerValue } from '../../models'; -export interface PickerValueManager { +export interface PickerValueManager { /** * Determines if two values are equal. - * @template TValue + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @param {MuiPickersAdapter} utils The adapter. - * @param {TValue} valueLeft The first value to compare. - * @param {TValue} valueRight The second value to compare. + * @param {InferPickerValue} valueLeft The first value to compare. + * @param {InferPickerValue} valueRight The second value to compare. * @returns {boolean} A boolean indicating if the two values are equal. */ - areValuesEqual: (utils: MuiPickersAdapter, valueLeft: TValue, valueRight: TValue) => boolean; + areValuesEqual: ( + utils: MuiPickersAdapter, + valueLeft: InferPickerValue, + valueRight: InferPickerValue, + ) => boolean; /** * Value to set when clicking the "Clear" button. */ - emptyValue: TValue; + emptyValue: InferPickerValue; /** * Method returning the value to set when clicking the "Today" button - * @template TValue + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @param {MuiPickersAdapter} utils The adapter. * @param {PickersTimezone} timezone The current timezone. * @param {FieldValueType} valueType The type of the value being edited. - * @returns {TValue} The value to set when clicking the "Today" button. + * @returns {InferPickerValue} The value to set when clicking the "Today" button. */ getTodayValue: ( utils: MuiPickersAdapter, timezone: PickersTimezone, valueType: FieldValueType, - ) => TValue; + ) => InferPickerValue; /** - * @template TValue + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * Method returning the reference value to use when mounting the component. * @param {object} params The params of the method. * @param {PickerValidDate | undefined} params.referenceDate The referenceDate provided by the user. - * @param {TValue} params.value The value provided by the user. + * @param {InferPickerValue} params.value The value provided by the user. * @param {GetDefaultReferenceDateProps} params.props The validation props needed to compute the reference value. * @param {MuiPickersAdapter} params.utils The adapter. * @param {number} params.granularity The granularity of the selection possible on this component. * @param {PickersTimezone} params.timezone The current timezone. * @param {() => PickerValidDate} params.getTodayDate The reference date to use if no reference date is passed to the component. - * @returns {TValue} The reference value to use for non-provided dates. + * @returns {InferPickerValue} The reference value to use for non-provided dates. */ getInitialReferenceValue: (params: { referenceDate: PickerValidDate | undefined; - value: TValue; + value: InferPickerValue; props: GetDefaultReferenceDateProps; utils: MuiPickersAdapter; granularity: number; timezone: PickersTimezone; getTodayDate?: () => PickerValidDate; - }) => TValue; + }) => InferNonNullablePickerValue; /** * Method parsing the input value to replace all invalid dates by `null`. - * @template TValue + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @param {MuiPickersAdapter} utils The adapter. - * @param {TValue} value The value to parse. - * @returns {TValue} The value without invalid date. + * @param {InferPickerValue} value The value to parse. + * @returns {InferPickerValue} The value without invalid date. */ - cleanValue: (utils: MuiPickersAdapter, value: TValue) => TValue; + cleanValue: ( + utils: MuiPickersAdapter, + value: InferPickerValue, + ) => InferPickerValue; /** * Generates the new value, given the previous value and the new proposed value. - * @template TValue + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @param {MuiPickersAdapter} utils The adapter. - * @param {TValue} lastValidDateValue The last valid value. - * @param {TValue} value The proposed value. - * @returns {TValue} The new value. + * @param {InferPickerValue} lastValidDateValue The last valid value. + * @param {InferPickerValue} value The proposed value. + * @returns {InferPickerValue} The new value. */ - valueReducer?: (utils: MuiPickersAdapter, lastValidDateValue: TValue, value: TValue) => TValue; + valueReducer?: ( + utils: MuiPickersAdapter, + lastValidDateValue: InferPickerValue, + value: InferPickerValue, + ) => InferPickerValue; /** * Compare two errors to know if they are equal. * @template TError @@ -106,46 +117,50 @@ export interface PickerValueManager { /** * Return the timezone of the date inside a value. * Throw an error on range picker if both values don't have the same timezone. - @template TValue + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. @param {MuiPickersAdapter} utils The utils to manipulate the date. - @param {TValue} value The current value. + @param {InferPickerValue} value The current value. @returns {string | null} The timezone of the current value. */ - getTimezone: (utils: MuiPickersAdapter, value: TValue) => string | null; + getTimezone: (utils: MuiPickersAdapter, value: InferPickerValue) => string | null; /** * Change the timezone of the dates inside a value. - @template TValue + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. @param {MuiPickersAdapter} utils The utils to manipulate the date. @param {PickersTimezone} timezone The current timezone. - @param {TValue} value The value to convert. - @returns {TValue} The value with the new dates in the new timezone. + @param {InferPickerValue} value The value to convert. + @returns {InferPickerValue} The value with the new dates in the new timezone. */ - setTimezone: (utils: MuiPickersAdapter, timezone: PickersTimezone, value: TValue) => TValue; + setTimezone: ( + utils: MuiPickersAdapter, + timezone: PickersTimezone, + value: InferPickerValue, + ) => InferPickerValue; } export type PickerSelectionState = 'partial' | 'shallow' | 'finish'; -export interface UsePickerValueState { +export interface UsePickerValueState { /** * Date displayed on the views and the field. * It is updated whenever the user modifies something. */ - draft: TValue; + draft: InferPickerValue; /** * Last value published (e.g: the last value for which `shouldPublishValue` returned `true`). * If `onChange` is defined, it's the value that was passed on the last call to this callback. */ - lastPublishedValue: TValue; + lastPublishedValue: InferPickerValue; /** * Last value committed (e.g: the last value for which `shouldCommitValue` returned `true`). * If `onAccept` is defined, it's the value that was passed on the last call to this callback. */ - lastCommittedValue: TValue; + lastCommittedValue: InferPickerValue; /** * Last value passed with `props.value`. * Used to update the `draft` value whenever the `value` prop changes. */ - lastControlledValue: TValue | undefined; + lastControlledValue: InferPickerValue | undefined; /** * If we never modified the value since the mount of the component, * Then we might want to apply some custom logic. @@ -156,39 +171,39 @@ export interface UsePickerValueState { hasBeenModifiedSinceMount: boolean; } -export interface PickerValueUpdaterParams { - action: PickerValueUpdateAction; - dateState: UsePickerValueState; +export interface PickerValueUpdaterParams { + action: PickerValueUpdateAction; + dateState: UsePickerValueState; /** * Check if the new draft value has changed compared to some given value. - * @template TValue - * @param {TValue} comparisonValue The value to compare the new draft value with. + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. + * @param {InferPickerValue} comparisonValue The value to compare the new draft value with. * @returns {boolean} `true` if the new draft value is equal to the comparison value. */ - hasChanged: (comparisonValue: TValue) => boolean; + hasChanged: (comparisonValue: InferPickerValue) => boolean; isControlled: boolean; closeOnSelect: boolean; } -export type PickerValueUpdateAction = +export type PickerValueUpdateAction = | { name: 'setValueFromView'; - value: TValue; + value: InferPickerValue; selectionState: PickerSelectionState; } | { name: 'setValueFromField'; - value: TValue; + value: InferPickerValue; context: FieldChangeHandlerContext; } | { name: 'setValueFromAction'; - value: TValue; + value: InferPickerValue; pickerAction: 'accept' | 'today' | 'cancel' | 'dismiss' | 'clear'; } | { name: 'setValueFromShortcut'; - value: TValue; + value: InferPickerValue; changeImportance: PickerShortcutChangeImportance; shortcut: PickersShortcutsItemContext; }; @@ -196,33 +211,40 @@ export type PickerValueUpdateAction = /** * Props used to handle the value that are common to all pickers. */ -export interface UsePickerValueBaseProps extends OnErrorProps { +export interface UsePickerValueBaseProps + extends OnErrorProps { /** * The selected value. * Used when the component is controlled. */ - value?: TValue; + value?: InferPickerValue; /** * The default value. * Used when the component is not controlled. */ - defaultValue?: TValue; + defaultValue?: InferPickerValue; /** * Callback fired when the value changes. - * @template TValue The value type. It will be the same type as `value` or `null`. It can be in `[start, end]` format in case of range value. + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @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 {TValue} value The new value. + * @param {InferPickerValue} value The new value. * @param {FieldChangeHandlerContext} context The context containing the validation result of the current value. */ - onChange?: (value: TValue, context: PickerChangeHandlerContext) => void; + onChange?: ( + value: InferPickerValue, + context: PickerChangeHandlerContext, + ) => void; /** * Callback fired when the value is accepted. - * @template TValue The value type. It will be the same type as `value` or `null`. It can be in `[start, end]` format in case of range value. + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @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 {TValue} value The value that was just accepted. + * @param {InferPickerValue} value The value that was just accepted. * @param {FieldChangeHandlerContext} context The context containing the validation result of the current value. */ - onAccept?: (value: TValue, context: PickerChangeHandlerContext) => void; + onAccept?: ( + value: InferPickerValue, + context: PickerChangeHandlerContext, + ) => void; } /** @@ -254,20 +276,20 @@ export interface UsePickerValueNonStaticProps { /** * Props used to handle the value of the pickers. */ -export interface UsePickerValueProps - extends UsePickerValueBaseProps, +export interface UsePickerValueProps + extends UsePickerValueBaseProps, UsePickerValueNonStaticProps, TimezoneProps {} export interface UsePickerValueParams< - TValue, - TExternalProps extends UsePickerValueProps, + TIsRange extends boolean, + TExternalProps extends UsePickerValueProps, > { props: TExternalProps; - valueManager: PickerValueManager>; + valueManager: PickerValueManager>; valueType: FieldValueType; wrapperVariant: WrapperVariant; - validator: Validator, TExternalProps>; + validator: Validator, TExternalProps>; } export interface UsePickerValueActions { @@ -280,16 +302,16 @@ export interface UsePickerValueActions { onClose: (event?: React.UIEvent) => void; } -export type UsePickerValueFieldResponse = Required< - Pick, 'value' | 'onChange'> +export type UsePickerValueFieldResponse = Required< + Pick, 'value' | 'onChange'> >; /** * Props passed to `usePickerViews`. */ -export interface UsePickerValueViewsResponse { - value: TValue; - onChange: (value: TValue, selectionState?: PickerSelectionState) => void; +export interface UsePickerValueViewsResponse { + value: InferPickerValue; + onChange: (value: InferPickerValue, selectionState?: PickerSelectionState) => void; open: boolean; onClose: (event?: React.MouseEvent) => void; } @@ -297,21 +319,22 @@ export interface UsePickerValueViewsResponse { /** * Props passed to `usePickerLayoutProps`. */ -export interface UsePickerValueLayoutResponse extends UsePickerValueActions { - value: TValue; - onChange: (newValue: TValue) => void; +export interface UsePickerValueLayoutResponse + extends UsePickerValueActions { + value: InferPickerValue; + onChange: (newValue: InferPickerValue) => void; onSelectShortcut: ( - newValue: TValue, + newValue: InferPickerValue, changeImportance: PickerShortcutChangeImportance, shortcut: PickersShortcutsItemContext, ) => void; - isValid: (value: TValue) => boolean; + isValid: (value: InferPickerValue) => boolean; } -export interface UsePickerValueResponse { +export interface UsePickerValueResponse { open: boolean; actions: UsePickerValueActions; - viewProps: UsePickerValueViewsResponse; - fieldProps: UsePickerValueFieldResponse; - layoutProps: UsePickerValueLayoutResponse; + viewProps: UsePickerValueViewsResponse; + fieldProps: UsePickerValueFieldResponse; + layoutProps: UsePickerValueLayoutResponse; } diff --git a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerViews.ts b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerViews.ts index 44c47ddc696d..c3c841d5f3d9 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerViews.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerViews.ts @@ -7,19 +7,19 @@ import { useViews, UseViewsOptions } from '../useViews'; import type { UsePickerValueViewsResponse } from './usePickerValue.types'; import { isTimeView } from '../../utils/time-utils'; import { DateOrTimeViewWithMeridiem } from '../../models'; -import { FieldRef, FieldSection, PickerValidDate, TimezoneProps } from '../../../models'; +import { FieldRef, PickerValidDate, TimezoneProps } from '../../../models'; interface PickerViewsRendererBaseExternalProps extends Omit, 'openTo' | 'viewRenderers'> {} export type PickerViewsRendererProps< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, TExternalProps extends PickerViewsRendererBaseExternalProps, TAdditionalProps extends {}, > = Omit & TAdditionalProps & - UsePickerValueViewsResponse & { + UsePickerValueViewsResponse & { view: TView; views: readonly TView[]; focusedView: TView | null; @@ -29,30 +29,30 @@ export type PickerViewsRendererProps< }; export type PickerViewRenderer< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, TExternalProps extends PickerViewsRendererBaseExternalProps, TAdditionalProps extends {}, > = ( - props: PickerViewsRendererProps, + props: PickerViewsRendererProps, ) => React.ReactNode; export type PickerViewRendererLookup< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, TExternalProps extends PickerViewsRendererBaseExternalProps, TAdditionalProps extends {}, > = { - [K in TView]: PickerViewRenderer | null; + [K in TView]: PickerViewRenderer | null; }; /** * Props used to handle the views that are common to all pickers. */ export interface UsePickerViewsBaseProps< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, - TExternalProps extends UsePickerViewsProps, + TExternalProps extends UsePickerViewsProps, TAdditionalProps extends {}, > extends Omit, 'onChange' | 'onFocusedViewChange' | 'focusedView'>, TimezoneProps { @@ -65,7 +65,7 @@ export interface UsePickerViewsBaseProps< * If `null`, the section will only have field editing. * If `undefined`, internally defined view will be used. */ - viewRenderers: PickerViewRendererLookup; + viewRenderers: PickerViewRendererLookup; /** * If `true`, disable heavy animations. * @default `@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13 @@ -93,39 +93,38 @@ export interface UsePickerViewsNonStaticProps { * Props used to handle the value of the pickers. */ export interface UsePickerViewsProps< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, - TExternalProps extends UsePickerViewsProps, + TExternalProps extends UsePickerViewsProps, TAdditionalProps extends {}, -> extends UsePickerViewsBaseProps { +> extends UsePickerViewsBaseProps { className?: string; sx?: SxProps; } export interface UsePickerViewParams< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, - TSection extends FieldSection, - TExternalProps extends UsePickerViewsProps, + TExternalProps extends UsePickerViewsProps, TAdditionalProps extends {}, > { props: TExternalProps; - propsFromPickerValue: UsePickerValueViewsResponse; + propsFromPickerValue: UsePickerValueViewsResponse; additionalViewProps: TAdditionalProps; autoFocusView: boolean; - fieldRef: React.RefObject> | undefined; + fieldRef: React.RefObject> | undefined; /** * A function that intercepts the regular picker rendering. * Can be used to consume the provided `viewRenderers` and render a custom component wrapping them. - * @param {PickerViewRendererLookup} viewRenderers The `viewRenderers` that were provided to the picker component. + * @param {PickerViewRendererLookup} viewRenderers The `viewRenderers` that were provided to the picker component. * @param {TView} popperView The current picker view. * @param {any} rendererProps All the props that are being passed down to the renderer. * @returns {React.ReactNode} A React node that will be rendered instead of the default renderer. */ rendererInterceptor?: ( - viewRenderers: PickerViewRendererLookup, + viewRenderers: PickerViewRendererLookup, popperView: TView, - rendererProps: PickerViewsRendererProps, + rendererProps: PickerViewsRendererProps, ) => React.ReactNode; } @@ -152,10 +151,9 @@ export interface UsePickerViewsLayoutResponse, + TExternalProps extends UsePickerViewsProps, TAdditionalProps extends {}, >({ props, @@ -165,9 +163,8 @@ export const usePickerViews = < rendererInterceptor, fieldRef, }: UsePickerViewParams< - TValue, + TIsRange, TView, - TSection, TExternalProps, TAdditionalProps >): UsePickerViewsResponse => { @@ -290,7 +287,7 @@ export const usePickerViews = < } const rendererProps: PickerViewsRendererProps< - TValue, + TIsRange, TView, TExternalProps, TAdditionalProps diff --git a/packages/x-date-pickers/src/internals/hooks/useStaticPicker/useStaticPicker.tsx b/packages/x-date-pickers/src/internals/hooks/useStaticPicker/useStaticPicker.tsx index 38dc4787f8d1..da4300cdfce6 100644 --- a/packages/x-date-pickers/src/internals/hooks/useStaticPicker/useStaticPicker.tsx +++ b/packages/x-date-pickers/src/internals/hooks/useStaticPicker/useStaticPicker.tsx @@ -6,7 +6,6 @@ import { usePicker } from '../usePicker'; import { PickersProvider } from '../../components/PickersProvider'; import { PickersLayout } from '../../../PickersLayout'; import { DIALOG_WIDTH } from '../../constants/dimensions'; -import { FieldSection, PickerValidDate } from '../../../models'; import { DateOrTimeViewWithMeridiem } from '../../models'; const PickerStaticLayout = styled(PickersLayout)(({ theme }) => ({ @@ -32,9 +31,8 @@ export const useStaticPicker = < const { localeText, slots, slotProps, className, sx, displayStaticWrapperAs, autoFocus } = props; const { layoutProps, providerProps, renderCurrentView } = usePicker< - PickerValidDate | null, + false, TView, - FieldSection, TExternalProps, {} >({ diff --git a/packages/x-date-pickers/src/internals/hooks/useStaticPicker/useStaticPicker.types.ts b/packages/x-date-pickers/src/internals/hooks/useStaticPicker/useStaticPicker.types.ts index 0b2af3ccd50d..a72efbd8592e 100644 --- a/packages/x-date-pickers/src/internals/hooks/useStaticPicker/useStaticPicker.types.ts +++ b/packages/x-date-pickers/src/internals/hooks/useStaticPicker/useStaticPicker.types.ts @@ -6,14 +6,13 @@ import { import { BasePickerProps } from '../../models/props/basePickerProps'; import { UsePickerParams } from '../usePicker'; import { UsePickerViewsProps } from '../usePicker/usePickerViews'; -import { FieldSection, PickerValidDate } from '../../../models'; import { DateOrTimeViewWithMeridiem } from '../../models'; export interface UseStaticPickerSlots - extends ExportedPickersLayoutSlots {} + extends ExportedPickersLayoutSlots {} export interface UseStaticPickerSlotProps - extends ExportedPickersLayoutSlotProps {} + extends ExportedPickersLayoutSlotProps {} export interface StaticOnlyPickerProps { /** @@ -37,8 +36,8 @@ export interface StaticOnlyPickerProps { export interface UseStaticPickerProps< TView extends DateOrTimeViewWithMeridiem, TError, - TExternalProps extends UsePickerViewsProps, -> extends BasePickerProps, + TExternalProps extends UsePickerViewsProps, +> extends BasePickerProps, StaticOnlyPickerProps { /** * Overridable component slots. @@ -56,7 +55,7 @@ export interface UseStaticPickerParams< TView extends DateOrTimeViewWithMeridiem, TExternalProps extends UseStaticPickerProps, > extends Pick< - UsePickerParams, + UsePickerParams, 'valueManager' | 'valueType' | 'validator' > { props: TExternalProps; diff --git a/packages/x-date-pickers/src/internals/hooks/useValueWithTimezone.ts b/packages/x-date-pickers/src/internals/hooks/useValueWithTimezone.ts index f16b6f51410d..a0ef4482a46f 100644 --- a/packages/x-date-pickers/src/internals/hooks/useValueWithTimezone.ts +++ b/packages/x-date-pickers/src/internals/hooks/useValueWithTimezone.ts @@ -4,13 +4,17 @@ import useControlled from '@mui/utils/useControlled'; import { useUtils } from './useUtils'; import type { PickerValueManager } from './usePicker'; import { PickersTimezone } from '../../models'; +import { InferPickerValue } from '../models'; /** * Hooks making sure that: * - The value returned by `onChange` always have the timezone of `props.value` or `props.defaultValue` if defined * - The value rendered is always the one from `props.timezone` if defined */ -export const useValueWithTimezone = void>({ +export const useValueWithTimezone = < + TIsRange extends boolean, + TChange extends (...params: any[]) => void, +>({ timezone: timezoneProp, value: valueProp, defaultValue, @@ -18,10 +22,10 @@ export const useValueWithTimezone = | undefined; + defaultValue: InferPickerValue | undefined; onChange: TChange | undefined; - valueManager: PickerValueManager; + valueManager: PickerValueManager; }) => { const utils = useUtils(); @@ -33,7 +37,7 @@ export const useValueWithTimezone = { + const setInputTimezone = useEventCallback((newValue: InferPickerValue) => { if (inputTimezone == null) { return newValue; } @@ -48,10 +52,12 @@ export const useValueWithTimezone = { - const newValueWithInputTimezone = setInputTimezone(newValue); - onChange?.(newValueWithInputTimezone, ...otherParams); - }) as TChange; + const handleValueChange = useEventCallback( + (newValue: InferPickerValue, ...otherParams: any[]) => { + const newValueWithInputTimezone = setInputTimezone(newValue); + onChange?.(newValueWithInputTimezone, ...otherParams); + }, + ) as TChange; return { value: valueWithTimezoneToRender, handleValueChange, timezone: timezoneToRender }; }; @@ -59,7 +65,10 @@ export const useValueWithTimezone = void>({ +export const useControlledValueWithTimezone = < + TIsRange extends boolean, + TChange extends (...params: any[]) => void, +>({ name, timezone: timezoneProp, value: valueProp, @@ -69,10 +78,10 @@ export const useControlledValueWithTimezone = | undefined; + defaultValue: InferPickerValue | undefined; onChange: TChange | undefined; - valueManager: PickerValueManager; + valueManager: PickerValueManager; }) => { const [valueWithInputTimezone, setValue] = useControlled({ name, @@ -81,10 +90,12 @@ export const useControlledValueWithTimezone = { - setValue(newValue); - onChangeProp?.(newValue, ...otherParams); - }) as TChange; + const onChange = useEventCallback( + (newValue: InferPickerValue, ...otherParams: any[]) => { + setValue(newValue); + onChangeProp?.(newValue, ...otherParams); + }, + ) as TChange; return useValueWithTimezone({ timezone: timezoneProp, diff --git a/packages/x-date-pickers/src/internals/hooks/useViews.tsx b/packages/x-date-pickers/src/internals/hooks/useViews.tsx index cf72cc620f30..a493cc36553c 100644 --- a/packages/x-date-pickers/src/internals/hooks/useViews.tsx +++ b/packages/x-date-pickers/src/internals/hooks/useViews.tsx @@ -3,7 +3,7 @@ import useEventCallback from '@mui/utils/useEventCallback'; import useControlled from '@mui/utils/useControlled'; import { MakeOptional } from '@mui/x-internals/types'; import type { PickerSelectionState } from './usePicker'; -import { DateOrTimeViewWithMeridiem } from '../models'; +import { DateOrTimeViewWithMeridiem, InferPickerValue } from '../models'; import { PickerValidDate } from '../../models'; export type PickerOnChangeFn = ( @@ -11,16 +11,23 @@ export type PickerOnChangeFn = ( selectionState?: PickerSelectionState, ) => void; -export interface UseViewsOptions { +export interface UseViewsOptions< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> { /** * Callback fired when the value changes. - * @template TValue The value type. It will be the same type as `value` or `null`. It can be in `[start, end]` format in case of range value. + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @template TView The view type. Will be one of date or time views. - * @param {TValue} value The new value. + * @param {InferPickerValue} value The new value. * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete. * @param {TView | undefined} selectedView Indicates the view in which the selection has been made. */ - onChange: (value: TValue, selectionState?: PickerSelectionState, selectedView?: TView) => void; + onChange: ( + value: InferPickerValue, + selectionState?: PickerSelectionState, + selectedView?: TView, + ) => void; /** * Callback fired on view change. * @template TView @@ -63,12 +70,14 @@ export interface UseViewsOptions void; } -export interface ExportedUseViewsOptions - extends MakeOptional, 'onChange' | 'openTo' | 'views'> {} +export interface ExportedUseViewsOptions< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> extends MakeOptional, 'onChange' | 'openTo' | 'views'> {} let warnedOnceNotValidView = false; -interface UseViewsResponse { +interface UseViewsResponse { view: TView; setView: (view: TView) => void; focusedView: TView | null; @@ -78,13 +87,13 @@ interface UseViewsResponse { defaultView: TView; goToNextView: () => void; setValueAndGoToNextView: ( - value: TValue, + value: InferPickerValue, currentViewSelectionState?: PickerSelectionState, selectedView?: TView, ) => void; } -export function useViews({ +export function useViews({ onChange, onViewChange, openTo, @@ -93,7 +102,7 @@ export function useViews({ autoFocus, focusedView: inFocusedView, onFocusedViewChange, -}: UseViewsOptions): UseViewsResponse { +}: UseViewsOptions): UseViewsResponse { if (process.env.NODE_ENV !== 'production') { if (!warnedOnceNotValidView) { if (inView != null && !views.includes(inView)) { @@ -182,7 +191,11 @@ export function useViews({ }); const setValueAndGoToNextView = useEventCallback( - (value: TValue, currentViewSelectionState?: PickerSelectionState, selectedView?: TView) => { + ( + value: InferPickerValue, + currentViewSelectionState?: PickerSelectionState, + selectedView?: TView, + ) => { const isSelectionFinishedOnCurrentView = currentViewSelectionState === 'finish'; const hasMoreViews = selectedView ? // handles case like `DateTimePicker`, where a view might return a `finish` selection state diff --git a/packages/x-date-pickers/src/internals/index.ts b/packages/x-date-pickers/src/internals/index.ts index 11a6e4657b7f..316f108a5ea9 100644 --- a/packages/x-date-pickers/src/internals/index.ts +++ b/packages/x-date-pickers/src/internals/index.ts @@ -96,6 +96,7 @@ export { useViews } from './hooks/useViews'; export { usePreviousMonthDisabled, useNextMonthDisabled } from './hooks/date-helpers-hooks'; export type { BaseFieldProps } from './models/fields'; +export type { RangePosition } from './models/pickers'; export type { BasePickerProps, BasePickerInputProps, @@ -118,7 +119,7 @@ export type { DayValidationProps, DateTimeValidationProps, } from './models/validation'; -export type { PickerRangeValue } from './models/value'; +export type { PickerRangeValue, PickerNonNullableRangeValue } from './models/value'; export { convertFieldResponseIntoMuiTextFieldProps } from './utils/convertFieldResponseIntoMuiTextFieldProps'; export { diff --git a/packages/x-date-pickers/src/internals/models/fields.ts b/packages/x-date-pickers/src/internals/models/fields.ts index f31216d2f8c7..cd3de4f99ba2 100644 --- a/packages/x-date-pickers/src/internals/models/fields.ts +++ b/packages/x-date-pickers/src/internals/models/fields.ts @@ -1,15 +1,14 @@ import * as React from 'react'; import type { UseFieldInternalProps } from '../hooks/useField'; -import { FieldSection, PickerOwnerState } from '../../models'; +import { PickerOwnerState } from '../../models'; import type { ExportedUseClearableFieldProps } from '../../hooks/useClearableField'; export interface BaseFieldProps< - TValue, - TSection extends FieldSection, + TIsRange extends boolean, TEnableAccessibleFieldDOMStructure extends boolean, TError, > extends Omit< - UseFieldInternalProps, + UseFieldInternalProps, 'format' >, ExportedUseClearableFieldProps { diff --git a/packages/x-date-pickers/src/internals/models/pickers.ts b/packages/x-date-pickers/src/internals/models/pickers.ts new file mode 100644 index 000000000000..ff214a929bb7 --- /dev/null +++ b/packages/x-date-pickers/src/internals/models/pickers.ts @@ -0,0 +1 @@ +export type RangePosition = 'start' | 'end'; diff --git a/packages/x-date-pickers/src/internals/models/props/basePickerProps.tsx b/packages/x-date-pickers/src/internals/models/props/basePickerProps.tsx index c271a5322988..1a72e6c59ba2 100644 --- a/packages/x-date-pickers/src/internals/models/props/basePickerProps.tsx +++ b/packages/x-date-pickers/src/internals/models/props/basePickerProps.tsx @@ -12,12 +12,12 @@ import { UseFieldInternalProps } from '../../hooks/useField'; * Props common to all pickers after applying the default props on each picker. */ export interface BasePickerProps< - TValue, + TIsRange extends boolean, TView extends DateOrTimeViewWithMeridiem, TError, - TExternalProps extends UsePickerViewsProps, + TExternalProps extends UsePickerViewsProps, TAdditionalProps extends {}, -> extends UsePickerBaseProps { +> extends UsePickerBaseProps { className?: string; /** * The system prop that allows defining system overrides as well as additional CSS styles. @@ -33,9 +33,12 @@ export interface BasePickerProps< /** * Props common to all pickers before applying the default props on each picker. */ -export interface BasePickerInputProps - extends Omit< - MakeOptional, 'openTo' | 'views'>, +export interface BasePickerInputProps< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, + TError, +> extends Omit< + MakeOptional, 'openTo' | 'views'>, 'viewRenderers' > {} @@ -46,7 +49,7 @@ export interface BasePickerInputProps, + UseFieldInternalProps, | 'formatDensity' | 'enableAccessibleFieldDOMStructure' | 'selectedSections' diff --git a/packages/x-date-pickers/src/internals/models/props/time.ts b/packages/x-date-pickers/src/internals/models/props/time.ts index 2d30d90a4704..c08d8c8ecfcf 100644 --- a/packages/x-date-pickers/src/internals/models/props/time.ts +++ b/packages/x-date-pickers/src/internals/models/props/time.ts @@ -20,7 +20,7 @@ export interface ExportedBaseClockProps AmPmProps {} export interface BaseClockProps - extends ExportedUseViewsOptions, + extends ExportedUseViewsOptions, ExportedBaseClockProps { className?: string; /** diff --git a/packages/x-date-pickers/src/internals/models/props/toolbar.ts b/packages/x-date-pickers/src/internals/models/props/toolbar.ts index e4791d572f7c..7bf8221f28a1 100644 --- a/packages/x-date-pickers/src/internals/models/props/toolbar.ts +++ b/packages/x-date-pickers/src/internals/models/props/toolbar.ts @@ -2,12 +2,15 @@ import * as React from 'react'; import { SxProps } from '@mui/system'; import { Theme } from '@mui/material/styles'; import { DateOrTimeViewWithMeridiem } from '../common'; +import { InferPickerValue } from '../value'; -export interface BaseToolbarProps - extends ExportedBaseToolbarProps { +export interface BaseToolbarProps< + TIsRange extends boolean, + TView extends DateOrTimeViewWithMeridiem, +> extends ExportedBaseToolbarProps { isLandscape: boolean; - onChange: (newValue: TValue) => void; - value: TValue; + onChange: (newValue: InferPickerValue) => void; + value: InferPickerValue; /** * Currently visible picker view. */ diff --git a/packages/x-date-pickers/src/internals/models/value.ts b/packages/x-date-pickers/src/internals/models/value.ts index 7429c2df5c39..371c126d3c76 100644 --- a/packages/x-date-pickers/src/internals/models/value.ts +++ b/packages/x-date-pickers/src/internals/models/value.ts @@ -3,3 +3,17 @@ import { PickerValidDate } from '../../models/pickers'; export type PickerValue = PickerValidDate | null; export type PickerRangeValue = [PickerValidDate | null, PickerValidDate | null]; + +export type PickerNonNullableRangeValue = [PickerValidDate, PickerValidDate]; + +export type InferPickerValue = TIsRange extends true + ? TIsRange extends false + ? PickerValue | PickerRangeValue + : PickerRangeValue + : PickerValue; + +export type InferNonNullablePickerValue = TIsRange extends true + ? TIsRange extends false + ? PickerValidDate | PickerNonNullableRangeValue + : PickerNonNullableRangeValue + : PickerValidDate; diff --git a/packages/x-date-pickers/src/internals/utils/date-utils.ts b/packages/x-date-pickers/src/internals/utils/date-utils.ts index 08c294e0bc23..b99c46a3948a 100644 --- a/packages/x-date-pickers/src/internals/utils/date-utils.ts +++ b/packages/x-date-pickers/src/internals/utils/date-utils.ts @@ -110,7 +110,11 @@ export const applyDefaultDate = ( return value; }; -export const areDatesEqual = (utils: MuiPickersAdapter, a: PickerValidDate, b: PickerValidDate) => { +export const areDatesEqual = ( + utils: MuiPickersAdapter, + a: PickerValidDate | null, + b: PickerValidDate | null, +) => { if (!utils.isValid(a) && a != null && !utils.isValid(b) && b != null) { return true; } diff --git a/packages/x-date-pickers/src/internals/utils/valueManagers.ts b/packages/x-date-pickers/src/internals/utils/valueManagers.ts index 3e507fe925c1..5c476694b18a 100644 --- a/packages/x-date-pickers/src/internals/utils/valueManagers.ts +++ b/packages/x-date-pickers/src/internals/utils/valueManagers.ts @@ -1,10 +1,5 @@ import type { PickerValueManager } from '../hooks/usePicker'; -import { - DateValidationError, - TimeValidationError, - DateTimeValidationError, - FieldSection, -} from '../../models'; +import { DateValidationError, TimeValidationError, DateTimeValidationError } from '../../models'; import type { FieldValueManager } from '../hooks/useField'; import { areDatesEqual, getTodayDate, replaceInvalidDateByNull } from './date-utils'; import { getDefaultReferenceDate } from './getDefaultReferenceDate'; @@ -14,9 +9,8 @@ import { } from '../hooks/useField/useField.utils'; export type SingleItemPickerValueManager< - TValue = any, TError extends DateValidationError | TimeValidationError | DateTimeValidationError = any, -> = PickerValueManager; +> = PickerValueManager; export const singleItemValueManager: SingleItemPickerValueManager = { emptyValue: null, @@ -43,7 +37,7 @@ export const singleItemValueManager: SingleItemPickerValueManager = { value == null ? null : utils.setTimezone(value, timezone), }; -export const singleItemFieldValueManager: FieldValueManager = { +export const singleItemFieldValueManager: FieldValueManager = { updateReferenceValue: (utils, value, prevReferenceValue) => value == null || !utils.isValid(value) ? prevReferenceValue : value, getSectionsFromValue: (utils, date, prevSections, getSectionsFromDate) => { @@ -53,7 +47,7 @@ export const singleItemFieldValueManager: FieldValueManager = return prevSections; } - return getSectionsFromDate(date); + return getSectionsFromDate(date!); }, getV7HiddenInputValueFromSections: createDateStrForV7HiddenInputFromSections, getV6InputValueFromSections: createDateStrForV6InputFromSections, diff --git a/packages/x-date-pickers/src/models/fields.ts b/packages/x-date-pickers/src/models/fields.ts index 9d853e8d2ed8..c777fbaf0d1f 100644 --- a/packages/x-date-pickers/src/models/fields.ts +++ b/packages/x-date-pickers/src/models/fields.ts @@ -11,6 +11,7 @@ import type { import { ExportedPickersSectionListProps, PickersSectionListRef } from '../PickersSectionList'; import type { UseFieldResponse } from '../internals/hooks/useField'; import type { PickersTextFieldProps } from '../PickersTextField'; +import { RangePosition } from '../internals/models/pickers'; // Update PickersComponentAgnosticLocaleText -> viewNames when adding new entries export type FieldSectionType = @@ -91,12 +92,22 @@ export interface FieldSection { endSeparator: string; } -export interface FieldRef { +export interface FieldRangeSection extends FieldSection { + dateName: RangePosition; +} + +export type InferFieldSection = TIsRange extends true + ? TIsRange extends false + ? FieldSection | FieldRangeSection + : FieldRangeSection + : FieldSection; + +export interface FieldRef { /** * Returns the sections of the current value. - * @returns {TSection[]} The sections of the current value. + * @returns {InferFieldSection[]} The sections of the current value. */ - getSections: () => TSection[]; + getSections: () => InferFieldSection[]; /** * Returns the index of the active section (the first focused section). * If no section is active, returns `null`. @@ -165,11 +176,10 @@ type BaseForwardedSingleInputFieldProps = BaseFieldProps & +> = BaseFieldProps & BaseForwardedSingleInputFieldProps; /** diff --git a/packages/x-date-pickers/src/models/validation.ts b/packages/x-date-pickers/src/models/validation.ts index 5dcee050db5f..e81743554a38 100644 --- a/packages/x-date-pickers/src/models/validation.ts +++ b/packages/x-date-pickers/src/models/validation.ts @@ -1,3 +1,5 @@ +import type { InferPickerValue } from '../internals/models'; + /** * Validation error types applicable to both date and time validation */ @@ -22,17 +24,17 @@ export type TimeValidationError = export type DateTimeValidationError = DateValidationError | TimeValidationError; -export interface OnErrorProps { +export interface OnErrorProps { /** * Callback fired when the error associated with 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. It will be either `string` or a `null`. It can be in `[start, end]` format in case of range value. - * @template TValue The value type. It will be the same type as `value` or `null`. It can be in `[start, end]` format in case of range value. + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. * @param {TError} error The reason why the current value is not valid. - * @param {TValue} value The value associated with the error. + * @param {InferPickerValue} value The value associated with the error. */ - onError?: (error: TError, value: TValue) => void; + onError?: (error: TError, value: InferPickerValue) => void; } export type InferError = diff --git a/packages/x-date-pickers/src/themeAugmentation/props.d.ts b/packages/x-date-pickers/src/themeAugmentation/props.d.ts index 9fb69436bbad..19c3066219df 100644 --- a/packages/x-date-pickers/src/themeAugmentation/props.d.ts +++ b/packages/x-date-pickers/src/themeAugmentation/props.d.ts @@ -77,10 +77,10 @@ export interface PickersComponentsPropsList { MuiPickersMonth: ExportedPickersMonthProps; MuiPickersPopper: PickerPopperProps; MuiPickersSlideTransition: ExportedSlideTransitionProps; - MuiPickersToolbar: PickersToolbarProps; + MuiPickersToolbar: PickersToolbarProps; MuiPickersToolbarButton: PickersToolbarButtonProps; MuiPickersToolbarText: ExportedPickersToolbarTextProps; - MuiPickersLayout: PickersLayoutProps; + MuiPickersLayout: PickersLayoutProps; MuiPickersYear: ExportedPickersYearProps; MuiTimeClock: TimeClockProps; MuiTimeField: TimeFieldProps; diff --git a/packages/x-date-pickers/src/validation/useValidation.ts b/packages/x-date-pickers/src/validation/useValidation.ts index b09787bed9f0..598b7af37787 100644 --- a/packages/x-date-pickers/src/validation/useValidation.ts +++ b/packages/x-date-pickers/src/validation/useValidation.ts @@ -5,23 +5,24 @@ import { useLocalizationContext } from '../internals/hooks/useUtils'; import { MuiPickersAdapterContextValue } from '../LocalizationProvider/LocalizationProvider'; import { OnErrorProps, PickersTimezone } from '../models'; import type { PickerValueManager } from '../internals/hooks/usePicker'; +import { InferPickerValue } from '../internals/models'; -export type Validator = { +export type Validator = { (params: { adapter: MuiPickersAdapterContextValue; - value: TValue; + value: InferPickerValue; timezone: PickersTimezone; props: TValidationProps; }): TError; - valueManager: PickerValueManager; + valueManager: PickerValueManager; }; -interface UseValidationOptions - extends OnErrorProps { +interface UseValidationOptions + extends OnErrorProps { /** * The value to validate. */ - value: TValue; + value: InferPickerValue; /** * The timezone to use for the validation. */ @@ -32,7 +33,7 @@ interface UseValidationOptions * 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; + validator: Validator; /** * The validation props, they differ depending on the component. * For example, the `validateTime` function supports `minTime`, `maxTime`, etc. @@ -40,7 +41,7 @@ interface UseValidationOptions props: TValidationProps; } -interface UseValidationReturnValue { +interface UseValidationReturnValue { /** * The validation error associated to the value passed to the `useValidation` hook. */ @@ -54,27 +55,27 @@ interface UseValidationReturnValue { /** * 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. + * @template TIsRange `true` if the value comes from a range picker, `false` otherwise. + * @param {InferPickerValue} newValue The value to validate. * @returns {TError} The validation error associated to the new value. */ - getValidationErrorForNewValue: (newValue: TValue) => TError; + getValidationErrorForNewValue: (newValue: InferPickerValue) => TError; } /** * Utility hook to check if a given value is valid based on the provided validation props. - * @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 TIsRange `true` if the value comes from a range picker, `false` otherwise. * @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 {UseValidationOptions} options The options to configure the hook. + * @param {InferPickerValue} 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 {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. + * @param {(error: TError, value: InferPickerValue) => void} options.onError Callback fired when the error associated with the current value changes. */ -export function useValidation( - options: UseValidationOptions, -): UseValidationReturnValue { +export function useValidation( + options: UseValidationOptions, +): UseValidationReturnValue { const { props, validator, value, timezone, onError } = options; const adapter = useLocalizationContext(); @@ -96,7 +97,7 @@ export function useValidation( previousValidationErrorRef.current = validationError; }, [validator, onError, validationError, value]); - const getValidationErrorForNewValue = useEventCallback((newValue: TValue) => { + const getValidationErrorForNewValue = useEventCallback((newValue: InferPickerValue) => { return validator({ adapter, value: newValue, timezone, props }); }); diff --git a/packages/x-date-pickers/src/validation/validateDate.ts b/packages/x-date-pickers/src/validation/validateDate.ts index 3c53ee7acb38..cf6995363110 100644 --- a/packages/x-date-pickers/src/validation/validateDate.ts +++ b/packages/x-date-pickers/src/validation/validateDate.ts @@ -5,7 +5,7 @@ import { MonthValidationProps, YearValidationProps, } from '../internals/models/validation'; -import { DateValidationError, PickerValidDate } from '../models'; +import { DateValidationError } from '../models'; import { applyDefaultDate } from '../internals/utils/date-utils'; import { singleItemValueManager } from '../internals/utils/valueManagers'; @@ -24,11 +24,12 @@ export interface ValidateDateProps YearValidationProps, Required {} -export const validateDate: Validator< - PickerValidDate | null, - DateValidationError, - ValidateDateProps -> = ({ props, value, timezone, adapter }): DateValidationError => { +export const validateDate: Validator = ({ + props, + value, + timezone, + adapter, +}): DateValidationError => { if (value === null) { return null; } diff --git a/packages/x-date-pickers/src/validation/validateDateTime.ts b/packages/x-date-pickers/src/validation/validateDateTime.ts index 34ef257efba2..b827b21c888f 100644 --- a/packages/x-date-pickers/src/validation/validateDateTime.ts +++ b/packages/x-date-pickers/src/validation/validateDateTime.ts @@ -1,7 +1,7 @@ import { Validator } from './useValidation'; import { ExportedValidateDateProps, validateDate, ValidateDateProps } from './validateDate'; import { ExportedValidateTimeProps, validateTime, ValidateTimeProps } from './validateTime'; -import { DateTimeValidationError, PickerValidDate } from '../models'; +import { DateTimeValidationError } from '../models'; import { singleItemValueManager } from '../internals/utils/valueManagers'; import { DateTimeValidationProps } from '../internals/models/validation'; @@ -15,11 +15,12 @@ export interface ExportedValidateDateTimeProps export interface ValidateDateTimeProps extends ValidateDateProps, ValidateTimeProps {} -export const validateDateTime: Validator< - PickerValidDate | null, - DateTimeValidationError, - ValidateDateTimeProps -> = ({ adapter, value, timezone, props }) => { +export const validateDateTime: Validator = ({ + adapter, + value, + timezone, + props, +}) => { const dateValidationResult = validateDate({ adapter, value, diff --git a/packages/x-date-pickers/src/validation/validateTime.ts b/packages/x-date-pickers/src/validation/validateTime.ts index 2979aa6864e1..87e626d7aa67 100644 --- a/packages/x-date-pickers/src/validation/validateTime.ts +++ b/packages/x-date-pickers/src/validation/validateTime.ts @@ -1,7 +1,7 @@ import { createIsAfterIgnoreDatePart } from '../internals/utils/time-utils'; import { Validator } from './useValidation'; import { BaseTimeValidationProps, TimeValidationProps } from '../internals/models/validation'; -import { PickerValidDate, TimeValidationError } from '../models'; +import { TimeValidationError } from '../models'; import { singleItemValueManager } from '../internals/utils/valueManagers'; /** @@ -11,11 +11,12 @@ export interface ExportedValidateTimeProps extends BaseTimeValidationProps, Time export interface ValidateTimeProps extends Required, TimeValidationProps {} -export const validateTime: Validator< - PickerValidDate | null, - TimeValidationError, - ValidateTimeProps -> = ({ adapter, value, timezone, props }): TimeValidationError => { +export const validateTime: Validator = ({ + adapter, + value, + timezone, + props, +}): TimeValidationError => { if (value === null) { return null; } diff --git a/test/utils/pickers/describeValue/describeValue.tsx b/test/utils/pickers/describeValue/describeValue.tsx index 766fe523f9d0..b3e99cb4a80c 100644 --- a/test/utils/pickers/describeValue/describeValue.tsx +++ b/test/utils/pickers/describeValue/describeValue.tsx @@ -16,15 +16,15 @@ const TEST_SUITES: DescribeValueTestSuite[] = [ testShortcuts, ]; -function innerDescribeValue( +function innerDescribeValue( ElementToTest: React.FunctionComponent, - getOptions: () => DescribeValueOptions, + getOptions: () => DescribeValueOptions, ) { const options = getOptions(); const { defaultProps, render, clock, componentFamily } = options; function WrappedElementToTest( - props: BasePickerInputProps & UsePickerValueNonStaticProps & { hook?: any }, + props: BasePickerInputProps & UsePickerValueNonStaticProps & { hook?: any }, ) { const { hook, ...other } = props; const hookResult = hook?.(props); @@ -72,15 +72,19 @@ function innerDescribeValue( }); } -type P = [ +type P = [ React.FunctionComponent, - () => DescribeValueOptions, + () => DescribeValueOptions, ]; type DescribeValue = { - (...args: P): void; - skip: (...args: P) => void; - only: (...args: P) => void; + (...args: P): void; + skip: ( + ...args: P + ) => void; + only: ( + ...args: P + ) => void; }; /** diff --git a/test/utils/pickers/fields.tsx b/test/utils/pickers/fields.tsx index 5b552398c467..ce2878952e41 100644 --- a/test/utils/pickers/fields.tsx +++ b/test/utils/pickers/fields.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { createTheme, ThemeProvider } from '@mui/material/styles'; import { createRenderer, screen, act, fireEvent } from '@mui/internal-test-utils'; -import { FieldRef, FieldSection, FieldSectionType } from '@mui/x-date-pickers/models'; +import { FieldRef, FieldSectionType } from '@mui/x-date-pickers/models'; import { pickersSectionListClasses } from '@mui/x-date-pickers/PickersSectionList'; import { pickersInputBaseClasses } from '@mui/x-date-pickers/PickersTextField'; import { fireUserEvent } from '../fireUserEvent'; @@ -88,10 +88,10 @@ export const buildFieldInteractions =

({ props, { hook, componentFamily = 'field', direction = 'ltr' } = {}, ) => { - let fieldRef: React.RefObject> = { current: null }; + let fieldRef: React.RefObject> = { current: null }; function WrappedComponent(propsFromRender: any) { - fieldRef = React.useRef>(null); + fieldRef = React.useRef>(null); const hookResult = hook?.(propsFromRender); const allProps = {