diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts index 75ae6ce7b018b..e78b7619d0642 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/useSingleInputDateRangeField.ts @@ -1,40 +1,37 @@ 'use client'; import * as React from 'react'; -import { useField, useDefaultizedDateField } from '@mui/x-date-pickers/internals'; +import { useField, useFieldInternalPropsWithDefaults } from '@mui/x-date-pickers/internals'; import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { UseSingleInputDateRangeFieldProps } from './SingleInputDateRangeField.types'; -import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; -import { validateDateRange } from '../validation'; +import { getDateRangeValueManager } from '../valueManagers'; export const useSingleInputDateRangeField = < TEnableAccessibleFieldDOMStructure extends boolean, TAllProps extends UseSingleInputDateRangeFieldProps, >( - inProps: TAllProps, + props: TAllProps, ) => { - const props = useDefaultizedDateField< - UseSingleInputDateRangeFieldProps, - TAllProps - >(inProps); + const valueManager = React.useMemo( + () => + getDateRangeValueManager({ + enableAccessibleFieldDOMStructure: props.enableAccessibleFieldDOMStructure, + dateSeparator: props.dateSeparator, + }), + [props.enableAccessibleFieldDOMStructure, props.dateSeparator], + ); const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date'); + const internalPropsWithDefaults = useFieldInternalPropsWithDefaults({ + valueManager, + internalProps, + }); - const fieldValueManager = React.useMemo( - () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), - [internalProps.dateSeparator], - ); - - return useField< - true, - TEnableAccessibleFieldDOMStructure, - typeof forwardedProps, - typeof internalProps - >({ + return useField({ forwardedProps, - internalProps, - valueManager: rangeValueManager, - fieldValueManager, - validator: validateDateRange, - valueType: 'date', + internalProps: internalPropsWithDefaults, + valueManager: valueManager.legacyValueManager, + fieldValueManager: valueManager.fieldValueManager, + validator: valueManager.validator, + valueType: valueManager.valueType, }); }; diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts index 2e2dc22065a56..a086e78fb6aa3 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/useSingleInputDateTimeRangeField.ts @@ -1,40 +1,37 @@ 'use client'; import * as React from 'react'; -import { useField, useDefaultizedDateTimeField } from '@mui/x-date-pickers/internals'; +import { useField, useFieldInternalPropsWithDefaults } from '@mui/x-date-pickers/internals'; import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { UseSingleInputDateTimeRangeFieldProps } from './SingleInputDateTimeRangeField.types'; -import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; -import { validateDateTimeRange } from '../validation'; +import { getDateTimeRangeValueManager } from '../valueManagers'; export const useSingleInputDateTimeRangeField = < TEnableAccessibleFieldDOMStructure extends boolean, TAllProps extends UseSingleInputDateTimeRangeFieldProps, >( - inProps: TAllProps, + props: TAllProps, ) => { - const props = useDefaultizedDateTimeField< - UseSingleInputDateTimeRangeFieldProps, - TAllProps - >(inProps); - - const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date-time'); - - const fieldValueManager = React.useMemo( - () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), - [internalProps.dateSeparator], + const valueManager = React.useMemo( + () => + getDateTimeRangeValueManager({ + enableAccessibleFieldDOMStructure: props.enableAccessibleFieldDOMStructure, + dateSeparator: props.dateSeparator, + }), + [props.enableAccessibleFieldDOMStructure, props.dateSeparator], ); - return useField< - true, - TEnableAccessibleFieldDOMStructure, - typeof forwardedProps, - typeof internalProps - >({ - forwardedProps, + const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date'); + const internalPropsWithDefaults = useFieldInternalPropsWithDefaults({ + valueManager, internalProps, - valueManager: rangeValueManager, - fieldValueManager, - validator: validateDateTimeRange, - valueType: 'date-time', + }); + + return useField({ + forwardedProps, + internalProps: internalPropsWithDefaults, + valueManager: valueManager.legacyValueManager, + fieldValueManager: valueManager.fieldValueManager, + validator: valueManager.validator, + valueType: valueManager.valueType, }); }; diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts index 2c1933eae3e61..a16ea536a9161 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/useSingleInputTimeRangeField.ts @@ -1,40 +1,37 @@ 'use client'; import * as React from 'react'; -import { useField, useDefaultizedTimeField } from '@mui/x-date-pickers/internals'; +import { useField, useFieldInternalPropsWithDefaults } from '@mui/x-date-pickers/internals'; import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { UseSingleInputTimeRangeFieldProps } from './SingleInputTimeRangeField.types'; -import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers'; -import { validateTimeRange } from '../validation'; +import { getTimeRangeValueManager } from '../valueManagers'; export const useSingleInputTimeRangeField = < TEnableAccessibleFieldDOMStructure extends boolean, TAllProps extends UseSingleInputTimeRangeFieldProps, >( - inProps: TAllProps, + props: TAllProps, ) => { - const props = useDefaultizedTimeField< - UseSingleInputTimeRangeFieldProps, - TAllProps - >(inProps); - - const { forwardedProps, internalProps } = useSplitFieldProps(props, 'time'); - - const fieldValueManager = React.useMemo( - () => getRangeFieldValueManager({ dateSeparator: internalProps.dateSeparator }), - [internalProps.dateSeparator], + const valueManager = React.useMemo( + () => + getTimeRangeValueManager({ + enableAccessibleFieldDOMStructure: props.enableAccessibleFieldDOMStructure, + dateSeparator: props.dateSeparator, + }), + [props.enableAccessibleFieldDOMStructure, props.dateSeparator], ); - return useField< - true, - TEnableAccessibleFieldDOMStructure, - typeof forwardedProps, - typeof internalProps - >({ - forwardedProps, + const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date'); + const internalPropsWithDefaults = useFieldInternalPropsWithDefaults({ + valueManager, internalProps, - valueManager: rangeValueManager, - fieldValueManager, - validator: validateTimeRange, - valueType: 'time', + }); + + return useField({ + forwardedProps, + internalProps: internalPropsWithDefaults, + valueManager: valueManager.legacyValueManager, + fieldValueManager: valueManager.fieldValueManager, + validator: valueManager.validator, + valueType: valueManager.valueType, }); }; 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 1f48ae602878a..b37a65dd39e99 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 @@ -1,3 +1,4 @@ +import * as React from 'react'; import useEventCallback from '@mui/utils/useEventCallback'; import { unstable_useDateField as useDateField } from '@mui/x-date-pickers/DateField'; import { @@ -6,26 +7,24 @@ import { PickerRangeValue, UseFieldResponse, useControlledValueWithTimezone, - useDefaultizedDateField, + useLocalizationContext, } from '@mui/x-date-pickers/internals'; import { useValidation } from '@mui/x-date-pickers/validation'; import { DateValidationError } from '@mui/x-date-pickers/models'; -import { - UseMultiInputDateRangeFieldParams, - UseMultiInputDateRangeFieldProps, -} from '../../../MultiInputDateRangeField/MultiInputDateRangeField.types'; +import { UseMultiInputDateRangeFieldParams } from '../../../MultiInputDateRangeField/MultiInputDateRangeField.types'; import { validateDateRange } from '../../../validation'; import { rangeValueManager } from '../../utils/valueManagers'; import type { UseMultiInputRangeFieldResponse } from './useMultiInputRangeField.types'; import { DateRangeValidationError } from '../../../models'; import { excludeProps } from './shared'; import { useMultiInputFieldSelectedSections } from '../useMultiInputFieldSelectedSections'; +import { getDateRangeValueManager } from '../../../valueManagers'; export const useMultiInputDateRangeField = < TEnableAccessibleFieldDOMStructure extends boolean, TTextFieldSlotProps extends {}, >({ - sharedProps: inSharedProps, + sharedProps, startTextFieldProps, unstableStartFieldRef, endTextFieldProps, @@ -34,10 +33,24 @@ export const useMultiInputDateRangeField = < TEnableAccessibleFieldDOMStructure, TTextFieldSlotProps >): UseMultiInputRangeFieldResponse => { - const sharedProps = useDefaultizedDateField< - UseMultiInputDateRangeFieldProps, - typeof inSharedProps - >(inSharedProps); + const valueManager = React.useMemo( + () => + getDateRangeValueManager({ + enableAccessibleFieldDOMStructure: sharedProps.enableAccessibleFieldDOMStructure, + dateSeparator: sharedProps.dateSeparator, + }), + [sharedProps.enableAccessibleFieldDOMStructure, sharedProps.dateSeparator], + ); + + const localizationContext = useLocalizationContext(); + const sharedPropsWithDefaults = React.useMemo( + () => + valueManager.applyDefaultsToFieldInternalProps({ + ...localizationContext, + internalProps: sharedProps, + }), + [sharedProps, localizationContext, valueManager], + ); const { value: valueProp, @@ -53,7 +66,7 @@ export const useMultiInputDateRangeField = < timezone: timezoneProp, enableAccessibleFieldDOMStructure, autoFocus, - } = sharedProps; + } = sharedPropsWithDefaults; const { value, handleValueChange, timezone } = useControlledValueWithTimezone({ name: 'useMultiInputDateRangeField', @@ -65,11 +78,11 @@ export const useMultiInputDateRangeField = < }); const { validationError, getValidationErrorForNewValue } = useValidation({ - props: sharedProps, + props: sharedPropsWithDefaults, value, timezone, validator: validateDateRange, - onError: sharedProps.onError, + onError: sharedPropsWithDefaults.onError, }); // TODO: Maybe export utility from `useField` instead of copy/pasting the logic 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 2eb4995fb5110..bbfd0b405d917 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 @@ -1,3 +1,4 @@ +import * as React from 'react'; import useEventCallback from '@mui/utils/useEventCallback'; import { unstable_useDateTimeField as useDateTimeField } from '@mui/x-date-pickers/DateTimeField'; import { @@ -6,26 +7,24 @@ import { PickerRangeValue, UseFieldResponse, useControlledValueWithTimezone, - useDefaultizedDateTimeField, + useLocalizationContext, } from '@mui/x-date-pickers/internals'; -import { DateTimeValidationError } from '@mui/x-date-pickers/models'; import { useValidation } from '@mui/x-date-pickers/validation'; -import type { - UseMultiInputDateTimeRangeFieldParams, - UseMultiInputDateTimeRangeFieldProps, -} from '../../../MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.types'; -import { DateTimeRangeValidationError } from '../../../models'; +import { DateTimeValidationError } from '@mui/x-date-pickers/models'; +import { UseMultiInputDateTimeRangeFieldParams } from '../../../MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.types'; import { validateDateTimeRange } from '../../../validation'; import { rangeValueManager } from '../../utils/valueManagers'; import type { UseMultiInputRangeFieldResponse } from './useMultiInputRangeField.types'; +import { DateTimeRangeValidationError } from '../../../models'; import { excludeProps } from './shared'; import { useMultiInputFieldSelectedSections } from '../useMultiInputFieldSelectedSections'; +import { getDateTimeRangeValueManager } from '../../../valueManagers'; export const useMultiInputDateTimeRangeField = < TEnableAccessibleFieldDOMStructure extends boolean, TTextFieldSlotProps extends {}, >({ - sharedProps: inSharedProps, + sharedProps, startTextFieldProps, unstableStartFieldRef, endTextFieldProps, @@ -34,10 +33,24 @@ export const useMultiInputDateTimeRangeField = < TEnableAccessibleFieldDOMStructure, TTextFieldSlotProps >): UseMultiInputRangeFieldResponse => { - const sharedProps = useDefaultizedDateTimeField< - UseMultiInputDateTimeRangeFieldProps, - typeof inSharedProps - >(inSharedProps); + const valueManager = React.useMemo( + () => + getDateTimeRangeValueManager({ + enableAccessibleFieldDOMStructure: sharedProps.enableAccessibleFieldDOMStructure, + dateSeparator: sharedProps.dateSeparator, + }), + [sharedProps.enableAccessibleFieldDOMStructure, sharedProps.dateSeparator], + ); + + const localizationContext = useLocalizationContext(); + const sharedPropsWithDefaults = React.useMemo( + () => + valueManager.applyDefaultsToFieldInternalProps({ + ...localizationContext, + internalProps: sharedProps, + }), + [sharedProps, localizationContext, valueManager], + ); const { value: valueProp, @@ -53,10 +66,10 @@ export const useMultiInputDateTimeRangeField = < timezone: timezoneProp, enableAccessibleFieldDOMStructure, autoFocus, - } = sharedProps; + } = sharedPropsWithDefaults; const { value, handleValueChange, timezone } = useControlledValueWithTimezone({ - name: 'useMultiInputDateRangeField', + name: 'useMultiInputDateTimeRangeField', timezone: timezoneProp, value: valueProp, defaultValue, @@ -65,30 +78,30 @@ export const useMultiInputDateTimeRangeField = < }); const { validationError, getValidationErrorForNewValue } = useValidation({ - props: sharedProps, + props: sharedPropsWithDefaults, value, timezone, validator: validateDateTimeRange, - onError: sharedProps.onError, + onError: sharedPropsWithDefaults.onError, }); // TODO: Maybe export utility from `useField` instead of copy/pasting the logic const buildChangeHandler = (index: 0 | 1): FieldChangeHandler => { - return (newDate, rawContext) => { - const newDateRange: PickerRangeValue = - index === 0 ? [newDate, value[1]] : [value[0], newDate]; + return (newDateTime, rawContext) => { + const newDateTimeRange: PickerRangeValue = + index === 0 ? [newDateTime, value[1]] : [value[0], newDateTime]; const context: FieldChangeHandlerContext = { ...rawContext, - validationError: getValidationErrorForNewValue(newDateRange), + validationError: getValidationErrorForNewValue(newDateTimeRange), }; - handleValueChange(newDateRange, context); + handleValueChange(newDateTimeRange, context); }; }; - const handleStartDateChange = useEventCallback(buildChangeHandler(0)); - const handleEndDateChange = useEventCallback(buildChangeHandler(1)); + const handleStartDateTimeChange = useEventCallback(buildChangeHandler(0)); + const handleEndDateTimeChange = useEventCallback(buildChangeHandler(1)); const selectedSectionsResponse = useMultiInputFieldSelectedSections({ selectedSections, @@ -109,7 +122,7 @@ export const useMultiInputDateTimeRangeField = < timezone, value: valueProp === undefined ? undefined : valueProp[0], defaultValue: defaultValue === undefined ? undefined : defaultValue[0], - onChange: handleStartDateChange, + onChange: handleStartDateTimeChange, enableAccessibleFieldDOMStructure, autoFocus, // Do not add on end field. }; @@ -126,23 +139,23 @@ export const useMultiInputDateTimeRangeField = < timezone, value: valueProp === undefined ? undefined : valueProp[1], defaultValue: defaultValue === undefined ? undefined : defaultValue[1], - onChange: handleEndDateChange, + onChange: handleEndDateTimeChange, enableAccessibleFieldDOMStructure, }; - const startDateResponse = useDateTimeField< + const startDateTimeResponse = useDateTimeField< TEnableAccessibleFieldDOMStructure, typeof startFieldProps >(startFieldProps) as UseFieldResponse; - const endDateResponse = useDateTimeField< + const endDateTimeResponse = useDateTimeField< TEnableAccessibleFieldDOMStructure, typeof endFieldProps >(endFieldProps) as UseFieldResponse; /* TODO: Undo this change when a clearable behavior for multiple input range fields is implemented */ return { - startDate: excludeProps(startDateResponse, ['clearable', 'onClear']), - endDate: excludeProps(endDateResponse, ['clearable', 'onClear']), + startDate: excludeProps(startDateTimeResponse, ['clearable', 'onClear']), + endDate: excludeProps(endDateTimeResponse, ['clearable', 'onClear']), }; }; 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 13459313a1c3a..fe20f6e7a572f 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 @@ -1,3 +1,4 @@ +import * as React from 'react'; import useEventCallback from '@mui/utils/useEventCallback'; import { unstable_useTimeField as useTimeField } from '@mui/x-date-pickers/TimeField'; import { @@ -6,26 +7,24 @@ import { PickerRangeValue, UseFieldResponse, useControlledValueWithTimezone, - useDefaultizedTimeField, + useLocalizationContext, } from '@mui/x-date-pickers/internals'; import { useValidation } from '@mui/x-date-pickers/validation'; import { TimeValidationError } from '@mui/x-date-pickers/models'; +import { UseMultiInputTimeRangeFieldParams } from '../../../MultiInputTimeRangeField/MultiInputTimeRangeField.types'; import { validateTimeRange } from '../../../validation'; -import { TimeRangeValidationError } from '../../../models'; -import type { - UseMultiInputTimeRangeFieldParams, - UseMultiInputTimeRangeFieldProps, -} from '../../../MultiInputTimeRangeField/MultiInputTimeRangeField.types'; import { rangeValueManager } from '../../utils/valueManagers'; import type { UseMultiInputRangeFieldResponse } from './useMultiInputRangeField.types'; +import { TimeRangeValidationError } from '../../../models'; import { excludeProps } from './shared'; import { useMultiInputFieldSelectedSections } from '../useMultiInputFieldSelectedSections'; +import { getTimeRangeValueManager } from '../../../valueManagers'; export const useMultiInputTimeRangeField = < TEnableAccessibleFieldDOMStructure extends boolean, TTextFieldSlotProps extends {}, >({ - sharedProps: inSharedProps, + sharedProps, startTextFieldProps, unstableStartFieldRef, endTextFieldProps, @@ -34,10 +33,24 @@ export const useMultiInputTimeRangeField = < TEnableAccessibleFieldDOMStructure, TTextFieldSlotProps >): UseMultiInputRangeFieldResponse => { - const sharedProps = useDefaultizedTimeField< - UseMultiInputTimeRangeFieldProps, - typeof inSharedProps - >(inSharedProps); + const valueManager = React.useMemo( + () => + getTimeRangeValueManager({ + enableAccessibleFieldDOMStructure: sharedProps.enableAccessibleFieldDOMStructure, + dateSeparator: sharedProps.dateSeparator, + }), + [sharedProps.enableAccessibleFieldDOMStructure, sharedProps.dateSeparator], + ); + + const localizationContext = useLocalizationContext(); + const sharedPropsWithDefaults = React.useMemo( + () => + valueManager.applyDefaultsToFieldInternalProps({ + ...localizationContext, + internalProps: sharedProps, + }), + [sharedProps, localizationContext, valueManager], + ); const { value: valueProp, @@ -53,10 +66,10 @@ export const useMultiInputTimeRangeField = < timezone: timezoneProp, enableAccessibleFieldDOMStructure, autoFocus, - } = sharedProps; + } = sharedPropsWithDefaults; const { value, handleValueChange, timezone } = useControlledValueWithTimezone({ - name: 'useMultiInputDateRangeField', + name: 'useMultiInputTimeRangeField', timezone: timezoneProp, value: valueProp, defaultValue, @@ -65,30 +78,30 @@ export const useMultiInputTimeRangeField = < }); const { validationError, getValidationErrorForNewValue } = useValidation({ - props: sharedProps, - validator: validateTimeRange, + props: sharedPropsWithDefaults, value, timezone, - onError: sharedProps.onError, + validator: validateTimeRange, + onError: sharedPropsWithDefaults.onError, }); // TODO: Maybe export utility from `useField` instead of copy/pasting the logic const buildChangeHandler = (index: 0 | 1): FieldChangeHandler => { - return (newDate, rawContext) => { - const newDateRange: PickerRangeValue = - index === 0 ? [newDate, value[1]] : [value[0], newDate]; + return (newTime, rawContext) => { + const newTimeRange: PickerRangeValue = + index === 0 ? [newTime, value[1]] : [value[0], newTime]; const context: FieldChangeHandlerContext = { ...rawContext, - validationError: getValidationErrorForNewValue(newDateRange), + validationError: getValidationErrorForNewValue(newTimeRange), }; - handleValueChange(newDateRange, context); + handleValueChange(newTimeRange, context); }; }; - const handleStartDateChange = useEventCallback(buildChangeHandler(0)); - const handleEndDateChange = useEventCallback(buildChangeHandler(1)); + const handleStartTimeChange = useEventCallback(buildChangeHandler(0)); + const handleEndTimeChange = useEventCallback(buildChangeHandler(1)); const selectedSectionsResponse = useMultiInputFieldSelectedSections({ selectedSections, @@ -109,7 +122,7 @@ export const useMultiInputTimeRangeField = < timezone, value: valueProp === undefined ? undefined : valueProp[0], defaultValue: defaultValue === undefined ? undefined : defaultValue[0], - onChange: handleStartDateChange, + onChange: handleStartTimeChange, enableAccessibleFieldDOMStructure, autoFocus, // Do not add on end field. }; @@ -126,22 +139,22 @@ export const useMultiInputTimeRangeField = < timezone, value: valueProp === undefined ? undefined : valueProp[1], defaultValue: defaultValue === undefined ? undefined : defaultValue[1], - onChange: handleEndDateChange, + onChange: handleEndTimeChange, enableAccessibleFieldDOMStructure, }; - const startDateResponse = useTimeField< + const startTimeResponse = useTimeField< TEnableAccessibleFieldDOMStructure, typeof startFieldProps >(startFieldProps) as UseFieldResponse; - const endDateResponse = useTimeField( + const endTimeResponse = useTimeField( endFieldProps, ) as UseFieldResponse; /* TODO: Undo this change when a clearable behavior for multiple input range fields is implemented */ return { - startDate: excludeProps(startDateResponse, ['clearable', 'onClear']), - endDate: excludeProps(endDateResponse, ['clearable', 'onClear']), + startDate: excludeProps(startTimeResponse, ['clearable', 'onClear']), + endDate: excludeProps(endTimeResponse, ['clearable', 'onClear']), }; }; diff --git a/packages/x-date-pickers/src/DateField/useDateField.ts b/packages/x-date-pickers/src/DateField/useDateField.ts index 46429703193a9..fb835029bebbd 100644 --- a/packages/x-date-pickers/src/DateField/useDateField.ts +++ b/packages/x-date-pickers/src/DateField/useDateField.ts @@ -1,45 +1,38 @@ 'use client'; import * as React from 'react'; -import { - singleItemFieldValueManager, - singleItemValueManager, -} from '../internals/utils/valueManagers'; -import { useField } from '../internals/hooks/useField'; +import { useField, useFieldInternalPropsWithDefaults } from '../internals/hooks/useField'; import { UseDateFieldProps } from './DateField.types'; -import { validateDate } from '../validation'; import { useSplitFieldProps } from '../hooks'; -import { useDefaultizedDateField } from '../internals/hooks/defaultizedFieldProps'; import { getDateValueManager } from '../valueManagers'; export const useDateField = < TEnableAccessibleFieldDOMStructure extends boolean, TAllProps extends UseDateFieldProps, >( - inProps: TAllProps, + props: TAllProps, ) => { const valueManager = React.useMemo( - () => getDateValueManager(inProps.enableAccessibleFieldDOMStructure), - [inProps.enableAccessibleFieldDOMStructure], + () => getDateValueManager(props.enableAccessibleFieldDOMStructure), + [props.enableAccessibleFieldDOMStructure], ); - const props = useDefaultizedDateField< - UseDateFieldProps, - TAllProps - >(inProps); - const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date'); + const internalPropsWithDefaults = useFieldInternalPropsWithDefaults({ + valueManager, + internalProps, + }); return useField< false, TEnableAccessibleFieldDOMStructure, typeof forwardedProps, - typeof internalProps + typeof internalPropsWithDefaults >({ forwardedProps, - internalProps, - valueManager: singleItemValueManager, - fieldValueManager: singleItemFieldValueManager, - validator: validateDate, - valueType: 'date', + internalProps: internalPropsWithDefaults, + valueManager: valueManager.legacyValueManager, + fieldValueManager: valueManager.fieldValueManager, + validator: valueManager.validator, + valueType: valueManager.valueType, }); }; diff --git a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts index d95b01f4b62d0..362e52d3823d9 100644 --- a/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts +++ b/packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts @@ -1,38 +1,33 @@ 'use client'; -import { - singleItemFieldValueManager, - singleItemValueManager, -} from '../internals/utils/valueManagers'; -import { useField } from '../internals/hooks/useField'; +import * as React from 'react'; +import { useField, useFieldInternalPropsWithDefaults } from '../internals/hooks/useField'; import { UseDateTimeFieldProps } from './DateTimeField.types'; -import { validateDateTime } from '../validation'; import { useSplitFieldProps } from '../hooks'; -import { useDefaultizedDateTimeField } from '../internals/hooks/defaultizedFieldProps'; +import { getDateTimeValueManager } from '../valueManagers'; export const useDateTimeField = < TEnableAccessibleFieldDOMStructure extends boolean, TAllProps extends UseDateTimeFieldProps, >( - inProps: TAllProps, + props: TAllProps, ) => { - const props = useDefaultizedDateTimeField< - UseDateTimeFieldProps, - TAllProps - >(inProps); + const valueManager = React.useMemo( + () => getDateTimeValueManager(props.enableAccessibleFieldDOMStructure), + [props.enableAccessibleFieldDOMStructure], + ); - const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date-time'); + const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date'); + const internalPropsWithDefaults = useFieldInternalPropsWithDefaults({ + valueManager, + internalProps, + }); - return useField< - false, - TEnableAccessibleFieldDOMStructure, - typeof forwardedProps, - typeof internalProps - >({ + return useField({ forwardedProps, - internalProps, - valueManager: singleItemValueManager, - fieldValueManager: singleItemFieldValueManager, - validator: validateDateTime, - valueType: 'date-time', + internalProps: internalPropsWithDefaults, + valueManager: valueManager.legacyValueManager, + fieldValueManager: valueManager.fieldValueManager, + validator: valueManager.validator, + valueType: valueManager.valueType, }); }; diff --git a/packages/x-date-pickers/src/TimeField/useTimeField.ts b/packages/x-date-pickers/src/TimeField/useTimeField.ts index 601d593fe0b61..7f3e2024e0ba4 100644 --- a/packages/x-date-pickers/src/TimeField/useTimeField.ts +++ b/packages/x-date-pickers/src/TimeField/useTimeField.ts @@ -1,38 +1,33 @@ 'use client'; -import { - singleItemFieldValueManager, - singleItemValueManager, -} from '../internals/utils/valueManagers'; -import { useField } from '../internals/hooks/useField'; +import * as React from 'react'; +import { useField, useFieldInternalPropsWithDefaults } from '../internals/hooks/useField'; import { UseTimeFieldProps } from './TimeField.types'; -import { validateTime } from '../validation'; import { useSplitFieldProps } from '../hooks'; -import { useDefaultizedTimeField } from '../internals/hooks/defaultizedFieldProps'; +import { getTimeValueManager } from '../valueManagers'; export const useTimeField = < TEnableAccessibleFieldDOMStructure extends boolean, TAllProps extends UseTimeFieldProps, >( - inProps: TAllProps, + props: TAllProps, ) => { - const props = useDefaultizedTimeField< - UseTimeFieldProps, - TAllProps - >(inProps); + const valueManager = React.useMemo( + () => getTimeValueManager(props.enableAccessibleFieldDOMStructure), + [props.enableAccessibleFieldDOMStructure], + ); - const { forwardedProps, internalProps } = useSplitFieldProps(props, 'time'); + const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date'); + const internalPropsWithDefaults = useFieldInternalPropsWithDefaults({ + valueManager, + internalProps, + }); - return useField< - false, - TEnableAccessibleFieldDOMStructure, - typeof forwardedProps, - typeof internalProps - >({ + return useField({ forwardedProps, - internalProps, - valueManager: singleItemValueManager, - fieldValueManager: singleItemFieldValueManager, - validator: validateTime, - valueType: 'time', + internalProps: internalPropsWithDefaults, + valueManager: valueManager.legacyValueManager, + fieldValueManager: valueManager.fieldValueManager, + validator: valueManager.validator, + valueType: valueManager.valueType, }); }; diff --git a/packages/x-date-pickers/src/internals/hooks/defaultizedFieldProps.ts b/packages/x-date-pickers/src/internals/hooks/defaultizedFieldProps.ts deleted file mode 100644 index 4856e809a5297..0000000000000 --- a/packages/x-date-pickers/src/internals/hooks/defaultizedFieldProps.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { DefaultizedProps } from '@mui/x-internals/types'; -import { applyDefaultDate } from '../utils/date-utils'; -import { useUtils, useDefaultDates } from './useUtils'; -import { - BaseDateValidationProps, - BaseTimeValidationProps, - DateTimeValidationProps, - TimeValidationProps, -} from '../models/validation'; - -export interface UseDefaultizedTimeFieldBaseProps extends BaseTimeValidationProps { - format?: string; -} - -export const useDefaultizedTimeField = < - TKnownProps extends UseDefaultizedTimeFieldBaseProps & { ampm?: boolean }, - TAllProps extends {}, ->( - props: TKnownProps & TAllProps, -): TAllProps & DefaultizedProps => { - const utils = useUtils(); - - const ampm = props.ampm ?? utils.is12HourCycleInCurrentLocale(); - const defaultFormat = ampm ? utils.formats.fullTime12h : utils.formats.fullTime24h; - - return { - ...props, - disablePast: props.disablePast ?? false, - disableFuture: props.disableFuture ?? false, - format: props.format ?? defaultFormat, - }; -}; - -export interface UseDefaultizedDateTimeFieldBaseProps - extends BaseDateValidationProps, - BaseTimeValidationProps { - format?: string; -} - -export const useDefaultizedDateTimeField = < - TKnownProps extends UseDefaultizedDateTimeFieldBaseProps & - DateTimeValidationProps & - TimeValidationProps & { ampm?: boolean }, - TAllProps extends {}, ->( - props: TKnownProps & TAllProps, -): TAllProps & DefaultizedProps => { - const utils = useUtils(); - const defaultDates = useDefaultDates(); - - const ampm = props.ampm ?? utils.is12HourCycleInCurrentLocale(); - const defaultFormat = ampm - ? utils.formats.keyboardDateTime12h - : utils.formats.keyboardDateTime24h; - - return { - ...props, - disablePast: props.disablePast ?? false, - disableFuture: props.disableFuture ?? false, - format: props.format ?? defaultFormat, - disableIgnoringDatePartForTimeValidation: Boolean(props.minDateTime || props.maxDateTime), - minDate: applyDefaultDate(utils, props.minDateTime ?? props.minDate, defaultDates.minDate), - maxDate: applyDefaultDate(utils, props.maxDateTime ?? props.maxDate, defaultDates.maxDate), - minTime: props.minDateTime ?? props.minTime, - maxTime: props.maxDateTime ?? props.maxTime, - }; -}; diff --git a/packages/x-date-pickers/src/internals/hooks/useField/index.ts b/packages/x-date-pickers/src/internals/hooks/useField/index.ts index af21ba83d5b90..1880c3dd20fd9 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/index.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/index.ts @@ -1,4 +1,4 @@ -export { useField } from './useField'; +export { useField, useFieldInternalPropsWithDefaults } from './useField'; export type { FieldValueManager, UseFieldInternalProps, 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 c480686b62f46..188c61f24593a 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useField.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useField.ts @@ -21,42 +21,63 @@ import { useFieldV7TextField } from './useFieldV7TextField'; import { useFieldV6TextField } from './useFieldV6TextField'; import { PickerAnyValueManagerV8, PickerManagerProperties } from '../../../models'; +/** + * Applies the default values to the field internal props. + * This will be moved inside `useField` and is only here to allow the migration to be done in smaller steps. + */ +export const useFieldInternalPropsWithDefaults = ({ + valueManager, + internalProps, +}: { + valueManager: TManager; + internalProps: PickerManagerProperties['fieldInternalProps']; +}) => { + const localizationContext = useLocalizationContext(); + return React.useMemo(() => { + return valueManager.applyDefaultsToFieldInternalProps({ + ...localizationContext, + internalProps, + }); + }, [valueManager, internalProps, localizationContext]); +}; + export const useField = < - TManager extends PickerAnyValueManagerV8, + TIsRange extends boolean, + TEnableAccessibleFieldDOMStructure extends boolean, TForwardedProps extends UseFieldCommonForwardedProps & - UseFieldForwardedProps['enableAccessibleFieldDOMStructure']>, + UseFieldForwardedProps, + TInternalProps extends UseFieldInternalProps< + TIsRange, + TEnableAccessibleFieldDOMStructure, + any + > & { + minutesStep?: number; + }, >( - params: UseFieldParams, -): UseFieldResponse< - PickerManagerProperties['enableAccessibleFieldDOMStructure'], - TForwardedProps -> => { - type Properties = PickerManagerProperties; - type TIsRange = Properties['isRange']; - type TEnableAccessibleFieldDOMStructure = Properties['enableAccessibleFieldDOMStructure']; - + params: UseFieldParams< + TIsRange, + TEnableAccessibleFieldDOMStructure, + TForwardedProps, + TInternalProps + >, +): UseFieldResponse => { const utils = useUtils(); - const localizationContext = useLocalizationContext(); const { internalProps, + internalProps: { + unstableFieldRef, + minutesStep, + enableAccessibleFieldDOMStructure = true, + disabled = false, + readOnly = false, + }, forwardedProps: { onKeyDown, error, clearable, onClear }, + fieldValueManager, valueManager, + validator, } = params; - const internalPropsWithDefaults = React.useMemo( - () => valueManager.applyDefaultsToFieldInternalProps({ ...localizationContext, internalProps }), - [internalProps, localizationContext, valueManager], - ); - - const { - unstableFieldRef, - minutesStep, - enableAccessibleFieldDOMStructure = true, - disabled = false, - readOnly = false, - } = internalPropsWithDefaults; - const isRtl = useRtl(); const stateResponse = useFieldState(params); @@ -85,10 +106,10 @@ export const useField = < const { resetCharacterQuery } = characterEditingResponse; - const areAllSectionsEmpty = valueManager.legacyValueManager.areValuesEqual( + const areAllSectionsEmpty = valueManager.areValuesEqual( utils, state.value, - valueManager.legacyValueManager.emptyValue, + valueManager.emptyValue, ); const useFieldTextField = ( @@ -188,7 +209,7 @@ export const useField = < } const activeSection = state.sections[activeSectionIndex]; - const activeDateManager = valueManager.fieldValueManager.getActiveDateManager( + const activeDateManager = fieldValueManager.getActiveDateManager( utils, state, activeSection, @@ -220,8 +241,8 @@ export const useField = < }); const { hasValidationError } = useValidation({ - props: internalPropsWithDefaults, - validator: valueManager.validator, + props: internalProps, + validator, timezone, value: state.value, onError: internalProps.onError, 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 24dfd9fd006d2..8f61b5e3a4653 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 @@ -6,13 +6,15 @@ import { MuiPickersAdapter, TimezoneProps, FieldSectionContentType, + FieldValueType, PickerValidDate, FieldRef, OnErrorProps, + InferError, InferFieldSection, - PickerAnyValueManagerV8, - PickerManagerProperties, } from '../../../models'; +import type { PickerValueManager } from '../usePicker'; +import type { Validator } from '../../../validation'; import type { UseFieldStateResponse } from './useFieldState'; import type { UseFieldCharacterEditingResponse } from './useFieldCharacterEditing'; import { PickersSectionElement, PickersSectionListRef } from '../../../PickersSectionList'; @@ -20,13 +22,18 @@ import { ExportedUseClearableFieldProps } from '../../../hooks/useClearableField import { FormProps, InferNonNullablePickerValue, InferPickerValue } from '../../models'; export interface UseFieldParams< - TManager extends PickerAnyValueManagerV8, + TIsRange extends boolean, + TEnableAccessibleFieldDOMStructure extends boolean, TForwardedProps extends UseFieldCommonForwardedProps & - UseFieldForwardedProps['enableAccessibleFieldDOMStructure']>, + UseFieldForwardedProps, + TInternalProps extends UseFieldInternalProps, > { forwardedProps: TForwardedProps; - internalProps: PickerManagerProperties['fieldInternalProps']; - valueManager: TManager; + internalProps: TInternalProps; + valueManager: PickerValueManager>; + fieldValueManager: FieldValueManager; + validator: Validator, TInternalProps>; + valueType: FieldValueType; } export interface UseFieldInternalProps< 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 c1b158824a1e9..b5f4f410ad9a0 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts @@ -4,10 +4,13 @@ import { useRtl } from '@mui/system/RtlProvider'; import { usePickerTranslations } from '../../../hooks/usePickerTranslations'; import { useUtils, useLocalizationContext } from '../useUtils'; import { + UseFieldInternalProps, + UseFieldParams, UseFieldState, FieldParsedSelectedSections, FieldChangeHandlerContext, FieldSectionsValueBoundaries, + UseFieldForwardedProps, } from './useField.types'; import { mergeDateIntoReferenceDate, @@ -24,8 +27,6 @@ import { PickerValidDate, InferError, InferFieldSection, - PickerAnyValueManagerV8, - PickerManagerProperties, } from '../../../models'; import { useValueWithTimezone } from '../useValueWithTimezone'; import { @@ -68,12 +69,19 @@ export interface UseFieldStateResponse { timezone: PickersTimezone; } -export const useFieldState = ( - params: UseFieldStateParameters, -): UseFieldStateResponse['isRange']> => { - type Properties = PickerManagerProperties; - type TIsRange = Properties['isRange']; - +export const useFieldState = < + TIsRange extends boolean, + TEnableAccessibleFieldDOMStructure extends boolean, + TForwardedProps extends UseFieldForwardedProps, + TInternalProps extends UseFieldInternalProps, +>( + params: UseFieldParams< + TIsRange, + TEnableAccessibleFieldDOMStructure, + TForwardedProps, + TInternalProps + >, +): UseFieldStateResponse => { const utils = useUtils(); const translations = usePickerTranslations(); const adapter = useLocalizationContext(); @@ -81,8 +89,11 @@ export const useFieldState = ( const { valueManager, - internalPropsWithDefaults, - internalPropsWithDefaults: { + fieldValueManager, + valueType, + validator, + internalProps, + internalProps: { value: valueProp, defaultValue, referenceDate: referenceDateProp, @@ -101,12 +112,12 @@ export const useFieldState = ( timezone, value: valueFromTheOutside, handleValueChange, - } = useValueWithTimezone({ + } = useValueWithTimezone({ timezone: timezoneProp, value: valueProp, defaultValue, onChange, - valueManager: valueManager.legacyValueManager, + valueManager, }); const localizedDigits = React.useMemo(() => getLocalizedDigits(utils), [utils]); @@ -121,7 +132,7 @@ export const useFieldState = ( value: InferPickerValue, fallbackSections: InferFieldSection[] | null = null, ) => - valueManager.fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, (date) => + fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, (date) => buildSectionsFromFormat({ utils, localeText: translations, @@ -135,7 +146,7 @@ export const useFieldState = ( }), ), [ - valueManager.fieldValueManager, + fieldValueManager, format, translations, localizedDigits, @@ -149,7 +160,7 @@ export const useFieldState = ( const [state, setState] = React.useState>(() => { const sections = getSectionsFromValue(valueFromTheOutside); - validateSections(sections, valueManager.valueType); + validateSections(sections, valueType); const stateWithoutReferenceDate: Omit, 'referenceValue'> = { sections, @@ -158,11 +169,11 @@ export const useFieldState = ( }; const granularity = getSectionTypeGranularity(sections); - const referenceValue = valueManager.legacyValueManager.getInitialReferenceValue({ + const referenceValue = valueManager.getInitialReferenceValue({ referenceDate: referenceDateProp, value: valueFromTheOutside, utils, - props: internalPropsWithDefaults as GetDefaultReferenceDateProps, + props: internalProps as GetDefaultReferenceDateProps, granularity, timezone, }); @@ -283,13 +294,9 @@ export const useFieldState = ( return mergeDateIntoReferenceDate(utils, date, sections, referenceDate, false); }; - const newValue = valueManager.fieldValueManager.parseValueStr( - valueStr, - state.referenceValue, - parseDateStr, - ); + const newValue = fieldValueManager.parseValueStr(valueStr, state.referenceValue, parseDateStr); - const newReferenceValue = valueManager.fieldValueManager.updateReferenceValue( + const newReferenceValue = fieldValueManager.updateReferenceValue( utils, newValue, state.referenceValue, @@ -317,11 +324,7 @@ export const useFieldState = ( /** * 2. Try to build a valid date from the new section value */ - const activeDateManager = valueManager.fieldValueManager.getActiveDateManager( - utils, - state, - activeSection, - ); + const activeDateManager = fieldValueManager.getActiveDateManager(utils, state, activeSection); const newSections = setSectionValue(activeSectionIndex!, newSectionValue); const newActiveDateSections = activeDateManager.getSections(newSections); const newActiveDate = getDateFromDateSections(utils, newActiveDateSections, localizedDigits); @@ -372,7 +375,7 @@ export const useFieldState = ( React.useEffect(() => { const sections = getSectionsFromValue(state.value); - validateSections(sections, valueManager.valueType); + validateSections(sections, valueType); setState((prevState) => ({ ...prevState, sections, @@ -381,19 +384,19 @@ export const useFieldState = ( React.useEffect(() => { let shouldUpdate: boolean; - if (!valueManager.legacyValueManager.areValuesEqual(utils, state.value, valueFromTheOutside)) { + if (!valueManager.areValuesEqual(utils, state.value, valueFromTheOutside)) { shouldUpdate = true; } else { shouldUpdate = - valueManager.legacyValueManager.getTimezone(utils, state.value) !== - valueManager.legacyValueManager.getTimezone(utils, valueFromTheOutside); + valueManager.getTimezone(utils, state.value) !== + valueManager.getTimezone(utils, valueFromTheOutside); } if (shouldUpdate) { setState((prevState) => ({ ...prevState, value: valueFromTheOutside, - referenceValue: valueManager.fieldValueManager.updateReferenceValue( + referenceValue: fieldValueManager.updateReferenceValue( utils, valueFromTheOutside, prevState.referenceValue, @@ -419,8 +422,3 @@ export const useFieldState = ( timezone, }; }; - -interface UseFieldStateParameters { - valueManager: TManager; - internalPropsWithDefaults: PickerManagerProperties['fieldInternalPropsWithDefaults']; -} diff --git a/packages/x-date-pickers/src/internals/index.ts b/packages/x-date-pickers/src/internals/index.ts index 8ba0224e949f8..4d71c50564732 100644 --- a/packages/x-date-pickers/src/internals/index.ts +++ b/packages/x-date-pickers/src/internals/index.ts @@ -53,6 +53,7 @@ export { useControlledValueWithTimezone } from './hooks/useValueWithTimezone'; export type { DesktopOnlyPickerProps } from './hooks/useDesktopPicker'; export { useField, + useFieldInternalPropsWithDefaults, createDateStrForV7HiddenInputFromSections, createDateStrForV6InputFromSections, } from './hooks/useField'; @@ -146,11 +147,6 @@ export { onSpaceOrEnter, DEFAULT_DESKTOP_MODE_MEDIA_QUERY, } from './utils/utils'; -export { - useDefaultizedDateField, - useDefaultizedTimeField, - useDefaultizedDateTimeField, -} from './hooks/defaultizedFieldProps'; export { useDefaultReduceAnimations } from './hooks/useDefaultReduceAnimations'; export { applyDefaultViewProps } from './utils/views'; diff --git a/packages/x-date-pickers/src/models/valueManager.ts b/packages/x-date-pickers/src/models/valueManager.ts index 9265b449e1653..0d8059fd12b52 100644 --- a/packages/x-date-pickers/src/models/valueManager.ts +++ b/packages/x-date-pickers/src/models/valueManager.ts @@ -1,4 +1,4 @@ -import { InferPickerValue } from '../internals/models/value'; +import { InferNonNullablePickerValue, InferPickerValue } from '../internals/models/value'; import type { FieldValueManager, UseFieldInternalProps } from '../internals/hooks/useField'; import type { PickerValueManager } from '../internals/hooks/usePicker'; import type { MuiPickersAdapterContextValue } from '../LocalizationProvider/LocalizationProvider'; @@ -78,6 +78,7 @@ export type PickerManagerProperties = // Derived properties value: InferPickerValue; + nonNullableValue: InferNonNullablePickerValue; section: InferFieldSection; } : never;