diff --git a/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.js b/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.js index ab660eb554b9..e102430740bd 100644 --- a/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.js +++ b/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.js @@ -1,4 +1,5 @@ import * as React from 'react'; + import Typography from '@mui/material/Typography'; import Stack from '@mui/material/Stack'; import Button from '@mui/material/Button'; diff --git a/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx b/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx index 68995de41ed1..6465a9a84a03 100644 --- a/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx +++ b/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { Dayjs } from 'dayjs'; import Typography from '@mui/material/Typography'; import Stack from '@mui/material/Stack'; import Button from '@mui/material/Button'; @@ -9,14 +10,14 @@ import { FieldSelectedSections, FieldRef, } from '@mui/x-date-pickers/models'; -import { RangeFieldSection, RangePosition } from '@mui/x-date-pickers-pro/models'; +import { DateRange, 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/data/date-pickers/shortcuts/CustomizedRangeShortcuts.js b/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.js index 31c77d7d7420..478f2dcb5455 100644 --- a/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.js +++ b/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.js @@ -1,10 +1,10 @@ import * as React from 'react'; +import dayjs from 'dayjs'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import Chip from '@mui/material/Chip'; import Divider from '@mui/material/Divider'; import Box from '@mui/material/Box'; -import dayjs from 'dayjs'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { StaticDateRangePicker } from '@mui/x-date-pickers-pro/StaticDateRangePicker'; diff --git a/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.tsx b/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.tsx index 3e3d6fda53c9..87530990c3a8 100644 --- a/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.tsx +++ b/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; +import dayjs, { Dayjs } from 'dayjs'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import Chip from '@mui/material/Chip'; import Divider from '@mui/material/Divider'; import Box from '@mui/material/Box'; -import dayjs, { Dayjs } from 'dayjs'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { StaticDateRangePicker } from '@mui/x-date-pickers-pro/StaticDateRangePicker'; diff --git a/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md b/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md index 4df6769af818..764f28cfb98a 100644 --- a/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md +++ b/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md @@ -348,9 +348,9 @@ const theme = createTheme({ +console.log(readOnly); ``` -## Renamed variables +## Renamed variables and types -The following variables were renamed to have a coherent `Picker` / `Pickers` prefix: +The following variables and types have been renamed to have a coherent `Picker` / `Pickers` prefix: - `usePickersTranslations` @@ -394,9 +394,19 @@ The following variables were renamed to have a coherent `Picker` / `Pickers` pre +import { PickerValueType } from '@mui/x-date-pickers-pro'; ``` + - `RangeFieldSection` + + ```diff + -import { RangeFieldSection } from '@mui/x-date-pickers-pro/models'; + -import { RangeFieldSection } from '@mui/x-date-pickers-pro'; + + +import { FieldRangeSection } from '@mui/x-date-pickers-pro/models'; + +import { FieldRangeSection } from '@mui/x-date-pickers-pro'; + ``` + ## Typing breaking changes -### Remove `TDate` generic +### Do not pass the date object as a generic The `TDate` generic has been removed from all the types, interfaces, and variables of the `@mui/x-date-pickers` and `@mui/x-date-pickers-pro` packages. @@ -406,14 +416,24 @@ If you were passing your date object type as a generic to any element of one of - value={value} onChange={onChange} /> + --type Slot = DateCalendarSlots['calendarHeader']; -+type Slot = DateCalendarSlots['calendarHeader']; +-type FieldComponent = DatePickerSlots['field']; ++type FieldComponent = DatePickerSlots['field']; --type Props = DatePickerToolbarProps; -+type Props = DatePickerToolbarProps; +-function CustomDatePicker(props: DatePickerProps) {} ++function CustomDatePicker(props: DatePickerProps) {} ``` -A follow-up release will add the full list of the impacted elements to the migration guide. +### Do not pass the section type as a generic + +The `TSection` generic of the `FieldRef` type has been replaced with the `TValue` generic: + +```diff +-const fieldRef = React.useRef>(null); ++const fieldRef = React.useRef(null); + +-const fieldRef = React.useRef>(null); ++const fieldRef = React.useRef>(null); +``` ### Removed types 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 8afa43015506..013359cc8f08 100644 --- a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.types.ts +++ b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.types.ts @@ -9,7 +9,7 @@ import { MobileDateRangePickerSlots, MobileDateRangePickerSlotProps, } from '../MobileDateRangePicker'; -import { DateRangeValidationError, RangeFieldSection } from '../models'; +import { DateRangeValidationError } from '../models'; import { ValidateDateRangeProps } from '../validation'; export interface DateRangePickerSlots @@ -48,7 +48,6 @@ export type DateRangePickerFieldProps; 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 bfb0237f8f03..509f8246c2ce 100644 --- a/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePicker.types.ts +++ b/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePicker.types.ts @@ -9,7 +9,7 @@ import { MobileDateTimeRangePickerSlots, MobileDateTimeRangePickerSlotProps, } from '../MobileDateTimeRangePicker'; -import { DateTimeRangeValidationError, RangeFieldSection } from '../models'; +import { DateTimeRangeValidationError } from '../models'; import type { ValidateDateTimeRangeProps } from '../validation'; export interface DateTimeRangePickerSlots @@ -49,7 +49,6 @@ export type DateTimeRangePickerFieldProps< > = ValidateDateTimeRangeProps & BaseSingleInputFieldProps< PickerRangeValue, - RangeFieldSection, TEnableAccessibleFieldDOMStructure, DateTimeRangeValidationError >; diff --git a/packages/x-date-pickers-pro/src/DesktopDateRangePicker/tests/describes.DesktopDateRangePicker.test.tsx b/packages/x-date-pickers-pro/src/DesktopDateRangePicker/tests/describes.DesktopDateRangePicker.test.tsx index 8fd06df96b68..f9255bdd65af 100644 --- a/packages/x-date-pickers-pro/src/DesktopDateRangePicker/tests/describes.DesktopDateRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/DesktopDateRangePicker/tests/describes.DesktopDateRangePicker.test.tsx @@ -12,6 +12,7 @@ import { } from 'test/utils/pickers'; import { DesktopDateRangePicker } from '@mui/x-date-pickers-pro/DesktopDateRangePicker'; import { SingleInputDateRangeField } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; +import { PickerNonNullableRangeValue, PickerRangeValue } from '@mui/x-date-pickers/internals'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -45,7 +46,7 @@ describe(' - Describes', () => { ], })); - describeValue(DesktopDateRangePicker, () => ({ + describeValue(DesktopDateRangePicker, () => ({ render, componentFamily: 'picker', type: 'date-range', @@ -76,7 +77,7 @@ describe(' - Describes', () => { value, { isOpened, applySameValue, setEndDate = false, selectSection, pressKey }, ) => { - let newValue: any[]; + let newValue: PickerNonNullableRangeValue; if (applySameValue) { newValue = value; } else if (setEndDate) { @@ -101,7 +102,7 @@ describe(' - Describes', () => { })); // With single input field - describeValue(DesktopDateRangePicker, () => ({ + describeValue(DesktopDateRangePicker, () => ({ render, componentFamily: 'picker', type: 'date-range', @@ -138,7 +139,7 @@ describe(' - Describes', () => { value, { isOpened, applySameValue, setEndDate = false, selectSection, pressKey }, ) => { - let newValue: any[]; + let newValue: PickerNonNullableRangeValue; if (applySameValue) { newValue = value; } else if (setEndDate) { diff --git a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/describes.DesktopDateTimeRangePicker.test.tsx b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/describes.DesktopDateTimeRangePicker.test.tsx index d3a4235ce6e1..dfdd329087ff 100644 --- a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/describes.DesktopDateTimeRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/describes.DesktopDateTimeRangePicker.test.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { describeConformance, fireEvent, screen } from '@mui/internal-test-utils'; +import { PickerNonNullableRangeValue, PickerRangeValue } from '@mui/x-date-pickers/internals'; import { createPickerRenderer, adapterToUse, @@ -46,7 +47,7 @@ describe(' - Describes', () => { ], })); - describeValue(DesktopDateTimeRangePicker, () => ({ + describeValue(DesktopDateTimeRangePicker, () => ({ render, componentFamily: 'picker', type: 'date-time-range', @@ -86,7 +87,7 @@ describe(' - Describes', () => { value, { isOpened, applySameValue, setEndDate = false, selectSection, pressKey }, ) => { - let newValue: any[]; + let newValue: PickerNonNullableRangeValue; if (applySameValue) { newValue = value; } else if (setEndDate) { diff --git a/packages/x-date-pickers-pro/src/MobileDateRangePicker/tests/describes.MobileDateRangePicker.test.tsx b/packages/x-date-pickers-pro/src/MobileDateRangePicker/tests/describes.MobileDateRangePicker.test.tsx index 3d5b9c2013bc..830468015211 100644 --- a/packages/x-date-pickers-pro/src/MobileDateRangePicker/tests/describes.MobileDateRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/MobileDateRangePicker/tests/describes.MobileDateRangePicker.test.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { screen, fireDiscreteEvent, fireEvent } from '@mui/internal-test-utils'; import { MobileDateRangePicker } from '@mui/x-date-pickers-pro/MobileDateRangePicker'; +import { PickerNonNullableRangeValue, PickerRangeValue } from '@mui/x-date-pickers/internals'; import { adapterToUse, createPickerRenderer, @@ -45,7 +46,7 @@ describe(' - Describes', () => { ], })); - describeValue(MobileDateRangePicker, () => ({ + describeValue(MobileDateRangePicker, () => ({ render, componentFamily: 'picker', type: 'date-range', @@ -73,7 +74,7 @@ describe(' - Describes', () => { expectFieldValueV7(endFieldRoot, expectedEndValueStr); }, setNewValue: (value, { isOpened, applySameValue, setEndDate = false }) => { - let newValue: any[]; + let newValue: PickerNonNullableRangeValue; if (applySameValue) { newValue = value; } else if (setEndDate) { diff --git a/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/tests/describes.MobileDateTimeRangePicker.test.tsx b/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/tests/describes.MobileDateTimeRangePicker.test.tsx index e0ba6d9c933a..90a5dc4057ec 100644 --- a/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/tests/describes.MobileDateTimeRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/tests/describes.MobileDateTimeRangePicker.test.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { describeConformance, fireEvent, screen } from '@mui/internal-test-utils'; +import { PickerNonNullableRangeValue, PickerRangeValue } from '@mui/x-date-pickers/internals'; import { createPickerRenderer, adapterToUse, @@ -10,7 +11,7 @@ import { getFieldSectionsContainer, openPicker, } from 'test/utils/pickers'; -import { MobileDateTimeRangePicker } from '../MobileDateTimeRangePicker'; +import { MobileDateTimeRangePicker } from '@mui/x-date-pickers-pro/MobileDateTimeRangePicker'; describe(' - Describes', () => { const { render, clock } = createPickerRenderer({ @@ -47,7 +48,7 @@ describe(' - Describes', () => { ], })); - describeValue(MobileDateTimeRangePicker, () => ({ + describeValue(MobileDateTimeRangePicker, () => ({ render, componentFamily: 'picker', type: 'date-time-range', @@ -91,7 +92,7 @@ describe(' - Describes', () => { initialFocus: setEndDate ? 'end' : 'start', }); } - let newValue: any[]; + let newValue: PickerNonNullableRangeValue; if (applySameValue) { newValue = value; } else if (setEndDate) { 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..90d138c59c32 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts @@ -1,18 +1,14 @@ 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 { PickerRangeValue, 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, @@ -21,7 +17,6 @@ export interface UseSingleInputDateRangeFieldProps< Pick< UseFieldInternalProps< PickerRangeValue, - RangeFieldSection, TEnableAccessibleFieldDOMStructure, DateRangeValidationError >, diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts index 628a548326c4..e1b71090039e 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts @@ -5,7 +5,6 @@ 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, @@ -27,7 +26,6 @@ export const useSingleInputDateRangeField = < return useField< PickerRangeValue, - RangeFieldSection, 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..53079837d53c 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 { PickerRangeValue, UseFieldInternalProps } from '@mui/x-date-pickers/internals'; import { BuiltInFieldTextFieldProps } from '@mui/x-date-pickers/models'; import { ExportedUseClearableFieldProps, @@ -9,7 +9,7 @@ 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, @@ -18,7 +18,6 @@ export interface UseSingleInputDateTimeRangeFieldProps< Pick< UseFieldInternalProps< PickerRangeValue, - RangeFieldSection, TEnableAccessibleFieldDOMStructure, DateTimeRangeValidationError >, diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts index f96bfe35fd10..1fbed22a25d0 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts @@ -9,7 +9,6 @@ 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, @@ -31,7 +30,6 @@ export const useSingleInputDateTimeRangeField = < return useField< PickerRangeValue, - RangeFieldSection, 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..a1b94ce63cd7 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts @@ -9,7 +9,7 @@ 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, @@ -18,7 +18,6 @@ export interface UseSingleInputTimeRangeFieldProps< Pick< UseFieldInternalProps< PickerRangeValue, - RangeFieldSection, TEnableAccessibleFieldDOMStructure, TimeRangeValidationError >, diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts index f7a4eec521e6..a55e35d42c97 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts @@ -5,7 +5,6 @@ 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, @@ -27,7 +26,6 @@ export const useSingleInputTimeRangeField = < return useField< PickerRangeValue, - RangeFieldSection, 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..bf22eeb38d5d 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 @@ -20,7 +20,6 @@ import { RangePickerFieldSlots, RangePickerFieldSlotProps, } from '../useEnrichedRangePickerFieldProps'; -import { RangeFieldSection } from '../../../models'; export interface UseRangePickerSlots extends ExportedPickersLayoutSlots, @@ -58,13 +57,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 34d4e46d8008..4dabe621a1e7 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,6 +11,7 @@ import { DateOrTimeViewWithMeridiem, ExportedBaseTabsProps, PickerProvider, + PickerValue, PickerRangeValue, } from '@mui/x-date-pickers/internals'; import { FieldRef, InferError } from '@mui/x-date-pickers/models'; @@ -24,7 +25,6 @@ import { useEnrichedRangePickerFieldProps, } from '../useEnrichedRangePickerFieldProps'; import { getReleaseInfo } from '../../utils/releaseInfo'; -import { RangeFieldSection } from '../../../models'; import { useRangePosition } from '../useRangePosition'; const releaseInfo = getReleaseInfo(); @@ -69,16 +69,26 @@ 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 singleInputFieldRef = React.useRef>(null); const initialView = React.useRef(props.openTo ?? null); const fieldType = (slots.field as any).fieldType ?? 'multi-input'; const { rangePosition, onRangePositionChange } = useRangePosition( props, - fieldType === 'single-input' ? startFieldRef : undefined, + fieldType === 'single-input' ? singleInputFieldRef : undefined, ); + let fieldRef: React.RefObject | FieldRef>; + if (fieldType === 'single-input') { + fieldRef = singleInputFieldRef; + } else if (rangePosition === 'start') { + fieldRef = startFieldRef; + } else { + fieldRef = endFieldRef; + } + const { open, actions, @@ -88,18 +98,12 @@ export const useDesktopRangePicker = < shouldRestoreFocus, fieldProps: pickerFieldProps, ownerState, - } = usePicker< - PickerRangeValue, - TView, - RangeFieldSection, - TExternalProps, - DesktopRangePickerAdditionalViewProps - >({ + } = usePicker({ ...pickerParams, props, variant: 'desktop', autoFocusView: false, - fieldRef: rangePosition === 'start' ? startFieldRef : endFieldRef, + fieldRef, localeText, additionalViewProps: { rangePosition, @@ -181,6 +185,7 @@ export const useDesktopRangePicker = < anchorRef, startFieldRef, endFieldRef, + singleInputFieldRef, currentView: layoutProps.view !== props.openTo ? layoutProps.view : undefined, initialView: initialView.current ?? undefined, onViewChange: layoutProps.onViewChange, 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 17ffbc770c21..5e35864340a9 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts @@ -20,12 +20,12 @@ import { DateOrTimeViewWithMeridiem, BaseSingleInputFieldProps, PickerRangeValue, + PickerValue, } from '@mui/x-date-pickers/internals'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { MultiInputFieldSlotRootProps, MultiInputFieldSlotTextFieldProps, - RangeFieldSection, RangePosition, FieldType, UseDateRangeFieldProps, @@ -57,11 +57,7 @@ export interface RangePickerFieldSlots extends UseClearableFieldSlots { export interface RangePickerFieldSlotProps extends UseClearableFieldSlotProps { field?: SlotComponentPropsFromProps< - PickerRangeFieldSlotProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure - >, + PickerRangeFieldSlotProps, {}, PickerOwnerState >; @@ -80,20 +76,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< @@ -101,10 +87,7 @@ export interface UseEnrichedRangePickerFieldPropsParams< TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean, TError, -> extends Pick< - UsePickerResponse, - 'open' | 'actions' - >, +> extends Pick, 'open' | 'actions'>, UseRangePositionResponse { variant: PickerVariant; fieldType: FieldType; @@ -125,8 +108,9 @@ export interface UseEnrichedRangePickerFieldPropsParams< currentView?: TView | null; initialView?: TView; onViewChange?: (view: TView) => void; - startFieldRef: React.RefObject>; - endFieldRef: React.RefObject>; + startFieldRef: React.RefObject>; + endFieldRef: React.RefObject>; + singleInputFieldRef: React.RefObject>; } const useMultiInputFieldSlotProps = < @@ -159,12 +143,7 @@ const useMultiInputFieldSlotProps = < TEnableAccessibleFieldDOMStructure, TError >) => { - type ReturnType = BaseMultiInputFieldProps< - PickerRangeValue, - RangeFieldSection, - TEnableAccessibleFieldDOMStructure, - TError - >; + type ReturnType = BaseMultiInputFieldProps; const translations = usePickerTranslations(); const handleStartFieldRef = useForkRef(fieldProps.unstableStartFieldRef, startFieldRef); @@ -322,8 +301,7 @@ const useSingleInputFieldSlotProps = < onBlur, rangePosition, onRangePositionChange, - startFieldRef, - endFieldRef, + singleInputFieldRef, pickerSlots, pickerSlotProps, fieldProps, @@ -337,40 +315,39 @@ const useSingleInputFieldSlotProps = < >) => { type ReturnType = BaseSingleInputFieldProps< PickerRangeValue, - RangeFieldSection, TEnableAccessibleFieldDOMStructure, TError >; - const handleFieldRef = useForkRef(fieldProps.unstableFieldRef, startFieldRef, endFieldRef); + const handleFieldRef = useForkRef(fieldProps.unstableFieldRef, singleInputFieldRef); React.useEffect(() => { - if (!open || !startFieldRef.current || variant === 'mobile') { + if (!open || !singleInputFieldRef.current || variant === 'mobile') { return; } - if (startFieldRef.current.isFieldFocused()) { + if (singleInputFieldRef.current.isFieldFocused()) { return; } // bring back focus to the field with the current view section selected if (currentView) { - const sections = startFieldRef.current.getSections().map((section) => section.type); + const sections = singleInputFieldRef.current.getSections().map((section) => section.type); const newSelectedSection = rangePosition === 'start' ? sections.indexOf(currentView) : sections.lastIndexOf(currentView); - startFieldRef.current?.focusField(newSelectedSection); + singleInputFieldRef.current?.focusField(newSelectedSection); } - }, [rangePosition, open, currentView, startFieldRef, variant]); + }, [rangePosition, open, currentView, singleInputFieldRef, variant]); const updateRangePosition = () => { - if (!startFieldRef.current?.isFieldFocused()) { + if (!singleInputFieldRef.current?.isFieldFocused()) { return; } - const sections = startFieldRef.current.getSections(); - const activeSectionIndex = startFieldRef.current?.getActiveSectionIndex(); + const sections = singleInputFieldRef.current.getSections(); + const activeSectionIndex = singleInputFieldRef.current?.getActiveSectionIndex(); const domRangePosition = activeSectionIndex == null || activeSectionIndex < sections.length / 2 ? 'start' : 'end'; 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 fecc321ac037..32b4ac1dab03 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 @@ -10,6 +10,7 @@ import { ExportedBaseTabsProps, PickerProvider, PickerRangeValue, + PickerValue, } from '@mui/x-date-pickers/internals'; import { usePickerTranslations } from '@mui/x-date-pickers/hooks'; import { FieldRef, InferError } from '@mui/x-date-pickers/models'; @@ -24,7 +25,6 @@ import { useEnrichedRangePickerFieldProps, } from '../useEnrichedRangePickerFieldProps'; import { getReleaseInfo } from '../../utils/releaseInfo'; -import { RangeFieldSection } from '../../../models'; import { useRangePosition } from '../useRangePosition'; const releaseInfo = getReleaseInfo(); @@ -64,17 +64,27 @@ 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 singleInputFieldRef = React.useRef>(null); const fieldType = (slots.field as any).fieldType ?? 'multi-input'; const { rangePosition, onRangePositionChange } = useRangePosition( props, - fieldType === 'single-input' ? startFieldRef : undefined, + fieldType === 'single-input' ? singleInputFieldRef : undefined, ); const labelId = useId(); const contextTranslations = usePickerTranslations(); + let fieldRef: React.Ref | FieldRef>; + if (fieldType === 'single-input') { + fieldRef = singleInputFieldRef; + } else if (rangePosition === 'start') { + fieldRef = startFieldRef; + } else { + fieldRef = endFieldRef; + } + const { open, actions, @@ -83,18 +93,12 @@ export const useMobileRangePicker = < renderCurrentView, fieldProps: pickerFieldProps, ownerState, - } = usePicker< - PickerRangeValue, - TView, - RangeFieldSection, - TExternalProps, - MobileRangePickerAdditionalViewProps - >({ + } = usePicker({ ...pickerParams, props, variant: 'mobile', autoFocusView: true, - fieldRef: rangePosition === 'start' ? startFieldRef : endFieldRef, + fieldRef, localeText, additionalViewProps: { rangePosition, @@ -155,6 +159,7 @@ export const useMobileRangePicker = < fieldProps, startFieldRef, endFieldRef, + singleInputFieldRef, }); const slotPropsForLayout: PickersLayoutSlotProps = { 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..b5fb7e3f74f0 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputFieldSelectedSections.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputFieldSelectedSections.ts @@ -1,23 +1,26 @@ import * as React from 'react'; import useForkRef from '@mui/utils/useForkRef'; import useEventCallback from '@mui/utils/useEventCallback'; -import { UseFieldInternalProps } from '@mui/x-date-pickers/internals'; +import { + PickerRangeValue, + PickerValue, + 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 651ebdbd216c..081fbf140f0e 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField.ts @@ -4,12 +4,13 @@ import { FieldChangeHandler, FieldChangeHandlerContext, PickerRangeValue, + PickerValue, UseFieldResponse, useControlledValueWithTimezone, useDefaultizedDateField, } from '@mui/x-date-pickers/internals'; import { useValidation } from '@mui/x-date-pickers/validation'; -import { DateValidationError, PickerValidDate } from '@mui/x-date-pickers/models'; +import { DateValidationError } from '@mui/x-date-pickers/models'; import { UseMultiInputDateRangeFieldParams, UseMultiInputDateRangeFieldProps, @@ -77,7 +78,7 @@ export const useMultiInputDateRangeField = < // TODO: Maybe export utility from `useField` instead of copy/pasting the logic const buildChangeHandler = ( index: 0 | 1, - ): FieldChangeHandler => { + ): 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/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts index 021ef4f196b1..3a006da7c913 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts @@ -4,11 +4,12 @@ import { FieldChangeHandler, FieldChangeHandlerContext, PickerRangeValue, + PickerValue, UseFieldResponse, useControlledValueWithTimezone, useDefaultizedDateTimeField, } from '@mui/x-date-pickers/internals'; -import { DateTimeValidationError, PickerValidDate } from '@mui/x-date-pickers/models'; +import { DateTimeValidationError } from '@mui/x-date-pickers/models'; import { useValidation } from '@mui/x-date-pickers/validation'; import type { UseMultiInputDateTimeRangeFieldParams, @@ -77,7 +78,7 @@ export const useMultiInputDateTimeRangeField = < // TODO: Maybe export utility from `useField` instead of copy/pasting the logic const buildChangeHandler = ( index: 0 | 1, - ): FieldChangeHandler => { + ): 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/useMultiInputRangeField/useMultiInputTimeRangeField.ts b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts index 6b9d4c42313f..9f8b36291f5f 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts @@ -4,12 +4,13 @@ import { FieldChangeHandler, FieldChangeHandlerContext, PickerRangeValue, + PickerValue, UseFieldResponse, useControlledValueWithTimezone, useDefaultizedTimeField, } from '@mui/x-date-pickers/internals'; import { useValidation } from '@mui/x-date-pickers/validation'; -import { PickerValidDate, TimeValidationError } from '@mui/x-date-pickers/models'; +import { TimeValidationError } from '@mui/x-date-pickers/models'; import { validateTimeRange } from '../../../validation'; import { TimeRangeValidationError } from '../../../models'; import type { @@ -77,7 +78,7 @@ export const useMultiInputTimeRangeField = < // TODO: Maybe export utility from `useField` instead of copy/pasting the logic const buildChangeHandler = ( index: 0 | 1, - ): FieldChangeHandler => { + ): 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..4b71d9e2ecb7 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,8 @@ 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 { PickerRangeValue } from '@mui/x-date-pickers/internals'; +import { RangePosition } from '../../models'; export interface UseRangePositionProps { /** @@ -30,7 +31,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 43b7b168f493..c37b8aa21903 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 @@ -14,7 +14,6 @@ import { UseStaticRangePickerParams, UseStaticRangePickerProps, } from './useStaticRangePicker.types'; -import { RangeFieldSection } from '../../../models'; import { useRangePosition } from '../useRangePosition'; const PickerStaticLayout = styled(PickersLayout)(({ theme }) => ({ @@ -42,7 +41,6 @@ export const useStaticRangePicker = < const { layoutProps, providerProps, renderCurrentView } = usePicker< PickerRangeValue, TView, - RangeFieldSection, TExternalProps, {} >({ 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..b4c62b6437d0 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 @@ -11,7 +11,6 @@ import { ExportedPickersLayoutSlots, ExportedPickersLayoutSlotProps, } from '@mui/x-date-pickers/PickersLayout'; -import { RangeFieldSection } from '../../../models'; import { UseRangePositionProps } from '../useRangePosition'; export interface UseStaticRangePickerSlots @@ -46,7 +45,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..dddac7c0a86b 100644 --- a/packages/x-date-pickers-pro/src/internals/models/dateTimeRange.ts +++ b/packages/x-date-pickers-pro/src/internals/models/dateTimeRange.ts @@ -5,11 +5,7 @@ import { 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 @@ -17,7 +13,6 @@ export interface UseDateTimeRangeFieldProps, diff --git a/packages/x-date-pickers-pro/src/internals/models/fields.ts b/packages/x-date-pickers-pro/src/internals/models/fields.ts index 79a498efbd54..c0a227ac3f98 100644 --- a/packages/x-date-pickers-pro/src/internals/models/fields.ts +++ b/packages/x-date-pickers-pro/src/internals/models/fields.ts @@ -1,8 +1,7 @@ import { SxProps } from '@mui/material/styles'; import { SlotComponentProps } from '@mui/utils'; import { MakeRequired } from '@mui/x-internals/types'; -import { UseFieldInternalProps } from '@mui/x-date-pickers/internals'; -import { FieldSection } from '@mui/x-date-pickers/models'; +import { PickerRangeValue, UseFieldInternalProps } from '@mui/x-date-pickers/internals'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import type { MultiInputFieldRefs, @@ -16,13 +15,11 @@ import type { * Only contains what the MUI components are passing to the field, not what users can pass using the `props.slotProps.field`. */ export interface BaseMultiInputFieldProps< - TValue, - TSection extends FieldSection, TEnableAccessibleFieldDOMStructure extends boolean, TError, > extends MakeRequired< Pick< - UseFieldInternalProps, + UseFieldInternalProps, | 'readOnly' | 'disabled' | 'format' 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..171ad2c8c7cd 100644 --- a/packages/x-date-pickers-pro/src/internals/models/timeRange.ts +++ b/packages/x-date-pickers-pro/src/internals/models/timeRange.ts @@ -1,10 +1,6 @@ import { MakeOptional } from '@mui/x-internals/types'; import { UseFieldInternalProps, AmPmProps, PickerRangeValue } from '@mui/x-date-pickers/internals'; -import { - TimeRangeValidationError, - RangeFieldSection, - RangeFieldSeparatorProps, -} from '../../models'; +import { TimeRangeValidationError, RangeFieldSeparatorProps } from '../../models'; import type { ExportedValidateTimeRangeProps } from '../../validation/validateTimeRange'; export interface UseTimeRangeFieldProps @@ -12,7 +8,6 @@ export interface UseTimeRangeFieldProps, 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..51000b91b1e8 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/internals'; -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..59009cfebe63 100644 --- a/packages/x-date-pickers-pro/src/internals/utils/valueManagers.ts +++ b/packages/x-date-pickers-pro/src/internals/utils/valueManagers.ts @@ -8,6 +8,8 @@ import { getTodayDate, getDefaultReferenceDate, PickerRangeValue, + PickerNonNullableRangeValue, + FieldRangeSection, } from '@mui/x-date-pickers/internals'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { splitDateRangeSections, removeLastSeparator } from './date-fields-utils'; @@ -15,17 +17,15 @@ 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 +38,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 +77,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 +87,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 +104,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 +167,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..0e29e30990cc 100644 --- a/packages/x-date-pickers-pro/src/models/dateRange.ts +++ b/packages/x-date-pickers-pro/src/models/dateRange.ts @@ -1,6 +1,6 @@ import { MakeOptional } from '@mui/x-internals/types'; -import { UseFieldInternalProps, PickerRangeValue } from '@mui/x-date-pickers/internals'; -import { RangeFieldSection, RangeFieldSeparatorProps } from './fields'; +import { PickerRangeValue, UseFieldInternalProps } from '@mui/x-date-pickers/internals'; +import { RangeFieldSeparatorProps } from './fields'; import { DateRangeValidationError } from './validation'; import type { ExportedValidateDateRangeProps } from '../validation/validateDateRange'; @@ -9,7 +9,6 @@ export interface UseDateRangeFieldProps, diff --git a/packages/x-date-pickers-pro/src/models/fields.ts b/packages/x-date-pickers-pro/src/models/fields.ts index 09c12ac54307..648dc4c4f277 100644 --- a/packages/x-date-pickers-pro/src/models/fields.ts +++ b/packages/x-date-pickers-pro/src/models/fields.ts @@ -1,12 +1,14 @@ import * as React from 'react'; -import { UseFieldResponse, FormProps } from '@mui/x-date-pickers/internals'; -import { FieldRef, FieldSection, PickerFieldSlotProps } from '@mui/x-date-pickers/models'; +import { + UseFieldResponse, + FormProps, + PickerValue, + PickerRangeValue, +} from '@mui/x-date-pickers/internals'; +import { FieldRef, PickerFieldSlotProps } from '@mui/x-date-pickers/models'; import { UseClearableFieldResponse } from '@mui/x-date-pickers/hooks'; -import { RangePosition } from './range'; -export interface RangeFieldSection extends FieldSection { - dateName: RangePosition; -} +export type { FieldRangeSection } from '@mui/x-date-pickers/internals'; export type FieldType = 'single-input' | 'multi-input'; @@ -35,8 +37,8 @@ export interface MultiInputFieldSlotRootProps { } export interface MultiInputFieldRefs { - unstableStartFieldRef?: React.Ref>; - unstableEndFieldRef?: React.Ref>; + unstableStartFieldRef?: React.Ref>; + unstableEndFieldRef?: React.Ref>; } export interface RangeFieldSeparatorProps { @@ -50,12 +52,9 @@ export interface RangeFieldSeparatorProps { /** * Props the `slotProps.field` of a range picker component can receive. */ -export type PickerRangeFieldSlotProps< - TValue, - TSection extends FieldSection, - TEnableAccessibleFieldDOMStructure extends boolean, -> = PickerFieldSlotProps & - RangeFieldSeparatorProps; +export type PickerRangeFieldSlotProps = + PickerFieldSlotProps & + RangeFieldSeparatorProps; /** * Props the text field receives when used with a multi input picker. 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/src/DateCalendar/DateCalendar.types.ts b/packages/x-date-pickers/src/DateCalendar/DateCalendar.types.ts index a068987b9bb4..022149cfdc80 100644 --- a/packages/x-date-pickers/src/DateCalendar/DateCalendar.types.ts +++ b/packages/x-date-pickers/src/DateCalendar/DateCalendar.types.ts @@ -26,6 +26,7 @@ import { } from '../MonthCalendar/MonthCalendar.types'; import { ExportedValidateDateProps } from '../validation/validateDate'; import { FormProps } from '../internals/models/formProps'; +import { PickerValue } from '../internals/models'; export interface DateCalendarSlots extends PickersCalendarHeaderSlots, @@ -80,7 +81,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/DateCalendar/tests/describes.DateCalendar.test.tsx b/packages/x-date-pickers/src/DateCalendar/tests/describes.DateCalendar.test.tsx index 10df9befa2fa..0993722c40b4 100644 --- a/packages/x-date-pickers/src/DateCalendar/tests/describes.DateCalendar.test.tsx +++ b/packages/x-date-pickers/src/DateCalendar/tests/describes.DateCalendar.test.tsx @@ -3,6 +3,7 @@ import { expect } from 'chai'; import { fireEvent, screen } from '@mui/internal-test-utils'; import { DateCalendar, dateCalendarClasses as classes } from '@mui/x-date-pickers/DateCalendar'; import { pickersDayClasses } from '@mui/x-date-pickers/PickersDay'; +import { PickerValue } from '@mui/x-date-pickers/internals'; import { adapterToUse, createPickerRenderer, @@ -30,7 +31,7 @@ describe(' - Describes', () => { skip: ['componentProp', 'componentsProp', 'themeVariants'], })); - describeValue(DateCalendar, () => ({ + describeValue(DateCalendar, () => ({ render, componentFamily: 'calendar', values: [adapterToUse.date('2018-01-01'), adapterToUse.date('2018-01-02')], diff --git a/packages/x-date-pickers/src/DateCalendar/useCalendarState.tsx b/packages/x-date-pickers/src/DateCalendar/useCalendarState.tsx index 0fca874dbcb0..a22917a0eceb 100644 --- a/packages/x-date-pickers/src/DateCalendar/useCalendarState.tsx +++ b/packages/x-date-pickers/src/DateCalendar/useCalendarState.tsx @@ -106,10 +106,9 @@ export const createCalendarStateReducer = } }; -interface UseCalendarStateParams +interface UseCalendarStateParameters extends Pick< DateCalendarDefaultizedProps, - | 'value' | 'referenceDate' | 'disableFuture' | 'disablePast' @@ -119,11 +118,27 @@ interface UseCalendarStateParams | 'reduceAnimations' | 'shouldDisableDate' > { + value: PickerValidDate | null; disableSwitchToMonthOnDayFocus?: boolean; timezone: PickersTimezone; } -export const useCalendarState = (params: UseCalendarStateParams) => { +interface UseCalendarStateReturnValue { + referenceDate: PickerValidDate; + calendarState: CalendarState; + changeMonth: (newDate: PickerValidDate) => void; + changeFocusedDay: ( + newFocusedDate: PickerValidDate | null, + withoutMonthSwitchingAnimation?: boolean, + ) => void; + isDateDisabled: (day: PickerValidDate | null) => boolean; + onMonthSwitchingAnimationEnd: () => void; + handleChangeMonth: (payload: ChangeMonthPayload) => void; +} + +export const useCalendarState = ( + params: UseCalendarStateParameters, +): UseCalendarStateReturnValue => { const { value, referenceDate: referenceDateProp, @@ -144,7 +159,7 @@ export const useCalendarState = (params: UseCalendarStateParams) => { createCalendarStateReducer(Boolean(reduceAnimations), disableSwitchToMonthOnDayFocus, utils), ).current; - const referenceDate = React.useMemo( + const referenceDate = React.useMemo( () => { return singleItemValueManager.getInitialReferenceValue({ value, diff --git a/packages/x-date-pickers/src/DateField/DateField.types.ts b/packages/x-date-pickers/src/DateField/DateField.types.ts index 3a7c21470f5b..57e48ff53e20 100644 --- a/packages/x-date-pickers/src/DateField/DateField.types.ts +++ b/packages/x-date-pickers/src/DateField/DateField.types.ts @@ -7,23 +7,14 @@ 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'; +import { PickerValue } from '../internals/models'; export interface UseDateFieldProps extends MakeOptional< - UseFieldInternalProps< - PickerValidDate | null, - FieldSection, - TEnableAccessibleFieldDOMStructure, - DateValidationError - >, + UseFieldInternalProps, 'format' >, ExportedValidateDateProps, diff --git a/packages/x-date-pickers/src/DateField/tests/describes.DateField.test.tsx b/packages/x-date-pickers/src/DateField/tests/describes.DateField.test.tsx index 6f7090a606a6..c1441c9e3f0e 100644 --- a/packages/x-date-pickers/src/DateField/tests/describes.DateField.test.tsx +++ b/packages/x-date-pickers/src/DateField/tests/describes.DateField.test.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { DateField } from '@mui/x-date-pickers/DateField'; +import { PickerValue } from '@mui/x-date-pickers/internals'; import { createPickerRenderer, expectFieldValueV7, @@ -30,7 +31,7 @@ describe(' - Describes', () => { skip: ['componentProp', 'componentsProp', 'themeVariants', 'themeStyleOverrides'], })); - describeValue(DateField, () => ({ + describeValue(DateField, () => ({ render, componentFamily: 'field', values: [adapterToUse.date('2018-01-01'), adapterToUse.date('2018-01-02')], diff --git a/packages/x-date-pickers/src/DateField/useDateField.ts b/packages/x-date-pickers/src/DateField/useDateField.ts index c5f7e8da6210..42d7b01fe3a8 100644 --- a/packages/x-date-pickers/src/DateField/useDateField.ts +++ b/packages/x-date-pickers/src/DateField/useDateField.ts @@ -7,8 +7,8 @@ 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'; +import { PickerValue } from '../internals/models'; export const useDateField = < TEnableAccessibleFieldDOMStructure extends boolean, @@ -24,8 +24,7 @@ export const useDateField = < const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date'); return useField< - PickerValidDate | null, - FieldSection, + PickerValue, 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 6ea627c4a5eb..bbccb00651e4 100644 --- a/packages/x-date-pickers/src/DatePicker/DatePicker.types.ts +++ b/packages/x-date-pickers/src/DatePicker/DatePicker.types.ts @@ -3,13 +3,13 @@ import { DesktopDatePickerSlots, DesktopDatePickerSlotProps, } from '../DesktopDatePicker'; -import { BaseSingleInputFieldProps } from '../internals/models'; +import { BaseSingleInputFieldProps, PickerValue } from '../internals/models'; import { MobileDatePickerProps, MobileDatePickerSlots, MobileDatePickerSlotProps, } from '../MobileDatePicker'; -import { DateValidationError, FieldSection, PickerValidDate } from '../models'; +import { DateValidationError } from '../models'; import { ValidateDateProps } from '../validation/validateDate'; export interface DatePickerSlots extends DesktopDatePickerSlots, MobileDatePickerSlots {} @@ -49,9 +49,4 @@ export interface DatePickerProps = ValidateDateProps & - BaseSingleInputFieldProps< - PickerValidDate | null, - FieldSection, - TEnableAccessibleFieldDOMStructure, - DateValidationError - >; + BaseSingleInputFieldProps; diff --git a/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx b/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx index 3da4d4fbec57..53dc5ca34d07 100644 --- a/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx +++ b/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx @@ -9,15 +9,16 @@ import { PickersToolbar } from '../internals/components/PickersToolbar'; import { usePickerTranslations } from '../hooks/usePickerTranslations'; 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, } from './datePickerToolbarClasses'; import { resolveDateFormat } from '../internals/utils/date-utils'; +import { PickerValue } from '../internals/models'; 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 ddfcbc42a54e..6c2e372740f8 100644 --- a/packages/x-date-pickers/src/DatePicker/shared.tsx +++ b/packages/x-date-pickers/src/DatePicker/shared.tsx @@ -8,7 +8,7 @@ import { } from '../DateCalendar/DateCalendar.types'; import { useDefaultDates, useUtils } from '../internals/hooks/useUtils'; import { applyDefaultViewProps } from '../internals/utils/views'; -import { DateValidationError, DateView, PickerValidDate } from '../models'; +import { DateValidationError, DateView } from '../models'; import { BasePickerInputProps } from '../internals/models/props/basePickerProps'; import { applyDefaultDate } from '../internals/utils/date-utils'; import { LocalizedComponent, PickersInputLocaleText } from '../locales/utils/pickersLocaleTextApi'; @@ -19,6 +19,7 @@ import { } from './DatePickerToolbar'; import { PickerViewRendererLookup } from '../internals/hooks/usePicker/usePickerViews'; import { DateViewRendererProps } from '../dateViewRenderers'; +import { PickerValue } from '../internals/models'; import { ValidateDatePropsToDefault } from '../validation/validateDate'; export interface BaseDatePickerSlots extends DateCalendarSlots { @@ -36,15 +37,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..876545ded3c4 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, @@ -16,12 +11,12 @@ import { } from '../hooks/useClearableField'; import { ExportedValidateDateTimeProps } from '../validation/validateDateTime'; import { AmPmProps } from '../internals/models/props/time'; +import { PickerValue } from '../internals/models'; export interface UseDateTimeFieldProps extends MakeOptional< UseFieldInternalProps< - PickerValidDate | null, - FieldSection, + PickerValue, TEnableAccessibleFieldDOMStructure, DateTimeValidationError >, diff --git a/packages/x-date-pickers/src/DateTimeField/tests/describes.DateTimeField.test.tsx b/packages/x-date-pickers/src/DateTimeField/tests/describes.DateTimeField.test.tsx index f18c33dd44b2..a4de539e0e8e 100644 --- a/packages/x-date-pickers/src/DateTimeField/tests/describes.DateTimeField.test.tsx +++ b/packages/x-date-pickers/src/DateTimeField/tests/describes.DateTimeField.test.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { DateTimeField } from '@mui/x-date-pickers/DateTimeField'; +import { PickerValue } from '@mui/x-date-pickers/internals'; import { adapterToUse, createPickerRenderer, @@ -30,7 +31,7 @@ describe(' - Describes', () => { skip: ['componentProp', 'componentsProp', 'themeVariants', 'themeStyleOverrides'], })); - describeValue(DateTimeField, () => ({ + describeValue(DateTimeField, () => ({ render, componentFamily: 'field', values: [adapterToUse.date('2018-01-01'), adapterToUse.date('2018-01-02')], diff --git a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts index 33e215fd4c7d..bd3b0b585352 100644 --- a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts +++ b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts @@ -7,8 +7,8 @@ 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'; +import { PickerValue } from '../internals/models'; export const useDateTimeField = < TEnableAccessibleFieldDOMStructure extends boolean, @@ -24,8 +24,7 @@ export const useDateTimeField = < const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date-time'); return useField< - PickerValidDate | null, - FieldSection, + PickerValue, 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 a461ac290f65..1013150e535b 100644 --- a/packages/x-date-pickers/src/DateTimePicker/DateTimePicker.types.ts +++ b/packages/x-date-pickers/src/DateTimePicker/DateTimePicker.types.ts @@ -3,13 +3,17 @@ import { DesktopDateTimePickerSlots, DesktopDateTimePickerSlotProps, } from '../DesktopDateTimePicker'; -import { BaseSingleInputFieldProps, DateOrTimeViewWithMeridiem } from '../internals/models'; +import { + BaseSingleInputFieldProps, + DateOrTimeViewWithMeridiem, + PickerValue, +} from '../internals/models'; import { MobileDateTimePickerProps, MobileDateTimePickerSlots, MobileDateTimePickerSlotProps, } from '../MobileDateTimePicker'; -import { DateTimeValidationError, FieldSection, PickerValidDate } from '../models'; +import { DateTimeValidationError } from '../models'; import { ValidateDateTimeProps } from '../validation'; import { ExportedYearCalendarProps } from '../YearCalendar/YearCalendar.types'; @@ -55,4 +59,4 @@ export interface DateTimePickerProps, or component). */ export type DateTimePickerFieldProps = ValidateDateTimeProps & - BaseSingleInputFieldProps; + BaseSingleInputFieldProps; diff --git a/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx b/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx index 4d1e637bffce..12f4d359e59e 100644 --- a/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx +++ b/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx @@ -17,7 +17,7 @@ import { DateTimePickerToolbarClasses, getDateTimePickerToolbarUtilityClass, } from './dateTimePickerToolbarClasses'; -import { DateOrTimeViewWithMeridiem, PickerVariant } from '../internals/models'; +import { DateOrTimeViewWithMeridiem, PickerValue, PickerVariant } from '../internals/models'; import { useMeridiemMode } from '../internals/hooks/date-helpers-hooks'; import { MULTI_SECTION_CLOCK_SECTION_WIDTH } from '../internals/constants/dimensions'; import { formatMeridiem } from '../internals/utils/date-utils'; @@ -35,7 +35,7 @@ export interface ExportedDateTimePickerToolbarProps extends ExportedBaseToolbarP export interface DateTimePickerToolbarProps extends ExportedDateTimePickerToolbarProps, - MakeOptional, 'view'> { + MakeOptional, 'view'> { toolbarVariant?: PickerVariant; /** * 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 3bb939565333..a4f52ac694d6 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, @@ -27,7 +27,7 @@ import { DateViewRendererProps } from '../dateViewRenderers'; import { TimeViewRendererProps } from '../timeViewRenderers'; import { applyDefaultViewProps } from '../internals/utils/views'; import { BaseClockProps, ExportedBaseClockProps } from '../internals/models/props/time'; -import { DateOrTimeViewWithMeridiem, TimeViewWithMeridiem } from '../internals/models'; +import { DateOrTimeViewWithMeridiem, PickerValue, TimeViewWithMeridiem } from '../internals/models'; import { ExportedValidateDateTimeProps, ValidateDateTimePropsToDefault, @@ -61,7 +61,7 @@ export type DateTimePickerViewRenderers< TView extends DateOrTimeViewWithMeridiem, TAdditionalProps extends {} = {}, > = PickerViewRendererLookup< - PickerValidDate | null, + PickerValue, TView, Omit, 'slots' | 'slotProps'> & Omit< @@ -72,7 +72,7 @@ export type DateTimePickerViewRenderers< >; export interface BaseDateTimePickerProps - extends BasePickerInputProps, + extends BasePickerInputProps, Omit, ExportedBaseClockProps, ExportedValidateDateTimeProps { diff --git a/packages/x-date-pickers/src/DesktopDatePicker/tests/describes.DesktopDatePicker.test.tsx b/packages/x-date-pickers/src/DesktopDatePicker/tests/describes.DesktopDatePicker.test.tsx index 3f8d4cabb075..1c79140c4807 100644 --- a/packages/x-date-pickers/src/DesktopDatePicker/tests/describes.DesktopDatePicker.test.tsx +++ b/packages/x-date-pickers/src/DesktopDatePicker/tests/describes.DesktopDatePicker.test.tsx @@ -10,6 +10,7 @@ import { getFieldInputRoot, } from 'test/utils/pickers'; import { DesktopDatePicker } from '@mui/x-date-pickers/DesktopDatePicker'; +import { PickerValue } from '@mui/x-date-pickers/internals'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -41,7 +42,7 @@ describe(' - Describes', () => { ], })); - describeValue(DesktopDatePicker, () => ({ + describeValue(DesktopDatePicker, () => ({ render, componentFamily: 'picker', type: 'date', diff --git a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx index a53946a0c310..3e7ba8dd6635 100644 --- a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx +++ b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx @@ -16,7 +16,7 @@ import { renderDateViewCalendar } from '../dateViewRenderers/dateViewRenderers'; import { usePickerTranslations } from '../hooks/usePickerTranslations'; import { useUtils } from '../internals/hooks/useUtils'; import { validateDateTime, extractValidationProps } from '../validation'; -import { DateOrTimeViewWithMeridiem } from '../internals/models'; +import { DateOrTimeViewWithMeridiem, PickerValue } from '../internals/models'; import { CalendarIcon } from '../icons'; import { UseDesktopPickerProps, useDesktopPicker } from '../internals/hooks/useDesktopPicker'; import { PickerViewsRendererProps } from '../internals/hooks/usePicker'; @@ -25,7 +25,7 @@ import { resolveTimeViewsResponse, } from '../internals/utils/date-time-utils'; import { PickersActionBarAction } from '../PickersActionBar'; -import { PickerOwnerState, PickerValidDate } from '../models'; +import { PickerOwnerState } from '../models'; import { renderDigitalClockTimeView, renderMultiSectionDigitalClockTimeView, @@ -51,14 +51,14 @@ const rendererInterceptor = function rendererInterceptor< inViewRenderers: DateTimePickerViewRenderers, popperView: TView, rendererProps: PickerViewsRendererProps< - PickerValidDate | null, + PickerValue, TView, DefaultizedProps< UseDesktopPickerProps< TView, TEnableAccessibleFieldDOMStructure, any, - UsePickerViewsProps + UsePickerViewsProps >, 'openTo' >, diff --git a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx index 6f4b75e7ecb8..27522e004e00 100644 --- a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx +++ b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx @@ -11,8 +11,12 @@ import { } from '../PickersLayout'; import { DateOrTimeViewWithMeridiem } from '../internals/models/common'; import { usePickerContext } from '../hooks/usePickerContext'; +import { PickerValidValue } from '../internals/models'; -type DesktopDateTimePickerLayoutComponent = (( +type DesktopDateTimePickerLayoutComponent = (< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +>( props: PickersLayoutProps & React.RefAttributes, ) => React.JSX.Element) & { propTypes?: any }; @@ -20,7 +24,7 @@ type DesktopDateTimePickerLayoutComponent = ((props: PickersLayoutProps, ref: React.Ref) { const { toolbar, tabs, content, actionBar, shortcuts, ownerState } = usePickerLayout(props); @@ -97,7 +101,7 @@ DesktopDateTimePickerLayout.propTypes = { PropTypes.func, PropTypes.object, ]), - value: PropTypes.any, + value: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), view: PropTypes.oneOf(['day', 'hours', 'meridiem', 'minutes', 'month', 'seconds', 'year']), views: PropTypes.arrayOf( PropTypes.oneOf(['day', 'hours', 'meridiem', 'minutes', 'month', 'seconds', 'year']).isRequired, diff --git a/packages/x-date-pickers/src/DesktopDateTimePicker/tests/describes.DesktopDateTimePicker.test.tsx b/packages/x-date-pickers/src/DesktopDateTimePicker/tests/describes.DesktopDateTimePicker.test.tsx index 65f18f9d8090..5d6ab646c7b9 100644 --- a/packages/x-date-pickers/src/DesktopDateTimePicker/tests/describes.DesktopDateTimePicker.test.tsx +++ b/packages/x-date-pickers/src/DesktopDateTimePicker/tests/describes.DesktopDateTimePicker.test.tsx @@ -1,3 +1,5 @@ +import * as React from 'react'; +import { expect } from 'chai'; import { fireEvent, screen } from '@mui/internal-test-utils'; import { createPickerRenderer, @@ -9,8 +11,7 @@ import { getFieldInputRoot, } from 'test/utils/pickers'; import { DesktopDateTimePicker } from '@mui/x-date-pickers/DesktopDateTimePicker'; -import { expect } from 'chai'; -import * as React from 'react'; +import { PickerValue } from '@mui/x-date-pickers/internals'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -54,7 +55,7 @@ describe(' - Describes', () => { ], })); - describeValue(DesktopDateTimePicker, () => ({ + describeValue(DesktopDateTimePicker, () => ({ render, componentFamily: 'picker', type: 'date-time', diff --git a/packages/x-date-pickers/src/DesktopTimePicker/tests/describes.DesktopTimePicker.test.tsx b/packages/x-date-pickers/src/DesktopTimePicker/tests/describes.DesktopTimePicker.test.tsx index 48d8a67aa0d2..700a92a4156f 100644 --- a/packages/x-date-pickers/src/DesktopTimePicker/tests/describes.DesktopTimePicker.test.tsx +++ b/packages/x-date-pickers/src/DesktopTimePicker/tests/describes.DesktopTimePicker.test.tsx @@ -11,6 +11,7 @@ import { getFieldInputRoot, } from 'test/utils/pickers'; import { DesktopTimePicker } from '@mui/x-date-pickers/DesktopTimePicker'; +import { PickerValue } from '@mui/x-date-pickers/internals'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -46,7 +47,7 @@ describe(' - Describes', () => { ], })); - describeValue(DesktopTimePicker, () => ({ + describeValue(DesktopTimePicker, () => ({ render, componentFamily: 'picker', type: 'time', diff --git a/packages/x-date-pickers/src/DigitalClock/DigitalClock.tsx b/packages/x-date-pickers/src/DigitalClock/DigitalClock.tsx index ed52313e052d..9b167eb51c16 100644 --- a/packages/x-date-pickers/src/DigitalClock/DigitalClock.tsx +++ b/packages/x-date-pickers/src/DigitalClock/DigitalClock.tsx @@ -16,7 +16,7 @@ import { PickerViewRoot } from '../internals/components/PickerViewRoot'; import { getDigitalClockUtilityClass } from './digitalClockClasses'; import { DigitalClockProps } from './DigitalClock.types'; import { useViews } from '../internals/hooks/useViews'; -import { PickerValidDate, TimeView } from '../models'; +import { PickerValidDate } from '../models'; import { DIGITAL_CLOCK_VIEW_HEIGHT } from '../internals/constants/dimensions'; import { useControlledValueWithTimezone } from '../internals/hooks/useValueWithTimezone'; import { singleItemValueManager } from '../internals/utils/valueManagers'; @@ -198,7 +198,7 @@ export const DigitalClock = React.forwardRef(function DigitalClock( handleRawValueChange(newValue, 'finish', 'hours'), ); - const { setValueAndGoToNextView } = useViews>({ + const { setValueAndGoToNextView } = useViews({ view: inView, views, openTo, diff --git a/packages/x-date-pickers/src/DigitalClock/tests/describes.DigitalClock.test.tsx b/packages/x-date-pickers/src/DigitalClock/tests/describes.DigitalClock.test.tsx index e5c35a2387ef..c4f5013abc99 100644 --- a/packages/x-date-pickers/src/DigitalClock/tests/describes.DigitalClock.test.tsx +++ b/packages/x-date-pickers/src/DigitalClock/tests/describes.DigitalClock.test.tsx @@ -10,6 +10,7 @@ import { formatFullTimeValue, } from 'test/utils/pickers'; import { DigitalClock, digitalClockClasses as classes } from '@mui/x-date-pickers/DigitalClock'; +import { PickerValue } from '@mui/x-date-pickers/internals'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -32,7 +33,7 @@ describe(' - Describes', () => { skip: ['componentProp', 'componentsProp', 'themeVariants'], })); - describeValue(DigitalClock, () => ({ + describeValue(DigitalClock, () => ({ render, componentFamily: 'digital-clock', type: 'time', diff --git a/packages/x-date-pickers/src/MobileDatePicker/tests/describes.MobileDatePicker.test.tsx b/packages/x-date-pickers/src/MobileDatePicker/tests/describes.MobileDatePicker.test.tsx index 4423b3276797..2a75c950b93d 100644 --- a/packages/x-date-pickers/src/MobileDatePicker/tests/describes.MobileDatePicker.test.tsx +++ b/packages/x-date-pickers/src/MobileDatePicker/tests/describes.MobileDatePicker.test.tsx @@ -11,6 +11,7 @@ import { getFieldInputRoot, } from 'test/utils/pickers'; import { MobileDatePicker } from '@mui/x-date-pickers/MobileDatePicker'; +import { PickerValue } from '@mui/x-date-pickers/internals'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -41,7 +42,7 @@ describe(' - Describes', () => { ], })); - describeValue(MobileDatePicker, () => ({ + describeValue(MobileDatePicker, () => ({ render, componentFamily: 'picker', type: 'date', diff --git a/packages/x-date-pickers/src/MobileDateTimePicker/tests/describes.MobileDateTimePicker.test.tsx b/packages/x-date-pickers/src/MobileDateTimePicker/tests/describes.MobileDateTimePicker.test.tsx index d504885dad82..30ae63e192e4 100644 --- a/packages/x-date-pickers/src/MobileDateTimePicker/tests/describes.MobileDateTimePicker.test.tsx +++ b/packages/x-date-pickers/src/MobileDateTimePicker/tests/describes.MobileDateTimePicker.test.tsx @@ -12,6 +12,7 @@ import { getFieldInputRoot, } from 'test/utils/pickers'; import { MobileDateTimePicker } from '@mui/x-date-pickers/MobileDateTimePicker'; +import { PickerValue } from '@mui/x-date-pickers/internals'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -46,7 +47,7 @@ describe(' - Describes', () => { ], })); - describeValue(MobileDateTimePicker, () => ({ + describeValue(MobileDateTimePicker, () => ({ render, componentFamily: 'picker', type: 'date-time', diff --git a/packages/x-date-pickers/src/MobileTimePicker/tests/describes.MobileTimePicker.test.tsx b/packages/x-date-pickers/src/MobileTimePicker/tests/describes.MobileTimePicker.test.tsx index 34f8c027a14f..5cff45ba0c9c 100644 --- a/packages/x-date-pickers/src/MobileTimePicker/tests/describes.MobileTimePicker.test.tsx +++ b/packages/x-date-pickers/src/MobileTimePicker/tests/describes.MobileTimePicker.test.tsx @@ -13,6 +13,7 @@ import { getFieldInputRoot, } from 'test/utils/pickers'; import { MobileTimePicker } from '@mui/x-date-pickers/MobileTimePicker'; +import { PickerValue } from '@mui/x-date-pickers/internals'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -47,7 +48,7 @@ describe(' - Describes', () => { ], })); - describeValue(MobileTimePicker, () => ({ + describeValue(MobileTimePicker, () => ({ render, componentFamily: 'picker', type: 'time', diff --git a/packages/x-date-pickers/src/MonthCalendar/tests/describes.MonthCalendar.test.tsx b/packages/x-date-pickers/src/MonthCalendar/tests/describes.MonthCalendar.test.tsx index 6b13c8e125e9..9f9a3a8d903b 100644 --- a/packages/x-date-pickers/src/MonthCalendar/tests/describes.MonthCalendar.test.tsx +++ b/packages/x-date-pickers/src/MonthCalendar/tests/describes.MonthCalendar.test.tsx @@ -8,6 +8,7 @@ import { describeValue, } from 'test/utils/pickers'; import { MonthCalendar, monthCalendarClasses as classes } from '@mui/x-date-pickers/MonthCalendar'; +import { PickerValue } from '@mui/x-date-pickers/internals'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -29,7 +30,7 @@ describe(' - Describes', () => { skip: ['componentProp', 'componentsProp', 'themeVariants'], })); - describeValue(MonthCalendar, () => ({ + describeValue(MonthCalendar, () => ({ render, componentFamily: 'calendar', values: [adapterToUse.date('2018-01-01'), adapterToUse.date('2018-02-01')], diff --git a/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx b/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx index 0ecf6f91c1aa..68ef846a8cdd 100644 --- a/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx +++ b/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx @@ -154,10 +154,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 6f4861979f06..981618d81b93 100644 --- a/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClockSection.tsx +++ b/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClockSection.tsx @@ -28,12 +28,12 @@ export interface ExportedMultiSectionDigitalClockSectionProps { slotProps?: MultiSectionDigitalClockSlotProps; } -export interface MultiSectionDigitalClockSectionProps +export interface MultiSectionDigitalClockSectionProps extends FormProps, ExportedMultiSectionDigitalClockSectionProps { autoFocus?: 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/MultiSectionDigitalClock/tests/describes.MultiSectionDigitalClock.test.tsx b/packages/x-date-pickers/src/MultiSectionDigitalClock/tests/describes.MultiSectionDigitalClock.test.tsx index 06c7858b913e..3ab127d6bafa 100644 --- a/packages/x-date-pickers/src/MultiSectionDigitalClock/tests/describes.MultiSectionDigitalClock.test.tsx +++ b/packages/x-date-pickers/src/MultiSectionDigitalClock/tests/describes.MultiSectionDigitalClock.test.tsx @@ -12,7 +12,7 @@ import { MultiSectionDigitalClock, multiSectionDigitalClockClasses as classes, } from '@mui/x-date-pickers/MultiSectionDigitalClock'; -import { formatMeridiem } from '@mui/x-date-pickers/internals'; +import { formatMeridiem, PickerValue } from '@mui/x-date-pickers/internals'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -35,7 +35,7 @@ describe(' - Describes', () => { skip: ['componentProp', 'componentsProp', 'themeVariants'], })); - describeValue(MultiSectionDigitalClock, () => ({ + describeValue(MultiSectionDigitalClock, () => ({ render, componentFamily: 'multi-section-digital-clock', type: 'time', diff --git a/packages/x-date-pickers/src/PickersLayout/PickersLayout.tsx b/packages/x-date-pickers/src/PickersLayout/PickersLayout.tsx index dcb977d1b3ab..bb241e230453 100644 --- a/packages/x-date-pickers/src/PickersLayout/PickersLayout.tsx +++ b/packages/x-date-pickers/src/PickersLayout/PickersLayout.tsx @@ -11,7 +11,7 @@ import { PickersLayoutClasses, } from './pickersLayoutClasses'; import usePickerLayout from './usePickerLayout'; -import { DateOrTimeViewWithMeridiem } from '../internals/models'; +import { DateOrTimeViewWithMeridiem, PickerValidValue } from '../internals/models'; import { usePickerContext } from '../hooks/usePickerContext'; const useUtilityClasses = ( @@ -87,7 +87,10 @@ export const PickersLayoutContentWrapper = styled('div', { flexDirection: 'column', }); -type PickersLayoutComponent = (( +type PickersLayoutComponent = (< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +>( props: PickersLayoutProps & React.RefAttributes, ) => React.JSX.Element) & { propTypes?: any }; @@ -101,7 +104,7 @@ type PickersLayoutComponent = ((inProps: PickersLayoutProps, ref: React.Ref) { const props = useThemeProps({ props: inProps, name: 'MuiPickersLayout' }); @@ -179,7 +182,7 @@ PickersLayout.propTypes = { PropTypes.func, PropTypes.object, ]), - value: PropTypes.any, + value: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), view: PropTypes.oneOf(['day', 'hours', 'meridiem', 'minutes', 'month', 'seconds', 'year']), views: PropTypes.arrayOf( PropTypes.oneOf(['day', 'hours', 'meridiem', 'minutes', 'month', 'seconds', 'year']).isRequired, diff --git a/packages/x-date-pickers/src/PickersLayout/PickersLayout.types.ts b/packages/x-date-pickers/src/PickersLayout/PickersLayout.types.ts index bb2b12ba329b..d06b38e2044a 100644 --- a/packages/x-date-pickers/src/PickersLayout/PickersLayout.types.ts +++ b/packages/x-date-pickers/src/PickersLayout/PickersLayout.types.ts @@ -12,10 +12,14 @@ import { PickersShortcuts, } from '../PickersShortcuts/PickersShortcuts'; import { PickerOwnerState } from '../models'; +import { PickerValidValue } from '../internals/models'; import { UsePickerViewsLayoutResponse } from '../internals/hooks/usePicker/usePickerViews'; import { UsePickerValueLayoutResponse } from '../internals/hooks/usePicker/usePickerValue.types'; -export interface ExportedPickersLayoutSlots { +export interface ExportedPickersLayoutSlots< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +> { /** * Custom component for the action bar, it is placed below the picker views. * @default PickersActionBar @@ -43,7 +47,10 @@ export interface PickerLayoutOwnerState extends PickerOwnerState { isRtl: boolean; } -export interface ExportedPickersLayoutSlotProps { +export interface ExportedPickersLayoutSlotProps< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +> { /** * Props passed down to the action bar component. */ @@ -58,8 +65,10 @@ export interface ExportedPickersLayoutSlotProps>; } -export interface PickersLayoutSlots - extends ExportedPickersLayoutSlots { +export interface PickersLayoutSlots< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +> extends ExportedPickersLayoutSlots { /** * Tabs enabling toggling between views. */ @@ -71,8 +80,10 @@ export interface PickersLayoutSlots>; } -export interface PickersLayoutSlotProps - extends ExportedPickersLayoutSlotProps { +export interface PickersLayoutSlotProps< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +> extends ExportedPickersLayoutSlotProps { /** * Props passed down to the tabs component. */ @@ -83,10 +94,11 @@ export interface PickersLayoutSlotProps - extends UsePickerViewsLayoutResponse, - Omit, 'value'> { - value?: TValue; +export interface PickersLayoutProps< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +> extends UsePickerViewsLayoutResponse, + UsePickerValueLayoutResponse { className?: string; children?: React.ReactNode; /** @@ -109,7 +121,7 @@ export interface PickersLayoutProps; } -export interface SubComponents { +export interface SubComponents { toolbar: React.ReactElement | null; content: React.ReactNode; tabs: React.ReactElement | null; diff --git a/packages/x-date-pickers/src/PickersLayout/usePickerLayout.tsx b/packages/x-date-pickers/src/PickersLayout/usePickerLayout.tsx index ae978ffe1a0e..460520f4837a 100644 --- a/packages/x-date-pickers/src/PickersLayout/usePickerLayout.tsx +++ b/packages/x-date-pickers/src/PickersLayout/usePickerLayout.tsx @@ -8,11 +8,11 @@ import { PickerLayoutOwnerState, PickersLayoutProps, SubComponents } from './Pic import { getPickersLayoutUtilityClass, PickersLayoutClasses } from './pickersLayoutClasses'; import { PickersShortcuts } from '../PickersShortcuts'; import { BaseToolbarProps } from '../internals/models/props/toolbar'; -import { DateOrTimeViewWithMeridiem } from '../internals/models'; +import { DateOrTimeViewWithMeridiem, PickerValidValue } from '../internals/models'; import { usePickerPrivateContext } from '../internals/hooks/usePickerPrivateContext'; import { usePickerContext } from '../hooks'; -function toolbarHasView( +function toolbarHasView( toolbarProps: BaseToolbarProps | any, ): toolbarProps is BaseToolbarProps { return toolbarProps.view !== null; @@ -36,16 +36,11 @@ const useUtilityClasses = ( return composeClasses(slots, getPickersLayoutUtilityClass, classes); }; -interface PickersLayoutPropsWithValueRequired - extends PickersLayoutProps { - value: TValue; -} - -interface UsePickerLayoutResponse extends SubComponents { +interface UsePickerLayoutResponse extends SubComponents { ownerState: PickerLayoutOwnerState; } -const usePickerLayout = ( +const usePickerLayout = ( props: PickersLayoutProps, ): UsePickerLayoutResponse => { const { ownerState: pickerOwnerState } = usePickerPrivateContext(); @@ -72,7 +67,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; const ownerState: PickerLayoutOwnerState = { ...pickerOwnerState, isRtl }; const classes = useUtilityClasses(classesProp, ownerState); diff --git a/packages/x-date-pickers/src/PickersShortcuts/PickersShortcuts.tsx b/packages/x-date-pickers/src/PickersShortcuts/PickersShortcuts.tsx index b164341349a3..3a2f28421139 100644 --- a/packages/x-date-pickers/src/PickersShortcuts/PickersShortcuts.tsx +++ b/packages/x-date-pickers/src/PickersShortcuts/PickersShortcuts.tsx @@ -5,12 +5,13 @@ 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 { PickerValidValue } from '../internals/models'; -interface PickersShortcutsItemGetValueParams { +interface PickersShortcutsItemGetValueParams { isValid: (value: TValue) => boolean; } -export interface PickersShortcutsItem { +export interface PickersShortcutsItem { label: string; getValue: (params: PickersShortcutsItemGetValueParams) => TValue; /** @@ -20,11 +21,12 @@ 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. @@ -40,7 +42,8 @@ export interface ExportedPickersShortcutProps extends Omit extends ExportedPickersShortcutProps { +export interface PickersShortcutsProps + extends ExportedPickersShortcutProps { isLandscape: boolean; onChange: ( newValue: TValue, @@ -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 71207b92481b..f84029086259 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(); diff --git a/packages/x-date-pickers/src/TimeClock/tests/describes.TimeClock.test.tsx b/packages/x-date-pickers/src/TimeClock/tests/describes.TimeClock.test.tsx index d7286b18d86b..140d667a2938 100644 --- a/packages/x-date-pickers/src/TimeClock/tests/describes.TimeClock.test.tsx +++ b/packages/x-date-pickers/src/TimeClock/tests/describes.TimeClock.test.tsx @@ -13,6 +13,7 @@ import { describeValue, } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; +import { PickerValue } from '@mui/x-date-pickers/internals'; describe(' - Describes', () => { const { render, clock } = createPickerRenderer(); @@ -26,7 +27,7 @@ describe(' - Describes', () => { skip: ['componentProp', 'componentsProp', 'themeVariants'], })); - describeValue(TimeClock, () => ({ + describeValue(TimeClock, () => ({ render, componentFamily: 'clock', values: [adapterToUse.date('2018-01-01T12:30:00'), adapterToUse.date('2018-01-01T13:35:00')], diff --git a/packages/x-date-pickers/src/TimeField/TimeField.types.ts b/packages/x-date-pickers/src/TimeField/TimeField.types.ts index af41f53ee623..9767d48f47d1 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, @@ -16,15 +11,11 @@ import { } from '../hooks/useClearableField'; import { ExportedValidateTimeProps } from '../validation/validateTime'; import { AmPmProps } from '../internals/models/props/time'; +import { PickerValue } from '../internals/models'; export interface UseTimeFieldProps extends MakeOptional< - UseFieldInternalProps< - PickerValidDate | null, - FieldSection, - TEnableAccessibleFieldDOMStructure, - TimeValidationError - >, + UseFieldInternalProps, 'format' >, ExportedValidateTimeProps, diff --git a/packages/x-date-pickers/src/TimeField/tests/describes.TimeField.test.tsx b/packages/x-date-pickers/src/TimeField/tests/describes.TimeField.test.tsx index 35b9339620ac..515cbd0b2639 100644 --- a/packages/x-date-pickers/src/TimeField/tests/describes.TimeField.test.tsx +++ b/packages/x-date-pickers/src/TimeField/tests/describes.TimeField.test.tsx @@ -11,6 +11,7 @@ import { import { TimeField } from '@mui/x-date-pickers/TimeField'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { describeConformance } from 'test/utils/describeConformance'; +import { PickerValue } from '@mui/x-date-pickers/internals'; describe(' - Describes', () => { const { render, clock } = createPickerRenderer({ clock: 'fake' }); @@ -31,7 +32,7 @@ describe(' - Describes', () => { skip: ['componentProp', 'componentsProp', 'themeVariants', 'themeStyleOverrides'], })); - describeValue(TimeField, () => ({ + describeValue(TimeField, () => ({ render, componentFamily: 'field', values: [adapterToUse.date('2018-01-01'), adapterToUse.date('2018-01-02')], diff --git a/packages/x-date-pickers/src/TimeField/useTimeField.ts b/packages/x-date-pickers/src/TimeField/useTimeField.ts index 5ec3eba335b5..51a88016a8dc 100644 --- a/packages/x-date-pickers/src/TimeField/useTimeField.ts +++ b/packages/x-date-pickers/src/TimeField/useTimeField.ts @@ -7,8 +7,8 @@ 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'; +import { PickerValue } from '../internals/models'; export const useTimeField = < TEnableAccessibleFieldDOMStructure extends boolean, @@ -24,8 +24,7 @@ export const useTimeField = < const { forwardedProps, internalProps } = useSplitFieldProps(props, 'time'); return useField< - PickerValidDate | null, - FieldSection, + PickerValue, 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 787f4c68fba4..03ce715b6e85 100644 --- a/packages/x-date-pickers/src/TimePicker/TimePicker.types.ts +++ b/packages/x-date-pickers/src/TimePicker/TimePicker.types.ts @@ -3,13 +3,13 @@ import { DesktopTimePickerSlots, DesktopTimePickerSlotProps, } from '../DesktopTimePicker'; -import { BaseSingleInputFieldProps, TimeViewWithMeridiem } from '../internals/models'; +import { BaseSingleInputFieldProps, PickerValue, TimeViewWithMeridiem } from '../internals/models'; import { MobileTimePickerProps, MobileTimePickerSlots, MobileTimePickerSlotProps, } from '../MobileTimePicker'; -import { FieldSection, PickerValidDate, TimeValidationError } from '../models'; +import { TimeValidationError } from '../models'; import { ValidateTimeProps } from '../validation/validateTime'; export interface TimePickerSlots @@ -46,9 +46,4 @@ export interface TimePickerProps = ValidateTimeProps & - BaseSingleInputFieldProps< - PickerValidDate | null, - FieldSection, - TEnableAccessibleFieldDOMStructure, - TimeValidationError - >; + BaseSingleInputFieldProps; diff --git a/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx b/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx index 7624ad4271fa..a456281ad7f8 100644 --- a/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx +++ b/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx @@ -18,13 +18,13 @@ import { timePickerToolbarClasses, TimePickerToolbarClasses, } from './timePickerToolbarClasses'; -import { TimeViewWithMeridiem } from '../internals/models'; +import { PickerValue, TimeViewWithMeridiem } from '../internals/models'; import { formatMeridiem } from '../internals/utils/date-utils'; import { PickerValidDate } from '../models'; import { usePickerContext } from '../hooks'; 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 4326cb61e414..281caf40c139 100644 --- a/packages/x-date-pickers/src/TimePicker/shared.tsx +++ b/packages/x-date-pickers/src/TimePicker/shared.tsx @@ -10,12 +10,12 @@ 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'; import { BaseClockProps, ExportedBaseClockProps } from '../internals/models/props/time'; -import { TimeViewWithMeridiem } from '../internals/models'; +import { PickerValue, TimeViewWithMeridiem } from '../internals/models'; import { ValidateTimePropsToDefault } from '../validation/validateTime'; export interface BaseTimePickerSlots extends TimeClockSlots { @@ -34,14 +34,14 @@ export type TimePickerViewRenderers< TView extends TimeViewWithMeridiem, TAdditionalProps extends {} = {}, > = PickerViewRendererLookup< - PickerValidDate | null, + PickerValue, 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/YearCalendar/tests/describes.YearCalendar.test.tsx b/packages/x-date-pickers/src/YearCalendar/tests/describes.YearCalendar.test.tsx index a779c25c2194..448cbb8fe599 100644 --- a/packages/x-date-pickers/src/YearCalendar/tests/describes.YearCalendar.test.tsx +++ b/packages/x-date-pickers/src/YearCalendar/tests/describes.YearCalendar.test.tsx @@ -9,6 +9,7 @@ import { describeValue, } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; +import { PickerValue } from '@mui/x-date-pickers/internals'; describe(' - Describes', () => { const { render, clock } = createPickerRenderer({ @@ -31,7 +32,7 @@ describe(' - Describes', () => { skip: ['componentProp', 'componentsProp', 'themeVariants'], })); - describeValue(YearCalendar, () => ({ + describeValue(YearCalendar, () => ({ render, componentFamily: 'calendar', values: [adapterToUse.date('2018-01-01'), adapterToUse.date('2018-01-01')], diff --git a/packages/x-date-pickers/src/hooks/useParsedFormat.ts b/packages/x-date-pickers/src/hooks/useParsedFormat.ts index 438c3d34a0a0..8e777dd0731f 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 680cf8d90a2e..8c6547123ea4 100644 --- a/packages/x-date-pickers/src/internals/components/PickersToolbar.tsx +++ b/packages/x-date-pickers/src/internals/components/PickersToolbar.tsx @@ -5,10 +5,12 @@ import { styled, useThemeProps } from '@mui/material/styles'; import composeClasses from '@mui/utils/composeClasses'; import { BaseToolbarProps } from '../models/props/toolbar'; import { getPickersToolbarUtilityClass, PickersToolbarClasses } from './pickersToolbarClasses'; -import { DateOrTimeViewWithMeridiem } from '../models'; +import { DateOrTimeViewWithMeridiem, PickerValidValue } from '../models'; -export interface PickersToolbarProps - extends Pick, 'isLandscape' | 'hidden' | 'titleId'> { +export interface PickersToolbarProps< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +> extends Pick, 'isLandscape' | 'hidden' | 'titleId'> { className?: string; landscapeDirection?: 'row' | 'column'; toolbarTitle: React.ReactNode; @@ -83,13 +85,16 @@ const PickersToolbarContent = styled('div', { ], }); -type PickersToolbarComponent = (( +type PickersToolbarComponent = (< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +>( props: React.PropsWithChildren> & React.RefAttributes, ) => React.JSX.Element) & { propTypes?: any }; export const PickersToolbar = React.forwardRef(function PickersToolbar< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, >( inProps: React.PropsWithChildren>, diff --git a/packages/x-date-pickers/src/internals/hooks/useClockReferenceDate.ts b/packages/x-date-pickers/src/internals/hooks/useClockReferenceDate.ts index cef4af021371..f7de8e4de11d 100644 --- a/packages/x-date-pickers/src/internals/hooks/useClockReferenceDate.ts +++ b/packages/x-date-pickers/src/internals/hooks/useClockReferenceDate.ts @@ -3,6 +3,7 @@ import { MuiPickersAdapter, PickersTimezone, PickerValidDate } from '../../model import { singleItemValueManager } from '../utils/valueManagers'; import { getTodayDate } from '../utils/date-utils'; import { SECTION_TYPE_GRANULARITY } from '../utils/getDefaultReferenceDate'; +import { PickerValue } from '../models'; export const useClockReferenceDate = ({ value, @@ -11,7 +12,7 @@ export const useClockReferenceDate = ({ props, timezone, }: { - value: PickerValidDate; + value: PickerValue; 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 4d0ae7f7051c..3ac24e4b6227 100644 --- a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx +++ b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx @@ -8,8 +8,8 @@ import { PickersPopper } from '../../components/PickersPopper'; import { UseDesktopPickerParams, UseDesktopPickerProps } from './useDesktopPicker.types'; import { usePicker } from '../usePicker'; import { PickersLayout } from '../../../PickersLayout'; -import { FieldSection, PickerValidDate, FieldRef, InferError } from '../../../models'; -import { BaseSingleInputFieldProps, DateOrTimeViewWithMeridiem } from '../../models'; +import { FieldRef, InferError } from '../../../models'; +import { DateOrTimeViewWithMeridiem, BaseSingleInputFieldProps, PickerValue } from '../../models'; import { PickerProvider } from '../../components/PickerProvider'; /** @@ -54,7 +54,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; @@ -69,7 +69,7 @@ export const useDesktopPicker = < shouldRestoreFocus, fieldProps: pickerFieldProps, ownerState, - } = usePicker({ + } = usePicker({ ...pickerParams, props, fieldRef, @@ -111,8 +111,7 @@ export const useDesktopPicker = < const Field = slots.field; const fieldProps: BaseSingleInputFieldProps< - PickerValidDate | null, - FieldSection, + PickerValue, TEnableAccessibleFieldDOMStructure, InferError > = useSlotProps({ 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 8aead242e00d..555db1d6308f 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 { - FieldSection, - PickerFieldSlotProps, - PickerOwnerState, - PickerValidDate, -} from '../../../models'; +import { PickerFieldSlotProps, PickerOwnerState, PickerValidDate } from '../../../models'; import { ExportedPickersLayoutSlots, ExportedPickersLayoutSlotProps, @@ -24,7 +19,7 @@ import { } from '../../../PickersLayout/PickersLayout.types'; import { UsePickerValueNonStaticProps } from '../usePicker/usePickerValue.types'; import { UsePickerViewsNonStaticProps, UsePickerViewsProps } from '../usePicker/usePickerViews'; -import { DateOrTimeViewWithMeridiem } from '../../models'; +import { DateOrTimeViewWithMeridiem, PickerValue } from '../../models'; import { UseClearableFieldSlots, UseClearableFieldSlotProps, @@ -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,16 +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< - PickerFieldSlotProps, + PickerFieldSlotProps, {}, PickerOwnerState >; @@ -101,8 +96,8 @@ export interface UseDesktopPickerProps< TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean, TError, - TExternalProps extends UsePickerViewsProps, -> extends BasePickerProps, + TExternalProps extends UsePickerViewsProps, +> extends BasePickerProps, MakeRequired { /** * Overridable component slots. @@ -126,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..8bec0c4e9afa 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useField.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useField.ts @@ -17,28 +17,21 @@ 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'; +import { PickerValidValue } from '../../models'; export const useField = < - TValue, - TSection extends FieldSection, + TValue extends PickerValidValue, TEnableAccessibleFieldDOMStructure extends boolean, TForwardedProps extends UseFieldCommonForwardedProps & UseFieldForwardedProps, - TInternalProps extends UseFieldInternalProps< - any, - any, - TEnableAccessibleFieldDOMStructure, - any - > & { + TInternalProps extends UseFieldInternalProps & { minutesStep?: number; }, >( params: UseFieldParams< TValue, - TSection, TEnableAccessibleFieldDOMStructure, TForwardedProps, TInternalProps @@ -78,7 +71,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 b4909d425fca..e28638917817 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 @@ -10,6 +10,7 @@ import { FieldRef, OnErrorProps, InferError, + InferFieldSection, PickerValueType, } from '../../../models'; import type { PickerValueManager } from '../usePicker'; @@ -18,27 +19,25 @@ import type { UseFieldStateResponse } from './useFieldState'; import type { UseFieldCharacterEditingResponse } from './useFieldCharacterEditing'; import { PickersSectionElement, PickersSectionListRef } from '../../../PickersSectionList'; import { ExportedUseClearableFieldProps } from '../../../hooks/useClearableField'; -import { FormProps } from '../../models'; +import { FormProps, InferNonNullablePickerValue, PickerValidValue } from '../../models'; export interface UseFieldParams< - TValue, - TSection extends FieldSection, + TValue extends PickerValidValue, TEnableAccessibleFieldDOMStructure extends boolean, TForwardedProps extends UseFieldCommonForwardedProps & UseFieldForwardedProps, - TInternalProps extends UseFieldInternalProps, + TInternalProps extends UseFieldInternalProps, > { forwardedProps: TForwardedProps; internalProps: TInternalProps; valueManager: PickerValueManager>; - fieldValueManager: FieldValueManager; + fieldValueManager: FieldValueManager; validator: Validator, TInternalProps>; valueType: PickerValueType; } export interface UseFieldInternalProps< - TValue, - TSection extends FieldSection, + TValue extends PickerValidValue, TEnableAccessibleFieldDOMStructure extends boolean, TError, > extends TimezoneProps, @@ -110,7 +109,7 @@ export interface UseFieldInternalProps< /** * The ref object used to imperatively interact with the field. */ - unstableFieldRef?: React.Ref>; + unstableFieldRef?: React.Ref>; /** * @default true */ @@ -123,7 +122,7 @@ export interface UseFieldInternalProps< } export interface UseFieldCommonAdditionalProps - extends Required, 'disabled' | 'readOnly'>> {} + extends Required, 'disabled' | 'readOnly'>> {} export interface UseFieldCommonForwardedProps extends ExportedUseClearableFieldProps { onKeyDown?: React.KeyboardEventHandler; @@ -206,7 +205,7 @@ export type FieldSectionsBoundaries = { }; }; -export type FieldChangeHandler = ( +export type FieldChangeHandler = ( value: TValue, context: FieldChangeHandlerContext, ) => void; @@ -219,7 +218,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`. */ @@ -229,79 +228,79 @@ interface FieldActiveDateManager { */ referenceDate: PickerValidDate; /** - * @template TSection - * @param {TSection[]} sections The sections of the full value. - * @returns {TSection[]} The sections of the active date. + * @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. + * @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 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. * @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 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. * @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 {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, + 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 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. + * @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 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. + * @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 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. * @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 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. * @param {string} valueStr The string value to parse. * @param {TValue} 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. @@ -309,13 +308,13 @@ export interface FieldValueManager { */ parseValueStr: ( valueStr: string, - referenceValue: TValue, + referenceValue: InferNonNullablePickerValue, parseDate: (dateStr: string, referenceDate: PickerValidDate) => PickerValidDate | null, ) => TValue; /** * 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 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. * @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. @@ -324,18 +323,18 @@ export interface FieldValueManager { updateReferenceValue: ( utils: MuiPickersAdapter, value: TValue, - prevReferenceValue: TValue, - ) => TValue; + prevReferenceValue: InferNonNullablePickerValue, + ) => InferNonNullablePickerValue; } -export interface UseFieldState { +export interface UseFieldState { value: TValue; /** * 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: @@ -414,23 +413,16 @@ export interface UseFieldTextFieldInteractions { } export type UseFieldTextField = < - TValue, - TSection extends FieldSection, + TValue extends PickerValidValue, TForwardedProps extends TEnableAccessibleFieldDOMStructure extends false ? UseFieldV6ForwardedProps : UseFieldV7ForwardedProps, - TInternalProps extends UseFieldInternalProps< - any, - any, - TEnableAccessibleFieldDOMStructure, - any - > & { + TInternalProps extends UseFieldInternalProps & { minutesStep?: number; }, >( params: UseFieldTextFieldParams< TValue, - TSection, TEnableAccessibleFieldDOMStructure, TForwardedProps, TInternalProps @@ -443,21 +435,19 @@ export type UseFieldTextField, + TInternalProps extends UseFieldInternalProps, > extends UseFieldParams< TValue, - TSection, 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 cae26f41e08d..65324fa47abd 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,8 +15,10 @@ import { PickerValidDate, FieldSelectedSections, PickerValueType, + InferFieldSection, } from '../../../models'; import { getMonthsInYear } from '../../utils/date-utils'; +import { PickerValidValue } from '../../models'; export const getDateSectionConfigFromFormatToken = ( utils: MuiPickersAdapter, @@ -230,10 +232,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 +616,8 @@ export const getSectionsBoundaries = ( let warnedOnceInvalidSection = false; -export const validateSections = ( - sections: TSection[], +export const validateSections = ( + sections: InferFieldSection[], valueType: PickerValueType, ) => { 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..a348d3a396b6 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 { @@ -15,6 +20,7 @@ import { isStringNumber, } from './useField.utils'; import { UpdateSectionValueParams } from './useFieldState'; +import { PickerValidValue } from '../../models'; interface CharacterEditingQuery { value: string; @@ -27,9 +33,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 +71,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 +89,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 +123,7 @@ export const useFieldCharacterEditing = ({ const applyQuery = ( { keyPressed, sectionIndex }: ApplyCharacterEditingParams, - getFirstSectionValueMatchingWithQuery: QueryApplier, + getFirstSectionValueMatchingWithQuery: QueryApplier, isValidQueryValue?: (queryValue: string) => boolean, ): ReturnType => { const cleanKeyPressed = keyPressed.toLowerCase(); @@ -170,7 +176,7 @@ export const useFieldCharacterEditing = ({ format: string, options: string[], queryValue: string, - ): ReturnType> => { + ): ReturnType> => { const matchingValues = options.filter((option) => option.toLowerCase().startsWith(queryValue), ); @@ -187,7 +193,7 @@ export const useFieldCharacterEditing = ({ const testQueryOnFormatAndFallbackFormat = ( queryValue: string, - activeSection: TSection, + activeSection: InferFieldSection, fallbackFormat?: string, formatFallbackValue?: (fallbackValue: string, fallbackOptions: string[]) => string, ) => { @@ -225,7 +231,7 @@ export const useFieldCharacterEditing = ({ return { saveQuery: false }; }; - const getFirstSectionValueMatchingWithQuery: QueryApplier = ( + const getFirstSectionValueMatchingWithQuery: QueryApplier = ( queryValue, activeSection, ) => { @@ -284,7 +290,7 @@ export const useFieldCharacterEditing = ({ | 'hasLeadingZerosInInput' | 'maxLength' >, - ): ReturnType> => { + ): ReturnType> => { const cleanQueryValue = removeLocalizedDigits(queryValue, localizedDigits); const queryValueNumber = Number(cleanQueryValue); const sectionBoundaries = sectionsValueBoundaries[section.type]({ @@ -319,7 +325,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 d89b552637ef..a1f3842884f4 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 { PickerValidValue } 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: TValue, + fallbackSections?: InferFieldSection[] | null, + ) => InferFieldSection[]; localizedDigits: string[]; timezone: PickersTimezone; } export const useFieldState = < - TValue, - TSection extends FieldSection, + TValue extends PickerValidValue, TEnableAccessibleFieldDOMStructure extends boolean, TForwardedProps extends UseFieldForwardedProps, - TInternalProps extends UseFieldInternalProps, + TInternalProps extends UseFieldInternalProps, >( params: UseFieldParams< TValue, - TSection, TEnableAccessibleFieldDOMStructure, TForwardedProps, TInternalProps >, -): UseFieldStateResponse => { +): UseFieldStateResponse => { const utils = useUtils(); const translations = usePickerTranslations(); const adapter = useLocalizationContext(); @@ -127,7 +129,7 @@ export const useFieldState = < ); const getSectionsFromValue = React.useCallback( - (value: TValue, fallbackSections: TSection[] | null = null) => + (value: TValue, fallbackSections: InferFieldSection[] | null = null) => fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, (date) => buildSectionsFromFormat({ utils, @@ -154,14 +156,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, }; @@ -204,7 +205,7 @@ export const useFieldState = < value, referenceValue, sections, - }: Pick, 'value' | 'referenceValue' | 'sections'>) => { + }: Pick, 'value' | 'referenceValue' | 'sections'>) => { setState((prevState) => ({ ...prevState, sections, @@ -310,7 +311,7 @@ export const useFieldState = < activeSection, newSectionValue, shouldGoToNextSection, - }: UpdateSectionValueParams) => { + }: UpdateSectionValueParams) => { /** * 1. Decide which section should be focused */ @@ -326,7 +327,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..719a6561ca6a 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,12 @@ 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'; +import { PickerValidValue } from '../../models'; -type FieldSectionWithPositions = TSection & { +type FieldSectionWithPositions = InferFieldSection & { /** * Start index of the section in the format */ @@ -30,14 +31,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 4809144aa6ea..fc1ef14d56be 100644 --- a/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.tsx +++ b/packages/x-date-pickers/src/internals/hooks/useMobilePicker/useMobilePicker.tsx @@ -7,8 +7,8 @@ import { UseMobilePickerParams, UseMobilePickerProps } from './useMobilePicker.t import { usePicker } from '../usePicker'; import { onSpaceOrEnter } from '../../utils/utils'; import { PickersLayout } from '../../../PickersLayout'; -import { FieldSection, PickerValidDate, FieldRef, InferError } from '../../../models'; -import { BaseSingleInputFieldProps, DateOrTimeViewWithMeridiem } from '../../models'; +import { FieldRef, InferError } from '../../../models'; +import { BaseSingleInputFieldProps, DateOrTimeViewWithMeridiem, PickerValue } from '../../models'; import { PickerProvider } from '../../components/PickerProvider'; /** @@ -50,7 +50,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; @@ -63,7 +63,7 @@ export const useMobilePicker = < renderCurrentView, fieldProps: pickerFieldProps, ownerState, - } = usePicker({ + } = usePicker({ ...pickerParams, props, fieldRef, @@ -75,8 +75,7 @@ export const useMobilePicker = < const Field = slots.field; const fieldProps: BaseSingleInputFieldProps< - PickerValidDate | null, - FieldSection, + PickerValue, TEnableAccessibleFieldDOMStructure, InferError > = useSlotProps({ 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 a811500a7a67..b4d04f06e66e 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 { - FieldSection, - PickerFieldSlotProps, - PickerOwnerState, - PickerValidDate, -} from '../../../models'; +import { PickerFieldSlotProps, PickerOwnerState, PickerValidDate } from '../../../models'; import { ExportedPickersLayoutSlots, ExportedPickersLayoutSlotProps, @@ -25,11 +20,11 @@ import { } from '../../../PickersLayout/PickersLayout.types'; import { UsePickerValueNonStaticProps } from '../usePicker/usePickerValue.types'; import { UsePickerViewsNonStaticProps, UsePickerViewsProps } from '../usePicker/usePickerViews'; -import { DateOrTimeViewWithMeridiem } from '../../models'; +import { DateOrTimeViewWithMeridiem, PickerValue } from '../../models'; export interface UseMobilePickerSlots extends PickersModalDialogSlots, - ExportedPickersLayoutSlots { + ExportedPickersLayoutSlots { /** * Component used to enter the date with the keyboard. */ @@ -45,9 +40,9 @@ export interface ExportedUseMobilePickerSlotProps< TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean, > extends PickersModalDialogSlotProps, - ExportedPickersLayoutSlotProps { + ExportedPickersLayoutSlotProps { field?: SlotComponentPropsFromProps< - PickerFieldSlotProps, + PickerFieldSlotProps, {}, PickerOwnerState >; @@ -58,7 +53,7 @@ export interface UseMobilePickerSlotProps< TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean, > extends ExportedUseMobilePickerSlotProps, - Pick, 'toolbar'> {} + Pick, 'toolbar'> {} export interface MobileOnlyPickerProps extends BaseNonStaticPickerProps, @@ -71,7 +66,7 @@ export interface UseMobilePickerProps< TEnableAccessibleFieldDOMStructure extends boolean, TError, TExternalProps extends UsePickerViewsProps, -> extends BasePickerProps, +> extends BasePickerProps, MakeRequired { /** * Overridable component slots. @@ -95,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 441295d6a64c..30b80061a4af 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePicker.ts @@ -2,14 +2,13 @@ import { warnOnce } from '@mui/x-internals/warning'; import { UsePickerParams, UsePickerProps, UsePickerResponse } from './usePicker.types'; import { usePickerValue } from './usePickerValue'; import { usePickerViews } from './usePickerViews'; -import { FieldSection, InferError } from '../../../models'; -import { DateOrTimeViewWithMeridiem } from '../../models'; +import { InferError } from '../../../models'; +import { DateOrTimeViewWithMeridiem, PickerValidValue } from '../../models'; import { usePickerProvider } from './usePickerProvider'; export const usePicker = < - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, - TSection extends FieldSection, TExternalProps extends UsePickerProps, TAdditionalProps extends {}, >({ @@ -23,10 +22,9 @@ export const usePicker = < rendererInterceptor, fieldRef, localeText, -}: UsePickerParams): UsePickerResponse< +}: UsePickerParams): UsePickerResponse< TValue, TView, - TSection, InferError > => { if (process.env.NODE_ENV !== 'production') { @@ -38,7 +36,7 @@ export const usePicker = < ]); } } - const pickerValueResponse = usePickerValue({ + const pickerValueResponse = usePickerValue({ props, valueManager, valueType, @@ -46,13 +44,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 176ba741efc1..37bbb59b667c 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 @@ -10,8 +10,8 @@ import { UsePickerViewsResponse, UsePickerViewsBaseProps, } from './usePickerViews'; -import { FieldSection, PickerOwnerState } from '../../../models'; -import { DateOrTimeViewWithMeridiem } from '../../models'; +import { PickerOwnerState } from '../../../models'; +import { DateOrTimeViewWithMeridiem, PickerValidValue } from '../../models'; import { UsePickerProviderParameters, UsePickerProviderProps, @@ -22,7 +22,7 @@ import { * Props common to all picker headless implementations. */ export interface UsePickerBaseProps< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, TError, TExternalProps extends UsePickerViewsProps, @@ -32,7 +32,7 @@ export interface UsePickerBaseProps< UsePickerProviderProps {} export interface UsePickerProps< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, TError, TExternalProps extends UsePickerViewsProps, @@ -42,9 +42,8 @@ export interface UsePickerProps< UsePickerProviderProps {} export interface UsePickerParams< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, - TSection extends FieldSection, TExternalProps extends UsePickerProps, TAdditionalProps extends {}, > extends Pick< @@ -52,7 +51,7 @@ export interface UsePickerParams< 'valueManager' | 'valueType' | 'variant' | 'validator' >, Pick< - UsePickerViewParams, + UsePickerViewParams, 'additionalViewProps' | 'autoFocusView' | 'rendererInterceptor' | 'fieldRef' >, Pick, 'localeText'> { @@ -60,14 +59,13 @@ export interface UsePickerParams< } export interface UsePickerResponse< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, - TSection extends FieldSection, TError, -> extends Omit, 'viewProps' | 'layoutProps'>, +> extends Omit, 'viewProps' | 'layoutProps'>, Omit, 'layoutProps' | 'views'> { ownerState: PickerOwnerState; providerProps: UsePickerProviderReturnValue; - layoutProps: UsePickerValueResponse['layoutProps'] & + layoutProps: UsePickerValueResponse['layoutProps'] & UsePickerViewsResponse['layoutProps']; } 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 9933c91bb14d..92964972c29a 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerProvider.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerProvider.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; -import { FieldSection, PickerOwnerState } from '../../../models'; +import { PickerOwnerState } from '../../../models'; import { PickerValueManager, UsePickerValueResponse } from './usePickerValue.types'; import { PickerProviderProps, @@ -12,6 +12,7 @@ import { DateOrTimeViewWithMeridiem, FormProps, PickerOrientation, + PickerValidValue, PickerVariant, } from '../../models'; import { useUtils } from '../useUtils'; @@ -58,7 +59,7 @@ export const usePickerOrientation = ( return customOrientation ?? orientation; }; -export function usePickerProvider( +export function usePickerProvider( parameters: UsePickerProviderParameters, ): UsePickerProviderReturnValue { const { props, pickerValueResponse, valueManager, localeText, variant, views } = parameters; @@ -124,10 +125,10 @@ export function usePickerProvider( }; } -export interface UsePickerProviderParameters +export interface UsePickerProviderParameters extends Pick { props: UsePickerProps; - pickerValueResponse: UsePickerValueResponse; + pickerValueResponse: UsePickerValueResponse; valueManager: PickerValueManager; variant: PickerVariant; views: readonly DateOrTimeViewWithMeridiem[]; 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 9814fcf8cf74..6481132bd86f 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,12 +23,13 @@ import { PickerValueUpdaterParams, } from './usePickerValue.types'; import { useValueWithTimezone } from '../useValueWithTimezone'; +import { PickerValidValue } from '../../models'; /** * Decide if the new value should be published * The published value will be passed to `onChange` if defined. */ -const shouldPublishValue = ( +const shouldPublishValue = ( params: PickerValueUpdaterParams, ): boolean => { const { action, hasChanged, dateState, isControlled } = params; @@ -81,7 +82,7 @@ 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 = ( +const shouldCommitValue = ( params: PickerValueUpdaterParams, ): boolean => { const { action, hasChanged, dateState, isControlled, closeOnSelect } = params; @@ -121,7 +122,7 @@ const shouldCommitValue = ( /** * Decide if the picker should be closed after the value is updated. */ -const shouldClosePicker = ( +const shouldClosePicker = ( params: PickerValueUpdaterParams, ): boolean => { const { action, closeOnSelect } = params; @@ -145,8 +146,7 @@ const shouldClosePicker = ( * Manage the value lifecycle of all the pickers. */ export const usePickerValue = < - TValue, - TSection extends FieldSection, + TValue extends PickerValidValue, TExternalProps extends UsePickerValueProps, >({ props, @@ -156,7 +156,6 @@ export const usePickerValue = < validator, }: UsePickerValueParams): UsePickerValueResponse< TValue, - TSection, InferError > => { type TError = InferError; @@ -422,7 +421,7 @@ export const usePickerValue = < onClose: handleClose, }; - const fieldResponse: UsePickerValueFieldResponse = { + const fieldResponse: UsePickerValueFieldResponse = { value: dateState.draft, onChange: handleChangeFromField, }; 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 77356988bd30..1b301efd05be 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 { PickerVariant } from '../../models/common'; import { - FieldSection, TimezoneProps, MuiPickersAdapter, PickersTimezone, @@ -17,11 +16,12 @@ import { PickerShortcutChangeImportance, PickersShortcutsItemContext, } from '../../../PickersShortcuts'; +import { InferNonNullablePickerValue, PickerValidValue } from '../../models'; -export interface PickerValueManager { +export interface PickerValueManager { /** * Determines if two values are equal. - * @template TValue + * @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. * @param {MuiPickersAdapter} utils The adapter. * @param {TValue} valueLeft The first value to compare. * @param {TValue} valueRight The second value to compare. @@ -34,7 +34,7 @@ export interface PickerValueManager { emptyValue: TValue; /** * Method returning the value to set when clicking the "Today" button - * @template TValue + * @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. * @param {MuiPickersAdapter} utils The adapter. * @param {PickersTimezone} timezone The current timezone. * @param {PickerValueType} valueType The type of the value being edited. @@ -46,7 +46,7 @@ export interface PickerValueManager { valueType: PickerValueType, ) => TValue; /** - * @template TValue + * @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. * 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. @@ -66,10 +66,10 @@ export interface PickerValueManager { granularity: number; timezone: PickersTimezone; getTodayDate?: () => PickerValidDate; - }) => TValue; + }) => InferNonNullablePickerValue; /** * Method parsing the input value to replace all invalid dates by `null`. - * @template TValue + * @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. * @param {MuiPickersAdapter} utils The adapter. * @param {TValue} value The value to parse. * @returns {TValue} The value without invalid date. @@ -77,7 +77,7 @@ export interface PickerValueManager { cleanValue: (utils: MuiPickersAdapter, value: TValue) => TValue; /** * Generates the new value, given the previous value and the new proposed value. - * @template TValue + * @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. * @param {MuiPickersAdapter} utils The adapter. * @param {TValue} lastValidDateValue The last valid value. * @param {TValue} value The proposed value. @@ -106,7 +106,7 @@ 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 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. @param {MuiPickersAdapter} utils The utils to manipulate the date. @param {TValue} value The current value. @returns {string | null} The timezone of the current value. @@ -114,7 +114,7 @@ export interface PickerValueManager { getTimezone: (utils: MuiPickersAdapter, value: TValue) => string | null; /** * Change the timezone of the dates inside a value. - @template TValue + * @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. @param {MuiPickersAdapter} utils The utils to manipulate the date. @param {PickersTimezone} timezone The current timezone. @param {TValue} value The value to convert. @@ -125,7 +125,7 @@ export interface PickerValueManager { 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. @@ -156,12 +156,12 @@ export interface UsePickerValueState { hasBeenModifiedSinceMount: boolean; } -export interface PickerValueUpdaterParams { +export interface PickerValueUpdaterParams { action: PickerValueUpdateAction; dateState: UsePickerValueState; /** * Check if the new draft value has changed compared to some given value. - * @template TValue + * @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. * @param {TValue} comparisonValue The value to compare the new draft value with. * @returns {boolean} `true` if the new draft value is equal to the comparison value. */ @@ -170,7 +170,7 @@ export interface PickerValueUpdaterParams { closeOnSelect: boolean; } -export type PickerValueUpdateAction = +export type PickerValueUpdateAction = | { name: 'setValueFromView'; value: TValue; @@ -196,7 +196,8 @@ 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. @@ -254,7 +255,7 @@ export interface UsePickerValueNonStaticProps { /** * Props used to handle the value of the pickers. */ -export interface UsePickerValueProps +export interface UsePickerValueProps extends UsePickerValueBaseProps, UsePickerValueNonStaticProps, TimezoneProps { @@ -263,7 +264,7 @@ export interface UsePickerValueProps } export interface UsePickerValueParams< - TValue, + TValue extends PickerValidValue, TExternalProps extends UsePickerValueProps, > { props: TExternalProps; @@ -283,14 +284,14 @@ 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 { +export interface UsePickerValueViewsResponse { value: TValue; onChange: (value: TValue, selectionState?: PickerSelectionState) => void; open: boolean; @@ -300,7 +301,8 @@ export interface UsePickerValueViewsResponse { /** * Props passed to `usePickerLayoutProps`. */ -export interface UsePickerValueLayoutResponse extends UsePickerValueActions { +export interface UsePickerValueLayoutResponse + extends UsePickerValueActions { value: TValue; onChange: (newValue: TValue) => void; onSelectShortcut: ( @@ -311,10 +313,10 @@ export interface UsePickerValueLayoutResponse extends UsePickerValueActi isValid: (value: TValue) => boolean; } -export interface UsePickerValueResponse { +export interface UsePickerValueResponse { open: boolean; actions: UsePickerValueActions; viewProps: UsePickerValueViewsResponse; - fieldProps: UsePickerValueFieldResponse; + 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 2e5c4abab94e..fe23fa3eb402 100644 --- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerViews.ts +++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerViews.ts @@ -6,14 +6,19 @@ import useEventCallback from '@mui/utils/useEventCallback'; 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 { + DateOrTimeViewWithMeridiem, + PickerRangeValue, + PickerValidValue, + PickerValue, +} from '../../models'; +import { FieldRef, PickerValidDate, TimezoneProps } from '../../../models'; interface PickerViewsRendererBaseExternalProps extends Omit, 'openTo' | 'viewRenderers'> {} export type PickerViewsRendererProps< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, TExternalProps extends PickerViewsRendererBaseExternalProps, TAdditionalProps extends {}, @@ -29,7 +34,7 @@ export type PickerViewsRendererProps< }; export type PickerViewRenderer< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, TExternalProps extends PickerViewsRendererBaseExternalProps, TAdditionalProps extends {}, @@ -38,7 +43,7 @@ export type PickerViewRenderer< ) => React.ReactNode; export type PickerViewRendererLookup< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, TExternalProps extends PickerViewsRendererBaseExternalProps, TAdditionalProps extends {}, @@ -50,7 +55,7 @@ export type PickerViewRendererLookup< * Props used to handle the views that are common to all pickers. */ export interface UsePickerViewsBaseProps< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, TExternalProps extends UsePickerViewsProps, TAdditionalProps extends {}, @@ -88,7 +93,7 @@ export interface UsePickerViewsNonStaticProps { * Props used to handle the value of the pickers. */ export interface UsePickerViewsProps< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, TExternalProps extends UsePickerViewsProps, TAdditionalProps extends {}, @@ -98,9 +103,8 @@ export interface UsePickerViewsProps< } export interface UsePickerViewParams< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, - TSection extends FieldSection, TExternalProps extends UsePickerViewsProps, TAdditionalProps extends {}, > { @@ -108,7 +112,7 @@ export interface UsePickerViewParams< propsFromPickerValue: UsePickerValueViewsResponse; additionalViewProps: TAdditionalProps; autoFocusView: boolean; - fieldRef: React.RefObject> | undefined; + fieldRef: React.RefObject | FieldRef> | undefined; /** * A function that intercepts the regular picker rendering. * Can be used to consume the provided `viewRenderers` and render a custom component wrapping them. @@ -148,9 +152,8 @@ export interface UsePickerViewsLayoutResponse, TAdditionalProps extends {}, >({ @@ -163,7 +166,6 @@ export const usePickerViews = < }: UsePickerViewParams< TValue, TView, - TSection, TExternalProps, TAdditionalProps >): UsePickerViewsResponse => { 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 1464a724d965..0aee5be03535 100644 --- a/packages/x-date-pickers/src/internals/hooks/useStaticPicker/useStaticPicker.tsx +++ b/packages/x-date-pickers/src/internals/hooks/useStaticPicker/useStaticPicker.tsx @@ -6,8 +6,7 @@ import { usePicker } from '../usePicker'; import { PickerProvider } from '../../components/PickerProvider'; import { PickersLayout } from '../../../PickersLayout'; import { DIALOG_WIDTH } from '../../constants/dimensions'; -import { FieldSection, PickerValidDate } from '../../../models'; -import { DateOrTimeViewWithMeridiem } from '../../models'; +import { DateOrTimeViewWithMeridiem, PickerValue } from '../../models'; const PickerStaticLayout = styled(PickersLayout)(({ theme }) => ({ overflow: 'hidden', @@ -32,9 +31,8 @@ export const useStaticPicker = < const { localeText, slots, slotProps, className, sx, displayStaticWrapperAs, autoFocus } = props; const { layoutProps, providerProps, renderCurrentView } = usePicker< - PickerValidDate | null, + PickerValue, 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..aecb74e3eae8 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'; +import { DateOrTimeViewWithMeridiem, PickerValue } 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 852ad3dc5c8d..e54a757521c8 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, PickerValidDate } from '../../models'; +import { PickerValidValue } 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 = < + TValue extends PickerValidValue, + TChange extends (...params: any[]) => void, +>({ timezone: timezoneProp, value: valueProp, defaultValue, @@ -63,7 +67,10 @@ export const useValueWithTimezone = void>({ +export const useControlledValueWithTimezone = < + TValue extends PickerValidValue, + TChange extends (...params: any[]) => void, +>({ name, timezone: timezoneProp, value: valueProp, @@ -94,7 +101,10 @@ export const useControlledValueWithTimezone = void> { +interface UseValueWithTimezoneParameters< + TValue extends PickerValidValue, + TChange extends (...params: any[]) => void, +> { timezone: PickersTimezone | undefined; value: TValue | undefined; defaultValue: TValue | undefined; @@ -109,7 +119,7 @@ interface UseValueWithTimezoneParameters void, > extends UseValueWithTimezoneParameters { name: string; diff --git a/packages/x-date-pickers/src/internals/hooks/useViews.tsx b/packages/x-date-pickers/src/internals/hooks/useViews.tsx index cf72cc620f30..b26dc412b36c 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, PickerValidValue } from '../models'; import { PickerValidDate } from '../../models'; export type PickerOnChangeFn = ( @@ -11,7 +11,10 @@ export type PickerOnChangeFn = ( selectionState?: PickerSelectionState, ) => void; -export interface UseViewsOptions { +export interface UseViewsOptions< + TValue extends PickerValidValue, + 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. @@ -63,12 +66,17 @@ export interface UseViewsOptions void; } -export interface ExportedUseViewsOptions - extends MakeOptional, 'onChange' | 'openTo' | 'views'> {} +export interface ExportedUseViewsOptions< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +> extends MakeOptional, 'onChange' | 'openTo' | 'views'> {} let warnedOnceNotValidView = false; -interface UseViewsResponse { +interface UseViewsResponse< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +> { view: TView; setView: (view: TView) => void; focusedView: TView | null; @@ -84,7 +92,10 @@ interface UseViewsResponse { ) => void; } -export function useViews({ +export function useViews< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +>({ onChange, onViewChange, openTo, diff --git a/packages/x-date-pickers/src/internals/index.ts b/packages/x-date-pickers/src/internals/index.ts index 58791c5d2476..73086c769fcb 100644 --- a/packages/x-date-pickers/src/internals/index.ts +++ b/packages/x-date-pickers/src/internals/index.ts @@ -96,7 +96,8 @@ export type { ExportedUseViewsOptions, UseViewsOptions } from './hooks/useViews' export { useViews } from './hooks/useViews'; export { usePreviousMonthDisabled, useNextMonthDisabled } from './hooks/date-helpers-hooks'; -export type { BaseSingleInputFieldProps } from './models/fields'; +export type { RangePosition } from './models/pickers'; +export type { BaseSingleInputFieldProps, FieldRangeSection } from './models/fields'; export type { BasePickerProps, BasePickerInputProps, @@ -120,7 +121,13 @@ export type { DayValidationProps, DateTimeValidationProps, } from './models/validation'; -export type { PickerRangeValue } from './models/value'; +export type { + PickerValue, + PickerRangeValue, + PickerNonNullableRangeValue, + InferNonNullablePickerValue, + PickerValidValue, +} 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 5e8e5102cf3e..b7476ca12f04 100644 --- a/packages/x-date-pickers/src/internals/models/fields.ts +++ b/packages/x-date-pickers/src/internals/models/fields.ts @@ -7,6 +7,12 @@ import type { } from '../../hooks/useClearableField'; import type { FieldSection, PickerOwnerState } from '../../models'; import type { UseFieldInternalProps } from '../hooks/useField'; +import { RangePosition } from './pickers'; +import { PickerValidValue } from './value'; + +export interface FieldRangeSection extends FieldSection { + dateName: RangePosition; +} export interface BaseForwardedSingleInputFieldProps extends ExportedUseClearableFieldProps { className: string | undefined; @@ -39,13 +45,12 @@ export interface BaseForwardedSingleInputFieldProps extends ExportedUseClearable * Only contains what the MUI components are passing to the field, not what users can pass using the `props.slotProps.field`. */ export type BaseSingleInputFieldProps< - TValue, - TSection extends FieldSection, + TValue extends PickerValidValue, TEnableAccessibleFieldDOMStructure extends boolean, TError, > = MakeRequired< Pick< - UseFieldInternalProps, + UseFieldInternalProps, | 'readOnly' | 'disabled' | 'format' 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..c4fef0bdaa15 100644 --- a/packages/x-date-pickers/src/internals/models/props/basePickerProps.tsx +++ b/packages/x-date-pickers/src/internals/models/props/basePickerProps.tsx @@ -7,12 +7,13 @@ import { PickersInputComponentLocaleText } from '../../../locales/utils/pickersL import type { UsePickerViewsProps } from '../../hooks/usePicker/usePickerViews'; import { DateOrTimeViewWithMeridiem } from '../common'; import { UseFieldInternalProps } from '../../hooks/useField'; +import { PickerValidValue } from '../value'; /** * Props common to all pickers after applying the default props on each picker. */ export interface BasePickerProps< - TValue, + TValue extends PickerValidValue, TView extends DateOrTimeViewWithMeridiem, TError, TExternalProps extends UsePickerViewsProps, @@ -33,8 +34,11 @@ export interface BasePickerProps< /** * Props common to all pickers before applying the default props on each picker. */ -export interface BasePickerInputProps - extends Omit< +export interface BasePickerInputProps< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, + TError, +> extends Omit< MakeOptional, 'openTo' | 'views'>, 'viewRenderers' > {} @@ -46,7 +50,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 1036bc0aeb33..81583861b148 100644 --- a/packages/x-date-pickers/src/internals/models/props/time.ts +++ b/packages/x-date-pickers/src/internals/models/props/time.ts @@ -6,6 +6,7 @@ import type { ExportedUseViewsOptions } from '../../hooks/useViews'; import { TimeViewWithMeridiem } from '../common'; import { ExportedValidateTimeProps } from '../../../validation/validateTime'; import { FormProps } from '../formProps'; +import { PickerValue } from '../value'; export interface AmPmProps { /** @@ -21,7 +22,7 @@ export interface ExportedBaseClockProps AmPmProps {} export interface BaseClockProps - extends ExportedUseViewsOptions, + extends ExportedUseViewsOptions, ExportedBaseClockProps, FormProps { 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 de6a20208448..9b0a82632df9 100644 --- a/packages/x-date-pickers/src/internals/models/props/toolbar.ts +++ b/packages/x-date-pickers/src/internals/models/props/toolbar.ts @@ -2,9 +2,12 @@ import * as React from 'react'; import { SxProps } from '@mui/system'; import { Theme } from '@mui/material/styles'; import { DateOrTimeViewWithMeridiem } from '../common'; +import { PickerValidValue } from '../value'; -export interface BaseToolbarProps - extends ExportedBaseToolbarProps { +export interface BaseToolbarProps< + TValue extends PickerValidValue, + TView extends DateOrTimeViewWithMeridiem, +> extends ExportedBaseToolbarProps { isLandscape: boolean; onChange: (newValue: TValue) => void; value: TValue; diff --git a/packages/x-date-pickers/src/internals/models/value.ts b/packages/x-date-pickers/src/internals/models/value.ts index 7429c2df5c39..e5500f488ec9 100644 --- a/packages/x-date-pickers/src/internals/models/value.ts +++ b/packages/x-date-pickers/src/internals/models/value.ts @@ -1,5 +1,22 @@ import { PickerValidDate } from '../../models/pickers'; +/** + * The type that the `value` and `defaultValue` props can receive on non-range components (date, time and date-time). + */ export type PickerValue = PickerValidDate | null; +/** + * The type that the `value` and `defaultValue` props can receive on range components (date-range, time-range and date-time-range). + */ export type PickerRangeValue = [PickerValidDate | null, PickerValidDate | null]; + +export type PickerNonNullableRangeValue = [PickerValidDate, PickerValidDate]; + +export type PickerValidValue = PickerValue | PickerRangeValue; + +export type InferNonNullablePickerValue = + TValue extends PickerRangeValue + ? TValue extends PickerValue + ? 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 bdd7540c6f5c..299afe36e284 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..ae9a8d91ad70 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'; @@ -12,11 +7,11 @@ import { createDateStrForV7HiddenInputFromSections, createDateStrForV6InputFromSections, } from '../hooks/useField/useField.utils'; +import { PickerValue } from '../models'; export type SingleItemPickerValueManager< - TValue = any, TError extends DateValidationError | TimeValidationError | DateTimeValidationError = any, -> = PickerValueManager; +> = PickerValueManager; export const singleItemValueManager: SingleItemPickerValueManager = { emptyValue: null, @@ -43,7 +38,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 +48,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 aaff817b403e..55f14ebdce1a 100644 --- a/packages/x-date-pickers/src/models/fields.ts +++ b/packages/x-date-pickers/src/models/fields.ts @@ -7,7 +7,12 @@ import type { import { ExportedPickersSectionListProps } from '../PickersSectionList'; import type { UseFieldInternalProps, UseFieldResponse } from '../internals/hooks/useField'; import type { PickersTextFieldProps } from '../PickersTextField'; -import { BaseForwardedSingleInputFieldProps } from '../internals/models'; +import { + BaseForwardedSingleInputFieldProps, + FieldRangeSection, + PickerRangeValue, + PickerValidValue, +} from '../internals/models'; // Update PickersComponentAgnosticLocaleText -> viewNames when adding new entries export type FieldSectionType = @@ -86,12 +91,22 @@ export interface FieldSection { endSeparator: string; } -export interface FieldRef { +// If `PickerValidDate` contains `any`, then `TValue extends PickerRangeValue` will return true, so we have to handle this edge case first. +type IsAny = boolean extends (T extends never ? true : false) ? true : false; + +export type InferFieldSection = + IsAny extends true + ? FieldSection + : TValue extends PickerRangeValue + ? 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`. @@ -121,12 +136,11 @@ export type FieldSelectedSections = number | FieldSectionType | null | 'all'; * Props the prop `slotProps.field` of a picker can receive. */ export type PickerFieldSlotProps< - TValue, - TSection extends FieldSection, + TValue extends PickerValidValue, TEnableAccessibleFieldDOMStructure extends boolean, > = ExportedUseClearableFieldProps & Pick< - UseFieldInternalProps, + UseFieldInternalProps, 'shouldRespectLeadingZeros' | 'readOnly' > & React.HTMLAttributes & { diff --git a/packages/x-date-pickers/src/models/validation.ts b/packages/x-date-pickers/src/models/validation.ts index 5dcee050db5f..04833a901699 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 { PickerValidValue } from '../internals/models'; + /** * Validation error types applicable to both date and time validation */ @@ -22,7 +24,7 @@ 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. diff --git a/packages/x-date-pickers/src/themeAugmentation/props.d.ts b/packages/x-date-pickers/src/themeAugmentation/props.d.ts index 9fb69436bbad..f5bdfe45dade 100644 --- a/packages/x-date-pickers/src/themeAugmentation/props.d.ts +++ b/packages/x-date-pickers/src/themeAugmentation/props.d.ts @@ -52,6 +52,7 @@ import { PickersFilledInputProps, } from '../PickersTextField'; import { PickersSectionListProps } from '../PickersSectionList'; +import { PickerValidValue } from '../internals/models'; export interface PickersComponentsPropsList { MuiClock: ClockProps; @@ -77,10 +78,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..f9708c1f6363 100644 --- a/packages/x-date-pickers/src/validation/useValidation.ts +++ b/packages/x-date-pickers/src/validation/useValidation.ts @@ -5,8 +5,9 @@ import { useLocalizationContext } from '../internals/hooks/useUtils'; import { MuiPickersAdapterContextValue } from '../LocalizationProvider/LocalizationProvider'; import { OnErrorProps, PickersTimezone } from '../models'; import type { PickerValueManager } from '../internals/hooks/usePicker'; +import { PickerValidValue } from '../internals/models'; -export type Validator = { +export type Validator = { (params: { adapter: MuiPickersAdapterContextValue; value: TValue; @@ -16,7 +17,7 @@ export type Validator = { valueManager: PickerValueManager; }; -interface UseValidationOptions +interface UseValidationOptions extends OnErrorProps { /** * The value to validate. @@ -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,7 +55,7 @@ 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. + * @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. * @param {TValue} newValue The value to validate. * @returns {TError} The validation error associated to the new value. */ @@ -63,7 +64,7 @@ interface UseValidationReturnValue { /** * 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 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 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. @@ -72,7 +73,7 @@ interface UseValidationReturnValue { * @param {TValidationProps} options.props The validation props, they differ depending on the component. * @param {(error: TError, value: TValue) => void} options.onError Callback fired when the error associated with the current value changes. */ -export function useValidation( +export function useValidation( options: UseValidationOptions, ): UseValidationReturnValue { const { props, validator, value, timezone, onError } = options; diff --git a/packages/x-date-pickers/src/validation/validateDate.ts b/packages/x-date-pickers/src/validation/validateDate.ts index aae7114967d8..055fa29f7a20 100644 --- a/packages/x-date-pickers/src/validation/validateDate.ts +++ b/packages/x-date-pickers/src/validation/validateDate.ts @@ -6,9 +6,10 @@ 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'; +import { PickerValue } from '../internals/models'; /** * Validation props used by the Date Picker, Date Field and Date Calendar components. @@ -30,11 +31,12 @@ export interface ValidateDateProps */ export type ValidateDatePropsToDefault = keyof BaseDateValidationProps; -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 f1827fc83b72..66d898275339 100644 --- a/packages/x-date-pickers/src/validation/validateDateTime.ts +++ b/packages/x-date-pickers/src/validation/validateDateTime.ts @@ -11,9 +11,10 @@ import { ValidateTimeProps, ValidateTimePropsToDefault, } from './validateTime'; -import { DateTimeValidationError, PickerValidDate } from '../models'; +import { DateTimeValidationError } from '../models'; import { singleItemValueManager } from '../internals/utils/valueManagers'; import { DateTimeValidationProps } from '../internals/models/validation'; +import { PickerValue } from '../internals/models'; /** * Validation props used by the Date Time Picker and Date Time Field components. @@ -36,7 +37,7 @@ export type ValidateDateTimePropsToDefault = | ValidateTimePropsToDefault; export const validateDateTime: Validator< - PickerValidDate | null, + PickerValue, DateTimeValidationError, ValidateDateTimeProps > = ({ adapter, value, timezone, props }) => { diff --git a/packages/x-date-pickers/src/validation/validateTime.ts b/packages/x-date-pickers/src/validation/validateTime.ts index c27c31e5614e..72982ea2184a 100644 --- a/packages/x-date-pickers/src/validation/validateTime.ts +++ b/packages/x-date-pickers/src/validation/validateTime.ts @@ -2,8 +2,9 @@ import type { MakeRequired } from '@mui/x-internals/types'; 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'; +import { PickerValue } from '../internals/models'; /** * Validation props used by the Time Picker, Time Field and Clock components. @@ -21,11 +22,12 @@ export interface ValidateTimeProps */ export type ValidateTimePropsToDefault = keyof BaseTimeValidationProps; -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/scripts/x-date-pickers-pro.exports.json b/scripts/x-date-pickers-pro.exports.json index 1ea478a0b8c3..8e98bb949249 100644 --- a/scripts/x-date-pickers-pro.exports.json +++ b/scripts/x-date-pickers-pro.exports.json @@ -157,6 +157,7 @@ { "name": "ExportedUseClearableFieldProps", "kind": "Interface" }, { "name": "extractValidationProps", "kind": "Variable" }, { "name": "FieldFormatTokenMap", "kind": "TypeAlias" }, + { "name": "FieldRangeSection", "kind": "Interface" }, { "name": "FieldRef", "kind": "Interface" }, { "name": "FieldSection", "kind": "Interface" }, { "name": "FieldSectionContentType", "kind": "TypeAlias" }, @@ -186,6 +187,7 @@ { "name": "getTimeClockUtilityClass", "kind": "Function" }, { "name": "getYearCalendarUtilityClass", "kind": "Function" }, { "name": "InferError", "kind": "TypeAlias" }, + { "name": "InferFieldSection", "kind": "TypeAlias" }, { "name": "LocalizationProvider", "kind": "Variable" }, { "name": "LocalizationProviderProps", "kind": "Interface" }, { "name": "LocalizedComponent", "kind": "TypeAlias" }, @@ -337,7 +339,6 @@ { "name": "PickerValidDateLookup", "kind": "Interface" }, { "name": "PickerValueType", "kind": "TypeAlias" }, { "name": "PropsFromSlot", "kind": "TypeAlias" }, - { "name": "RangeFieldSection", "kind": "Interface" }, { "name": "RangeFieldSeparatorProps", "kind": "Interface" }, { "name": "RangePosition", "kind": "TypeAlias" }, { "name": "renderDateRangeViewCalendar", "kind": "Variable" }, diff --git a/scripts/x-date-pickers.exports.json b/scripts/x-date-pickers.exports.json index 0a7b338d04d4..91f2417b53db 100644 --- a/scripts/x-date-pickers.exports.json +++ b/scripts/x-date-pickers.exports.json @@ -125,6 +125,7 @@ { "name": "getTimeClockUtilityClass", "kind": "Function" }, { "name": "getYearCalendarUtilityClass", "kind": "Function" }, { "name": "InferError", "kind": "TypeAlias" }, + { "name": "InferFieldSection", "kind": "TypeAlias" }, { "name": "LocalizationProvider", "kind": "Variable" }, { "name": "LocalizationProviderProps", "kind": "Interface" }, { "name": "LocalizedComponent", "kind": "TypeAlias" }, diff --git a/test/utils/pickers/describeValue/describeValue.tsx b/test/utils/pickers/describeValue/describeValue.tsx index 766fe523f9d0..7565a92501cf 100644 --- a/test/utils/pickers/describeValue/describeValue.tsx +++ b/test/utils/pickers/describeValue/describeValue.tsx @@ -1,6 +1,10 @@ import * as React from 'react'; import createDescribe from '@mui/internal-test-utils/createDescribe'; -import { BasePickerInputProps, UsePickerValueNonStaticProps } from '@mui/x-date-pickers/internals'; +import { + BasePickerInputProps, + PickerValidValue, + UsePickerValueNonStaticProps, +} from '@mui/x-date-pickers/internals'; import { buildFieldInteractions, BuildFieldInteractionsResponse } from 'test/utils/pickers'; import { PickerComponentFamily } from '../describe.types'; import { DescribeValueOptions, DescribeValueTestSuite } from './describeValue.types'; @@ -16,7 +20,7 @@ const TEST_SUITES: DescribeValueTestSuite[] = [ testShortcuts, ]; -function innerDescribeValue( +function innerDescribeValue( ElementToTest: React.FunctionComponent, getOptions: () => DescribeValueOptions, ) { @@ -68,19 +72,24 @@ function innerDescribeValue( } TEST_SUITES.forEach((testSuite) => { - testSuite(WrappedElementToTest, { ...options, renderWithProps }); + const typedTestSuite = testSuite as DescribeValueTestSuite; + typedTestSuite(WrappedElementToTest, { ...options, renderWithProps }); }); } -type P = [ +type P = [ React.FunctionComponent, () => 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/describeValue/describeValue.types.ts b/test/utils/pickers/describeValue/describeValue.types.ts index 27332ec2b719..c1cb3b358d3f 100644 --- a/test/utils/pickers/describeValue/describeValue.types.ts +++ b/test/utils/pickers/describeValue/describeValue.types.ts @@ -1,5 +1,6 @@ import * as React from 'react'; import { createRenderer, MuiRenderResult } from '@mui/internal-test-utils/createRenderer'; +import { InferNonNullablePickerValue, PickerValidValue } from '@mui/x-date-pickers/internals'; import { BuildFieldInteractionsResponse, FieldPressCharacter, @@ -8,11 +9,14 @@ import { } from 'test/utils/pickers'; import { PickerComponentFamily } from '../describe.types'; -interface DescribeValueBaseOptions { +interface DescribeValueBaseOptions< + TValue extends PickerValidValue, + C extends PickerComponentFamily, +> { componentFamily: C; render: (node: React.ReactElement) => MuiRenderResult; assertRenderedValue: (expectedValue: TValue) => void; - values: [TValue, TValue]; + values: [InferNonNullablePickerValue, InferNonNullablePickerValue]; emptyValue: TValue; defaultProps?: object; // TODO: Export `Clock` from monorepo @@ -21,12 +25,12 @@ interface DescribeValueBaseOptions { export type DescribeValueOptions< C extends PickerComponentFamily, - TValue, + TValue extends PickerValidValue, > = DescribeValueBaseOptions & (C extends 'picker' ? OpenPickerParams & { setNewValue: ( - value: TValue, + value: InferNonNullablePickerValue, options: { selectSection: FieldSectionSelector; pressKey: FieldPressCharacter; @@ -34,7 +38,7 @@ export type DescribeValueOptions< applySameValue?: boolean; setEndDate?: boolean; }, - ) => TValue; + ) => InferNonNullablePickerValue; } : { setNewValue: ( @@ -43,7 +47,10 @@ export type DescribeValueOptions< ) => TValue; }); -export type DescribeValueTestSuite = ( +export type DescribeValueTestSuite< + TValue extends PickerValidValue, + C extends PickerComponentFamily, +> = ( ElementToTest: React.FunctionComponent, options: DescribeValueOptions & { renderWithProps: BuildFieldInteractionsResponse['renderWithProps']; diff --git a/test/utils/pickers/describeValue/testPickerActionBar.tsx b/test/utils/pickers/describeValue/testPickerActionBar.tsx index c223c52d2331..7497f806866c 100644 --- a/test/utils/pickers/describeValue/testPickerActionBar.tsx +++ b/test/utils/pickers/describeValue/testPickerActionBar.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { fireEvent, screen } from '@mui/internal-test-utils'; +import { PickerRangeValue } from '@mui/x-date-pickers/internals'; import { adapterToUse, getExpectedOnChangeCount, @@ -106,7 +107,7 @@ export const testPickerActionBar: DescribeValueTestSuite = ( getExpectedOnChangeCount(componentFamily, pickerParams) + 1, ); if (isRangeType) { - values[0].forEach((value, index) => { + (values[0] as PickerRangeValue).forEach((value, index) => { expect(onChange.lastCall.args[0][index]).toEqualDateTime(value); }); } else { diff --git a/test/utils/pickers/describeValue/testPickerOpenCloseLifeCycle.tsx b/test/utils/pickers/describeValue/testPickerOpenCloseLifeCycle.tsx index 9896bd8da947..8a5601814ce2 100644 --- a/test/utils/pickers/describeValue/testPickerOpenCloseLifeCycle.tsx +++ b/test/utils/pickers/describeValue/testPickerOpenCloseLifeCycle.tsx @@ -2,11 +2,12 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { fireEvent, screen } from '@mui/internal-test-utils'; +import { PickerRangeValue, PickerValidValue } from '@mui/x-date-pickers/internals'; import { getExpectedOnChangeCount, getFieldInputRoot, openPicker } from 'test/utils/pickers'; import { DescribeValueTestSuite } from './describeValue.types'; import { fireUserEvent } from '../../fireUserEvent'; -export const testPickerOpenCloseLifeCycle: DescribeValueTestSuite = ( +export const testPickerOpenCloseLifeCycle: DescribeValueTestSuite = ( ElementToTest, options, ) => { @@ -78,7 +79,7 @@ export const testPickerOpenCloseLifeCycle: DescribeValueTestSuite selectSection, pressKey, }); - newValue.forEach((value, index) => { + (newValue as PickerRangeValue).forEach((value, index) => { expect(onChange.lastCall.args[0][index]).toEqualDateTime(value); }); } else { @@ -136,7 +137,7 @@ export const testPickerOpenCloseLifeCycle: DescribeValueTestSuite selectSection, pressKey, }); - newValue.forEach((value, index) => { + (newValue as PickerRangeValue).forEach((value, index) => { expect(onChange.lastCall.args[0][index]).toEqualDateTime(value); }); } else { @@ -212,7 +213,7 @@ export const testPickerOpenCloseLifeCycle: DescribeValueTestSuite selectSection, pressKey, }); - newValue.forEach((value, index) => { + (newValue as PickerRangeValue).forEach((value, index) => { expect(onChange.lastCall.args[0][index]).toEqualDateTime(value); }); } else { @@ -235,7 +236,7 @@ export const testPickerOpenCloseLifeCycle: DescribeValueTestSuite selectSection, pressKey, }); - newValueBis.forEach((value, index) => { + (newValueBis as PickerRangeValue).forEach((value, index) => { expect(onChange.lastCall.args[0][index]).toEqualDateTime(value); }); } else { @@ -277,7 +278,7 @@ export const testPickerOpenCloseLifeCycle: DescribeValueTestSuite expect(onChange.callCount).to.equal(getExpectedOnChangeCount(componentFamily, pickerParams)); expect(onAccept.callCount).to.equal(1); if (isRangeType) { - newValue.forEach((value, index) => { + (newValue as PickerRangeValue).forEach((value, index) => { expect(onChange.lastCall.args[0][index]).toEqualDateTime(value); }); } else { diff --git a/test/utils/pickers/fields.tsx b/test/utils/pickers/fields.tsx index 5b552398c467..052d39f1e032 100644 --- a/test/utils/pickers/fields.tsx +++ b/test/utils/pickers/fields.tsx @@ -2,9 +2,10 @@ 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 { PickerValue } from '@mui/x-date-pickers/internals'; import { fireUserEvent } from '../fireUserEvent'; import { expectFieldValueV7, expectFieldValueV6 } from './assertions'; @@ -88,10 +89,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 = {