diff --git a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.js b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.js index 7743be94934f5..60e4a63bdef1d 100644 --- a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.js +++ b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.js @@ -5,8 +5,10 @@ import { styled } from '@mui/material/styles'; import Stack from '@mui/material/Stack'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { DateRangePicker } from '@mui/x-date-pickers-pro/DateRangePicker'; -import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; +import { useDateRangeManager } from '@mui/x-date-pickers-pro/managers'; +import { unstable_useMultiInputRangeField as useMultiInputRangeField } from '@mui/x-date-pickers-pro/hooks'; import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-pickers/PickersSectionList'; const BrowserFieldRoot = styled('div', { name: 'BrowserField', slot: 'Root' })({ @@ -78,18 +80,9 @@ const BrowserTextField = React.forwardRef((props, ref) => { }); const BrowserMultiInputDateRangeField = React.forwardRef((props, ref) => { - const { - slotProps, - readOnly, - shouldDisableDate, - minDate, - maxDate, - disableFuture, - disablePast, - className, - unstableStartFieldRef, - unstableEndFieldRef, - } = props; + const manager = useDateRangeManager(); + const { internalProps, forwardedProps } = useSplitFieldProps(props, 'date'); + const { slotProps, ownerState, ...otherForwardedProps } = forwardedProps; const startTextFieldProps = useSlotProps({ elementType: 'input', @@ -103,48 +96,24 @@ const BrowserMultiInputDateRangeField = React.forwardRef((props, ref) => { ownerState: { position: 'end' }, }); - const fieldResponse = useMultiInputDateRangeField({ - sharedProps: { - readOnly, - shouldDisableDate, - minDate, - maxDate, - disableFuture, - disablePast, - enableAccessibleFieldDOMStructure: true, - }, - startTextFieldProps, - endTextFieldProps, - unstableStartFieldRef, - unstableEndFieldRef, + const fieldResponse = useMultiInputRangeField({ + manager, + internalProps, + startForwardedProps: startTextFieldProps, + endForwardedProps: endTextFieldProps, }); - const { - // The multi input range field do not support clearable and onClear - onClear: onClearStartDate, - clearable: isStartDateClearable, - openPickerAriaLabel: openPickerStartDateAriaLabel, - ...startDateProps - } = fieldResponse.startDate; - const { - // The multi input range field do not support clearable and onClear - onClear: onClearEndDate, - clearable: isEndDateClearable, - openPickerAriaLabel: openPickerEndDateAriaLabel, - ...endDateProps - } = fieldResponse.endDate; - return ( - - - + + + ); }); diff --git a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx index b5c605dc0ac8f..8cfaa4b356a58 100644 --- a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx +++ b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx @@ -5,12 +5,14 @@ import { styled } from '@mui/material/styles'; import Stack from '@mui/material/Stack'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { DateRangePicker, DateRangePickerFieldProps, DateRangePickerProps, } from '@mui/x-date-pickers-pro/DateRangePicker'; -import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; +import { useDateRangeManager } from '@mui/x-date-pickers-pro/managers'; +import { unstable_useMultiInputRangeField as useMultiInputRangeField } from '@mui/x-date-pickers-pro/hooks'; import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-pickers/PickersSectionList'; import { MultiInputFieldSlotTextFieldProps, @@ -118,18 +120,9 @@ type BrowserMultiInputDateRangeFieldComponent = (( const BrowserMultiInputDateRangeField = React.forwardRef( (props: BrowserMultiInputDateRangeFieldProps, ref: React.Ref) => { - const { - slotProps, - readOnly, - shouldDisableDate, - minDate, - maxDate, - disableFuture, - disablePast, - className, - unstableStartFieldRef, - unstableEndFieldRef, - } = props; + const manager = useDateRangeManager(); + const { internalProps, forwardedProps } = useSplitFieldProps(props, 'date'); + const { slotProps, ownerState, ...otherForwardedProps } = forwardedProps; const startTextFieldProps = useSlotProps({ elementType: 'input', @@ -143,51 +136,24 @@ const BrowserMultiInputDateRangeField = React.forwardRef( ownerState: { position: 'end' } as any, }) as MultiInputFieldSlotTextFieldProps; - const fieldResponse = useMultiInputDateRangeField< - true, - MultiInputFieldSlotTextFieldProps - >({ - sharedProps: { - readOnly, - shouldDisableDate, - minDate, - maxDate, - disableFuture, - disablePast, - enableAccessibleFieldDOMStructure: true, - }, - startTextFieldProps, - endTextFieldProps, - unstableStartFieldRef, - unstableEndFieldRef, + const fieldResponse = useMultiInputRangeField({ + manager, + internalProps, + startForwardedProps: startTextFieldProps, + endForwardedProps: endTextFieldProps, }); - const { - // The multi input range field do not support clearable and onClear - onClear: onClearStartDate, - clearable: isStartDateClearable, - openPickerAriaLabel: openPickerStartDateAriaLabel, - ...startDateProps - } = fieldResponse.startDate; - const { - // The multi input range field do not support clearable and onClear - onClear: onClearEndDate, - clearable: isEndDateClearable, - openPickerAriaLabel: openPickerEndDateAriaLabel, - ...endDateProps - } = fieldResponse.endDate; - return ( - - - + + + ); }, diff --git a/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.js b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.js index 6adab583bfa13..118af0a126d91 100644 --- a/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.js +++ b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.js @@ -8,7 +8,6 @@ import useSlotProps from '@mui/utils/useSlotProps'; import { extendTheme as extendJoyTheme, useColorScheme, - styled, CssVarsProvider, THEME_ID, } from '@mui/joy/styles'; @@ -18,9 +17,11 @@ import FormControl from '@mui/joy/FormControl'; import FormLabel from '@mui/joy/FormLabel'; import Typography from '@mui/joy/Typography'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { DateRangePicker } from '@mui/x-date-pickers-pro/DateRangePicker'; -import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; +import { useDateRangeManager } from '@mui/x-date-pickers-pro/managers'; +import { unstable_useMultiInputRangeField as useMultiInputRangeField } from '@mui/x-date-pickers-pro/hooks'; const joyTheme = extendJoyTheme(); @@ -68,102 +69,47 @@ const JoyField = React.forwardRef((props, ref) => { ); }); -const MultiInputJoyDateRangeFieldRoot = styled( - React.forwardRef((props, ref) => ( - - )), - { - name: 'MuiMultiInputDateRangeField', - slot: 'Root', - overridesResolver: (props, styles) => styles.root, - }, -)({}); - -const MultiInputJoyDateRangeFieldSeparator = styled( - (props) => ( - - {/* Ensure that the separator is correctly aligned */} - - {props.children ?? ' – '} - - ), - { - name: 'MuiMultiInputDateRangeField', - slot: 'Separator', - overridesResolver: (props, styles) => styles.separator, - }, -)({ marginTop: '25px' }); - const JoyMultiInputDateRangeField = React.forwardRef((props, ref) => { - const { - slotProps, - readOnly, - shouldDisableDate, - minDate, - maxDate, - disableFuture, - disablePast, - className, - unstableStartFieldRef, - unstableEndFieldRef, - } = props; + const manager = useDateRangeManager({ + enableAccessibleFieldDOMStructure: false, + }); + const { internalProps, forwardedProps } = useSplitFieldProps(props, 'date'); + const { slotProps, ownerState, ...otherForwardedProps } = forwardedProps; const startTextFieldProps = useSlotProps({ - elementType: FormControl, + elementType: 'input', externalSlotProps: slotProps?.textField, ownerState: { position: 'start' }, }); const endTextFieldProps = useSlotProps({ - elementType: FormControl, + elementType: 'input', externalSlotProps: slotProps?.textField, ownerState: { position: 'end' }, }); - const fieldResponse = useMultiInputDateRangeField({ - sharedProps: { - readOnly, - shouldDisableDate, - minDate, - maxDate, - disableFuture, - disablePast, - enableAccessibleFieldDOMStructure: false, - }, - startTextFieldProps, - endTextFieldProps, - unstableStartFieldRef, - unstableEndFieldRef, + const fieldResponse = useMultiInputRangeField({ + manager, + internalProps: { ...internalProps, enableAccessibleFieldDOMStructure: false }, + startForwardedProps: startTextFieldProps, + endForwardedProps: endTextFieldProps, }); - const { - // The multi input range field do not support clearable, onClear and openPickerAriaLabel - onClear: onClearStartDate, - clearable: isStartDateClearable, - openPickerAriaLabel: openPickerStartDateAriaLabel, - ...startDateProps - } = fieldResponse.startDate; - const { - // The multi input range field do not support clearable, onClear and openPickerAriaLabel - onClear: onClearEndDate, - clearable: isEndDateClearable, - openPickerAriaLabel: openPickerEndDateAriaLabel, - ...endDateProps - } = fieldResponse.endDate; - return ( - - - - - + + + + {' – '} + + + ); }); diff --git a/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx index 9f5cbc60eff72..3add953616aa4 100644 --- a/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx +++ b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx @@ -8,23 +8,24 @@ import useSlotProps from '@mui/utils/useSlotProps'; import { extendTheme as extendJoyTheme, useColorScheme, - styled, CssVarsProvider, THEME_ID, } from '@mui/joy/styles'; import Input, { InputProps } from '@mui/joy/Input'; -import Stack, { StackProps } from '@mui/joy/Stack'; +import Stack from '@mui/joy/Stack'; import FormControl from '@mui/joy/FormControl'; import FormLabel from '@mui/joy/FormLabel'; -import Typography, { TypographyProps } from '@mui/joy/Typography'; +import Typography from '@mui/joy/Typography'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { DateRangePicker, DateRangePickerFieldProps, DateRangePickerProps, } from '@mui/x-date-pickers-pro/DateRangePicker'; -import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; +import { useDateRangeManager } from '@mui/x-date-pickers-pro/managers'; +import { unstable_useMultiInputRangeField as useMultiInputRangeField } from '@mui/x-date-pickers-pro/hooks'; import { MultiInputFieldRefs, MultiInputFieldSlotTextFieldProps, @@ -94,39 +95,6 @@ const JoyField = React.forwardRef( }, ) as JoyFieldComponent; -const MultiInputJoyDateRangeFieldRoot = styled( - React.forwardRef((props: StackProps, ref: React.Ref) => ( - - )), - { - name: 'MuiMultiInputDateRangeField', - slot: 'Root', - overridesResolver: (props, styles) => styles.root, - }, -)({}); - -const MultiInputJoyDateRangeFieldSeparator = styled( - (props: TypographyProps) => ( - - {/* Ensure that the separator is correctly aligned */} - - {props.children ?? ' – '} - - ), - { - name: 'MuiMultiInputDateRangeField', - slot: 'Separator', - overridesResolver: (props, styles) => styles.separator, - }, -)({ marginTop: '25px' }); - interface JoyMultiInputDateRangeFieldProps extends Omit< DateRangePickerFieldProps, @@ -144,71 +112,46 @@ type JoyMultiInputDateRangeFieldComponent = (( const JoyMultiInputDateRangeField = React.forwardRef( (props: JoyMultiInputDateRangeFieldProps, ref: React.Ref) => { - const { - slotProps, - readOnly, - shouldDisableDate, - minDate, - maxDate, - disableFuture, - disablePast, - className, - unstableStartFieldRef, - unstableEndFieldRef, - } = props; + const manager = useDateRangeManager({ + enableAccessibleFieldDOMStructure: false, + }); + const { internalProps, forwardedProps } = useSplitFieldProps(props, 'date'); + const { slotProps, ownerState, ...otherForwardedProps } = forwardedProps; const startTextFieldProps = useSlotProps({ - elementType: FormControl, + elementType: 'input', externalSlotProps: slotProps?.textField, ownerState: { position: 'start' } as any, }) as MultiInputFieldSlotTextFieldProps; const endTextFieldProps = useSlotProps({ - elementType: FormControl, + elementType: 'input', externalSlotProps: slotProps?.textField, ownerState: { position: 'end' } as any, }) as MultiInputFieldSlotTextFieldProps; - const fieldResponse = useMultiInputDateRangeField< - false, - MultiInputFieldSlotTextFieldProps - >({ - sharedProps: { - readOnly, - shouldDisableDate, - minDate, - maxDate, - disableFuture, - disablePast, - enableAccessibleFieldDOMStructure: false, - }, - startTextFieldProps, - endTextFieldProps, - unstableStartFieldRef, - unstableEndFieldRef, + const fieldResponse = useMultiInputRangeField({ + manager, + internalProps: { ...internalProps, enableAccessibleFieldDOMStructure: false }, + startForwardedProps: startTextFieldProps, + endForwardedProps: endTextFieldProps, }); - const { - // The multi input range field do not support clearable, onClear and openPickerAriaLabel - onClear: onClearStartDate, - clearable: isStartDateClearable, - openPickerAriaLabel: openPickerStartDateAriaLabel, - ...startDateProps - } = fieldResponse.startDate; - const { - // The multi input range field do not support clearable, onClear and openPickerAriaLabel - onClear: onClearEndDate, - clearable: isEndDateClearable, - openPickerAriaLabel: openPickerEndDateAriaLabel, - ...endDateProps - } = fieldResponse.endDate; - return ( - - - - - + + + + {' – '} + + + ); }, ) as JoyMultiInputDateRangeFieldComponent; 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 d8b17b13012ec..d84acfee829ff 100644 --- a/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md +++ b/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md @@ -944,6 +944,161 @@ The following variables and types have been renamed to have a coherent `Picker` ## Hooks breaking changes +### `useMultiInputDateRangeField` + +This hook has been removed in favor of the new `useMultiInputRangeField` hook with an improved DX: + +```diff + import useSlotProps from '@mui/utils/useSlotProps'; +-import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; ++import { useDateRangeManager } from '@mui/x-date-pickers-pro/managers'; ++import { unstable_useMultiInputRangeField as useMultiInputRangeField } from '@mui/x-date-pickers-pro/hooks'; + import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; + + const DateRangeField(props) { + const { internalProps, forwardedProps } = useSplitFieldProps(props, 'date'); + const { slotProps, slots } = forwardedProps; + + const startTextFieldProps = useSlotProps({ + elementType: 'input', + externalSlotProps: slotProps?.textField, + ownerState: { ...props, position: 'start' }, + }); + + const endTextFieldProps = useSlotProps({ + elementType: 'input', + externalSlotProps: slotProps?.textField, + ownerState: { ...props, position: 'end' }, + }); + +- const fieldResponse = useMultiInputDateRangeField({ +- sharedProps: internalProps, +- startTextFieldProps, +- endTextFieldProps, +- unstableStartFieldRef: internalProps.unstableStartFieldRef, +- unstableEndFieldRef: internalProps.unstableEndFieldRef, +- }); + ++ const manager = useDateRangeManager(props); ++ const fieldResponse = useMultiInputRangeField({ ++ manager, ++ internalProps, ++ startForwardedProps: startTextFieldProps, ++ endForwardedProps: endTextFieldProps, ++ }); + + return ( /** Your UI */ ) + } +``` + +:::success +The associated types have also been removed. [Learn how to migrate them](/x/migration/migration-pickers-v7/#removed-types). +::: + +### `useMultiInputTimeRangeField` + +This hook has been removed in favor of the new `useMultiInputRangeField` hook with an improved DX: + +```diff + import useSlotProps from '@mui/utils/useSlotProps'; +-import { unstable_useMultiInputTimeRangeField as useMultiInputTimeRangeField } from '@mui/x-date-pickers-pro/MultiInputTimeRangeField'; ++import { useTimeRangeManager } from '@mui/x-date-pickers-pro/managers'; ++import { unstable_useMultiInputRangeField as useMultiInputRangeField } from '@mui/x-date-pickers-pro/hooks'; + import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; + + const DateRangeField(props) { + const { internalProps, forwardedProps } = useSplitFieldProps(props, 'time'); + const { slotProps, slots } = forwardedProps; + + const startTextFieldProps = useSlotProps({ + elementType: 'input', + externalSlotProps: slotProps?.textField, + ownerState: { ...props, position: 'start' }, + }); + + const endTextFieldProps = useSlotProps({ + elementType: 'input', + externalSlotProps: slotProps?.textField, + ownerState: { ...props, position: 'end' }, + }); + + +- const fieldResponse = useMultiInputTimeRangeField({ +- sharedProps: internalProps, +- startTextFieldProps, +- endTextFieldProps, +- unstableStartFieldRef: internalProps.unstableStartFieldRef, +- unstableEndFieldRef: internalProps.unstableEndFieldRef, +- }); + ++ const manager = useTimeRangeManager(props); ++ const fieldResponse = useMultiInputRangeField({ ++ manager, ++ internalProps, ++ startForwardedProps: startTextFieldProps, ++ endForwardedProps: endTextFieldProps, ++ }); + + return ( /** Your UI */ ) + } +``` + +:::success +The associated types have also been removed. [Learn how to migrate them](/x/migration/migration-pickers-v7/#removed-types). +::: + +### `useMultiInputDateTimeRangeField` + +This hook has been removed in favor of the new `useMultiInputRangeField` hook with an improved DX: + +```diff + import useSlotProps from '@mui/utils/useSlotProps'; +-import { unstable_useMultiInputDateTimeRangeField as useMultiInputDateTimeRangeField } from '@mui/x-date-pickers-pro/MultiInputDateTimeRangeField'; ++import { useDateTimeRangeManager } from '@mui/x-date-pickers-pro/managers'; ++import { unstable_useMultiInputRangeField as useMultiInputRangeField } from '@mui/x-date-pickers-pro/hooks'; + import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; + + const DateRangeField(props) { + const { internalProps, forwardedProps } = useSplitFieldProps(props, 'date-time'); + const { slotProps, slots } = forwardedProps; + + const startTextFieldProps = useSlotProps({ + elementType: 'input', + externalSlotProps: slotProps?.textField, + ownerState: { ...props, position: 'start' }, + }); + + const endTextFieldProps = useSlotProps({ + elementType: 'input', + externalSlotProps: slotProps?.textField, + ownerState: { ...props, position: 'end' }, + }); + + +- const fieldResponse = useMultiInputDateTimeRangeField({ +- sharedProps: internalProps, +- startTextFieldProps, +- endTextFieldProps, +- unstableStartFieldRef: internalProps.unstableStartFieldRef, +- unstableEndFieldRef: internalProps.unstableEndFieldRef, +- }); + ++ const manager = useDateTimeRangeManager(props); ++ const fieldResponse = useMultiInputRangeField({ ++ manager, ++ internalProps, ++ startForwardedProps: startTextFieldProps, ++ endForwardedProps: endTextFieldProps, ++ }); + + return ( /** Your UI */ ) + } +``` + +:::success +The associated types have also been removed. [Learn how to migrate them](/x/migration/migration-pickers-v7/#removed-types). +::: + ### `usePickerContext` - The `onOpen` and `onClose` methods have been replaced with a single `setOpen` method. @@ -1088,6 +1243,135 @@ If you were using them, you need to replace them with the following code: UseDateTimeFieldProps; ``` +- `UseDateRangeFieldProps` + + ```ts + import { DateRangeManagerFieldInternalProps } from '@mui/x-date-pickers-pro/managers'; + + interface UseDateRangeFieldProps< + TEnableAccessibleFieldDOMStructure extends boolean, + > extends Omit< + DateRangeManagerFieldInternalProps, + 'unstableFieldRef' + > {} + ``` + +- `UseMultiInputDateRangeFieldProps` + + ```ts + import { DateRangeManagerFieldInternalProps } from '@mui/x-date-pickers-pro/managers'; + import { MultiInputFieldRefs } from '@mui/x-date-pickers-pro/models'; + + interface UseMultiInputDateRangeFieldProps< + TEnableAccessibleFieldDOMStructure extends boolean, + > extends DateRangeManagerFieldInternalProps, + MultiInputFieldRefs {} + ``` + +- `UseMultiInputDateRangeFieldComponentProps` + + ```ts + import { DateRangeManagerFieldInternalProps } from '@mui/x-date-pickers-pro/managers'; + import { MultiInputFieldRefs } from '@mui/x-date-pickers-pro/models'; + + type UseMultiInputDateRangeFieldComponentProps< + TEnableAccessibleFieldDOMStructure extends boolean, + TChildProps extends {}, + > = Omit< + TChildProps, + | keyof DateRangeManagerFieldInternalProps + | keyof MultiInputFieldRefs + > & + DateRangeManagerFieldInternalProps & + MultiInputFieldRefs; + ``` + +- `UseMultiInputTimeRangeFieldProps` + + ```ts + import { TimeRangeManagerFieldInternalProps } from '@mui/x-date-pickers-pro/managers'; + import { MultiInputFieldRefs } from '@mui/x-date-pickers-pro/models'; + + interface UseMultiInputTimeRangeFieldProps< + TEnableAccessibleFieldDOMStructure extends boolean, + > extends TimeRangeManagerFieldInternalProps, + MultiInputFieldRefs {} + ``` + +- `UseMultiInputTimeRangeFieldComponentProps` + + ```ts + import { TimeRangeManagerFieldInternalProps } from '@mui/x-date-pickers-pro/managers'; + import { MultiInputFieldRefs } from '@mui/x-date-pickers-pro/models'; + + type UseMultiInputTimeRangeFieldComponentProps< + TEnableAccessibleFieldDOMStructure extends boolean, + TChildProps extends {}, + > = Omit< + TChildProps, + | keyof TimeRangeManagerFieldInternalProps + | keyof MultiInputFieldRefs + > & + TimeRangeManagerFieldInternalProps & + MultiInputFieldRefs; + ``` + +- `UseMultiInputDateTimeRangeFieldProps` + + ```ts + import { DateTimeRangeManagerFieldInternalProps } from '@mui/x-date-pickers-pro/managers'; + import { MultiInputFieldRefs } from '@mui/x-date-pickers-pro/models'; + + interface UseMultiInputDateTimeRangeFieldProps< + TEnableAccessibleFieldDOMStructure extends boolean, + > extends DateTimeRangeManagerFieldInternalProps, + MultiInputFieldRefs {} + ``` + +- `UseMultiInputDateTimeRangeFieldComponentProps` + + ```ts + import { DateTimeRangeManagerFieldInternalProps } from '@mui/x-date-pickers-pro/managers'; + import { MultiInputFieldRefs } from '@mui/x-date-pickers-pro/models'; + + type UseMultiInputDateTimeRangeFieldComponentProps< + TEnableAccessibleFieldDOMStructure extends boolean, + TChildProps extends {}, + > = Omit< + TChildProps, + | keyof DateTimeRangeManagerFieldInternalProps + | keyof MultiInputFieldRefs + > & + DateTimeRangeManagerFieldInternalProps & + MultiInputFieldRefs; + ``` + +- `MultiInputRangeFieldClasses` + + ```ts + // If you were using MultiInputRangeFieldClasses for a date range field. + import { MultiInputDateRangeFieldClasses } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; + + // If you were using MultiInputRangeFieldClasses for a time range field. + import { MultiInputTimeRangeFieldClasses } from '@mui/x-date-pickers-pro/MultiInputTimeRangeField'; + + // If you were using MultiInputRangeFieldClasses for a date time range field. + import { MultiInputDateTimeRangeFieldClasses } from '@mui/x-date-pickers-pro/MultiInputDateTimeRangeField'; + ``` + +- `MultiInputRangeFieldClassKey` + + ```ts + // If you were using MultiInputRangeFieldClassKey for a date range field. + import { MultiInputRangeFieldClassKey } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; + + // If you were using MultiInputRangeFieldClassKey for a time range field. + import { MultiInputRangeFieldClassKey } from '@mui/x-date-pickers-pro/MultiInputTimeRangeField'; + + // If you were using MultiInputRangeFieldClassKey for a date time range field. + import { MultiInputRangeFieldClassKey } from '@mui/x-date-pickers-pro/MultiInputDateTimeRangeField'; + ``` + - `BaseSingleInputFieldProps` - If you are building a custom field for a Date Picker: diff --git a/docs/pages/x/api/date-pickers/multi-input-date-range-field.json b/docs/pages/x/api/date-pickers/multi-input-date-range-field.json index d9e6f2cbf77d5..94aabd8466a8d 100644 --- a/docs/pages/x/api/date-pickers/multi-input-date-range-field.json +++ b/docs/pages/x/api/date-pickers/multi-input-date-range-field.json @@ -1,6 +1,6 @@ { "props": { - "autoFocus": { "type": { "name": "bool" } }, + "autoFocus": { "type": { "name": "bool" }, "default": "false" }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, "dateSeparator": { "type": { "name": "string" }, "default": "\"–\"" }, "defaultValue": { "type": { "name": "arrayOf", "description": "Array<object>" } }, @@ -99,20 +99,27 @@ "import { MultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField';", "import { MultiInputDateRangeField } from '@mui/x-date-pickers-pro';" ], - "classes": [ + "slots": [ { - "key": "root", - "className": "MuiMultiInputDateRangeField-root", - "description": "Styles applied to the root element.", - "isGlobal": false + "name": "root", + "description": "Element rendered at the root.", + "default": "MultiInputRangeFieldRoot", + "class": "MuiMultiInputDateRangeField-root" }, { - "key": "separator", - "className": "MuiMultiInputDateRangeField-separator", - "description": "Styles applied to the separator element.", - "isGlobal": false + "name": "separator", + "description": "Element rendered between the two inputs.", + "default": "MultiInputRangeFieldSeparator", + "class": "MuiMultiInputDateRangeField-separator" + }, + { + "name": "textField", + "description": "Form control with an input to render a date.\nIt is rendered twice: once for the start date and once for the end date.", + "default": ", or from '@mui/material' if `enableAccessibleFieldDOMStructure` is `false`.", + "class": null } ], + "classes": [], "spread": true, "themeDefaultProps": true, "muiName": "MuiMultiInputDateRangeField", diff --git a/docs/pages/x/api/date-pickers/multi-input-date-time-range-field.json b/docs/pages/x/api/date-pickers/multi-input-date-time-range-field.json index 783e9b93b4674..4bafe16e5ecab 100644 --- a/docs/pages/x/api/date-pickers/multi-input-date-time-range-field.json +++ b/docs/pages/x/api/date-pickers/multi-input-date-time-range-field.json @@ -1,7 +1,7 @@ { "props": { "ampm": { "type": { "name": "bool" }, "default": "utils.is12HourCycleInCurrentLocale()" }, - "autoFocus": { "type": { "name": "bool" } }, + "autoFocus": { "type": { "name": "bool" }, "default": "false" }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, "dateSeparator": { "type": { "name": "string" }, "default": "\"–\"" }, "defaultValue": { "type": { "name": "arrayOf", "description": "Array<object>" } }, @@ -114,20 +114,27 @@ "import { MultiInputDateTimeRangeField } from '@mui/x-date-pickers-pro/MultiInputDateTimeRangeField';", "import { MultiInputDateTimeRangeField } from '@mui/x-date-pickers-pro';" ], - "classes": [ + "slots": [ { - "key": "root", - "className": "MuiMultiInputDateTimeRangeField-root", - "description": "Styles applied to the root element.", - "isGlobal": false + "name": "root", + "description": "Element rendered at the root.", + "default": "MultiInputRangeFieldRoot", + "class": "MuiMultiInputDateTimeRangeField-root" }, { - "key": "separator", - "className": "MuiMultiInputDateTimeRangeField-separator", - "description": "Styles applied to the separator element.", - "isGlobal": false + "name": "separator", + "description": "Element rendered between the two inputs.", + "default": "MultiInputRangeFieldSeparator", + "class": "MuiMultiInputDateTimeRangeField-separator" + }, + { + "name": "textField", + "description": "Form control with an input to render a date.\nIt is rendered twice: once for the start date and once for the end date.", + "default": ", or from '@mui/material' if `enableAccessibleFieldDOMStructure` is `false`.", + "class": null } ], + "classes": [], "spread": true, "themeDefaultProps": true, "muiName": "MuiMultiInputDateTimeRangeField", diff --git a/docs/pages/x/api/date-pickers/multi-input-time-range-field.json b/docs/pages/x/api/date-pickers/multi-input-time-range-field.json index 120e10742bd03..46e2ae2b0931a 100644 --- a/docs/pages/x/api/date-pickers/multi-input-time-range-field.json +++ b/docs/pages/x/api/date-pickers/multi-input-time-range-field.json @@ -1,7 +1,7 @@ { "props": { "ampm": { "type": { "name": "bool" }, "default": "utils.is12HourCycleInCurrentLocale()" }, - "autoFocus": { "type": { "name": "bool" } }, + "autoFocus": { "type": { "name": "bool" }, "default": "false" }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, "dateSeparator": { "type": { "name": "string" }, "default": "\"–\"" }, "defaultValue": { "type": { "name": "arrayOf", "description": "Array<object>" } }, @@ -102,20 +102,27 @@ "import { MultiInputTimeRangeField } from '@mui/x-date-pickers-pro/MultiInputTimeRangeField';", "import { MultiInputTimeRangeField } from '@mui/x-date-pickers-pro';" ], - "classes": [ + "slots": [ { - "key": "root", - "className": "MuiMultiInputTimeRangeField-root", - "description": "Styles applied to the root element.", - "isGlobal": false + "name": "root", + "description": "Element rendered at the root.", + "default": "MultiInputRangeFieldRoot", + "class": "MuiMultiInputTimeRangeField-root" }, { - "key": "separator", - "className": "MuiMultiInputTimeRangeField-separator", - "description": "Styles applied to the separator element.", - "isGlobal": false + "name": "separator", + "description": "Element rendered between the two inputs.", + "default": "MultiInputRangeFieldSeparator", + "class": "MuiMultiInputTimeRangeField-separator" + }, + { + "name": "textField", + "description": "Form control with an input to render a date.\nIt is rendered twice: once for the start date and once for the end date.", + "default": ", or from '@mui/material' if `enableAccessibleFieldDOMStructure` is `false`.", + "class": null } ], + "classes": [], "spread": true, "themeDefaultProps": true, "muiName": "MuiMultiInputTimeRangeField", diff --git a/docs/scripts/generateProptypes.ts b/docs/scripts/generateProptypes.ts index d45ba1f6af788..f8e9440a4ab03 100644 --- a/docs/scripts/generateProptypes.ts +++ b/docs/scripts/generateProptypes.ts @@ -76,6 +76,7 @@ async function generateProptypes(project: XTypeScriptProject, sourceFile: string 'rightAxis', 'plugins', 'seriesConfig', + 'manager', ]; if (propsToNotResolve.includes(name)) { return false; diff --git a/docs/translations/api-docs/date-pickers/multi-input-date-range-field/multi-input-date-range-field.json b/docs/translations/api-docs/date-pickers/multi-input-date-range-field/multi-input-date-range-field.json index 40cc9e7558110..e9da20d620141 100644 --- a/docs/translations/api-docs/date-pickers/multi-input-date-range-field/multi-input-date-range-field.json +++ b/docs/translations/api-docs/date-pickers/multi-input-date-range-field/multi-input-date-range-field.json @@ -81,11 +81,10 @@ }, "value": { "description": "The selected value. Used when the component is controlled." } }, - "classDescriptions": { - "root": { "description": "Styles applied to the root element." }, - "separator": { - "description": "Styles applied to {{nodeName}}.", - "nodeName": "the separator element" - } + "classDescriptions": {}, + "slotDescriptions": { + "root": "Element rendered at the root.", + "separator": "Element rendered between the two inputs.", + "textField": "Form control with an input to render a date. It is rendered twice: once for the start date and once for the end date." } } diff --git a/docs/translations/api-docs/date-pickers/multi-input-date-time-range-field/multi-input-date-time-range-field.json b/docs/translations/api-docs/date-pickers/multi-input-date-time-range-field/multi-input-date-time-range-field.json index 161927c19e224..02085db56e97a 100644 --- a/docs/translations/api-docs/date-pickers/multi-input-date-time-range-field/multi-input-date-time-range-field.json +++ b/docs/translations/api-docs/date-pickers/multi-input-date-time-range-field/multi-input-date-time-range-field.json @@ -106,11 +106,10 @@ }, "value": { "description": "The selected value. Used when the component is controlled." } }, - "classDescriptions": { - "root": { "description": "Styles applied to the root element." }, - "separator": { - "description": "Styles applied to {{nodeName}}.", - "nodeName": "the separator element" - } + "classDescriptions": {}, + "slotDescriptions": { + "root": "Element rendered at the root.", + "separator": "Element rendered between the two inputs.", + "textField": "Form control with an input to render a date. It is rendered twice: once for the start date and once for the end date." } } diff --git a/docs/translations/api-docs/date-pickers/multi-input-time-range-field/multi-input-time-range-field.json b/docs/translations/api-docs/date-pickers/multi-input-time-range-field/multi-input-time-range-field.json index 107711c75d708..896550c640a83 100644 --- a/docs/translations/api-docs/date-pickers/multi-input-time-range-field/multi-input-time-range-field.json +++ b/docs/translations/api-docs/date-pickers/multi-input-time-range-field/multi-input-time-range-field.json @@ -76,7 +76,7 @@ "description": "If true, the format will respect the leading zeroes (for example on dayjs, the format M/D/YYYY will render 8/16/2018) If false, the format will always add leading zeroes (for example on dayjs, the format M/D/YYYY will render 08/16/2018)
Warning n°1: Luxon is not able to respect the leading zeroes when using macro tokens (for example "DD"), so shouldRespectLeadingZeros={true} might lead to inconsistencies when using AdapterLuxon.
Warning n°2: When shouldRespectLeadingZeros={true}, the field will add an invisible character on the sections containing a single digit to make sure onChange is fired. If you need to get the clean value from the input, you can remove this character using input.value.replace(/\\u200e/g, '').
Warning n°3: When used in strict mode, dayjs and moment require to respect the leading zeros. This mean that when using shouldRespectLeadingZeros={false}, if you retrieve the value directly from the input (not listening to onChange) and your format contains tokens without leading zeros, the value will not be parsed by your library." }, "slotProps": { "description": "The props used for each component slot." }, - "slots": { "description": "Overridable slots." }, + "slots": { "description": "Overridable component slots." }, "spacing": { "description": "Defines the space between immediate children." }, "sx": { "description": "The system prop, which allows defining system overrides as well as additional CSS styles." @@ -90,11 +90,10 @@ }, "value": { "description": "The selected value. Used when the component is controlled." } }, - "classDescriptions": { - "root": { "description": "Styles applied to the root element." }, - "separator": { - "description": "Styles applied to {{nodeName}}.", - "nodeName": "the separator element" - } + "classDescriptions": {}, + "slotDescriptions": { + "root": "Element rendered at the root.", + "separator": "Element rendered between the two inputs.", + "textField": "Form control with an input to render a date. It is rendered twice: once for the start date and once for the end date." } } diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx index 6d58b8a4bb59b..706ab5665adca 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx @@ -1,62 +1,27 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import clsx from 'clsx'; -import Stack, { StackProps } from '@mui/material/Stack'; -import MuiTextField from '@mui/material/TextField'; -import Typography from '@mui/material/Typography'; -import { styled, useThemeProps } from '@mui/material/styles'; -import useSlotProps from '@mui/utils/useSlotProps'; +import { useDateRangeManager, UseDateRangeManagerReturnValue } from '../managers'; import { - unstable_composeClasses as composeClasses, - unstable_generateUtilityClass as generateUtilityClass, - unstable_generateUtilityClasses as generateUtilityClasses, -} from '@mui/utils'; -import { cleanFieldResponse, useFieldOwnerState } from '@mui/x-date-pickers/internals'; -import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; -import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; + // The alias is needed to have the doc gen working. + createMultiInputRangeField as createMultiInputDateRangeField, + MultiInputRangeFieldProps, +} from '../internals/utils/createMultiInputRangeField'; import { - MultiInputDateRangeFieldProps, - MultiInputDateRangeFieldSlotProps, -} from './MultiInputDateRangeField.types'; -import { useMultiInputDateRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField'; -import { MultiInputRangeFieldClasses, RangePosition } from '../models'; + getMultiInputDateRangeFieldUtilityClass, + MultiInputDateRangeFieldClasses, +} from './multiInputDateRangeFieldClasses'; -export const multiInputDateRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses( - 'MuiMultiInputDateRangeField', - ['root', 'separator'], -); - -export const getMultiInputDateRangeFieldUtilityClass = (slot: string) => - generateUtilityClass('MuiMultiInputDateRangeField', slot); - -const useUtilityClasses = (classes: Partial | undefined) => { - const slots = { - root: ['root'], - separator: ['separator'], - }; - - return composeClasses(slots, getMultiInputDateRangeFieldUtilityClass, classes); -}; - -const MultiInputDateRangeFieldRoot = styled( - React.forwardRef((props: StackProps, ref: React.Ref) => ( - - )), - { - name: 'MuiMultiInputDateRangeField', - slot: 'Root', - overridesResolver: (props, styles) => styles.root, - }, -)({}); - -const MultiInputDateRangeFieldSeparator = styled(Typography, { - name: 'MuiMultiInputDateRangeField', - slot: 'Separator', - overridesResolver: (props, styles) => styles.separator, -})({ - lineHeight: '1.4375em', // 23px -}); +export interface MultiInputDateRangeFieldProps + extends MultiInputRangeFieldProps< + UseDateRangeManagerReturnValue + > { + // We need to redefine the classes here, otherwise we don't have the doc generation. + /** + * Override or extend the styles applied to the component. + */ + classes?: Partial; +} type MultiInputDateRangeFieldComponent = (< TEnableAccessibleFieldDOMStructure extends boolean = true, @@ -75,107 +40,10 @@ type MultiInputDateRangeFieldComponent = (< * * - [MultiInputDateRangeField API](https://mui.com/x/api/multi-input-date-range-field/) */ -const MultiInputDateRangeField = React.forwardRef(function MultiInputDateRangeField< - TEnableAccessibleFieldDOMStructure extends boolean = true, ->( - inProps: MultiInputDateRangeFieldProps, - ref: React.Ref, -) { - const themeProps = useThemeProps({ - props: inProps, - name: 'MuiMultiInputDateRangeField', - }); - - const { internalProps, forwardedProps } = useSplitFieldProps(themeProps, 'date'); - - const { - slots, - slotProps, - unstableStartFieldRef, - unstableEndFieldRef, - className, - classes: classesProp, - ...otherForwardedProps - } = forwardedProps; - - const ownerState = useFieldOwnerState(internalProps); - const classes = useUtilityClasses(classesProp); - - const Root = slots?.root ?? MultiInputDateRangeFieldRoot; - const rootProps = useSlotProps({ - elementType: Root, - externalSlotProps: slotProps?.root, - externalForwardedProps: otherForwardedProps, - additionalProps: { - ref, - }, - ownerState, - className: clsx(className, classes.root), - }); - - const startTextFieldProps = useSlotProps< - typeof PickersTextField, - MultiInputDateRangeFieldSlotProps['textField'], - {}, - MultiInputDateRangeFieldProps & { - position: RangePosition; - } - >({ - elementType: PickersTextField, - externalSlotProps: slotProps?.textField, - ownerState: { ...ownerState, position: 'start' }, - }); - const endTextFieldProps = useSlotProps< - typeof PickersTextField, - MultiInputDateRangeFieldSlotProps['textField'], - {}, - MultiInputDateRangeFieldProps & { - position: RangePosition; - } - >({ - elementType: PickersTextField, - externalSlotProps: slotProps?.textField, - ownerState: { ...ownerState, position: 'end' }, - }); - - const Separator = slots?.separator ?? MultiInputDateRangeFieldSeparator; - const separatorProps = useSlotProps({ - elementType: Separator, - externalSlotProps: slotProps?.separator, - additionalProps: { - children: ` ${internalProps.dateSeparator ?? '–'} `, - }, - ownerState, - className: classes.separator, - }); - - const fieldResponse = useMultiInputDateRangeField< - TEnableAccessibleFieldDOMStructure, - typeof startTextFieldProps - >({ - sharedProps: internalProps, - startTextFieldProps, - endTextFieldProps, - unstableStartFieldRef, - unstableEndFieldRef, - }); - - const { textFieldProps: startDateProps } = cleanFieldResponse(fieldResponse.startDate); - const { textFieldProps: endDateProps } = cleanFieldResponse(fieldResponse.endDate); - - const TextField = - slots?.textField ?? - (fieldResponse.startDate.enableAccessibleFieldDOMStructure === false - ? MuiTextField - : PickersTextField); - - return ( - - - - - - ); +const MultiInputDateRangeField = createMultiInputDateRangeField({ + name: 'MuiMultiInputDateRangeField', + getUtilityClass: getMultiInputDateRangeFieldUtilityClass, + useManager: useDateRangeManager, }) as MultiInputDateRangeFieldComponent; MultiInputDateRangeField.propTypes = { @@ -185,6 +53,7 @@ MultiInputDateRangeField.propTypes = { // ---------------------------------------------------------------------- /** * If `true`, the `input` element is focused during the first mount. + * @default false */ autoFocus: PropTypes.bool, /** diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.types.ts b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.types.ts deleted file mode 100644 index 6565d64012de7..0000000000000 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.types.ts +++ /dev/null @@ -1,90 +0,0 @@ -import * as React from 'react'; -import type { TypographyProps } from '@mui/material/Typography'; -import type { StackProps } from '@mui/material/Stack'; -import type { TextFieldProps } from '@mui/material/TextField'; -import { FieldOwnerState } from '@mui/x-date-pickers/models'; -import { SlotComponentPropsFromProps } from '@mui/x-internals/types'; -import { PickersTextFieldProps } from '@mui/x-date-pickers/PickersTextField'; -import { UseMultiInputRangeFieldParams } from '../internals/hooks/useMultiInputRangeField/useMultiInputRangeField.types'; -import { - MultiInputFieldRefs, - MultiInputRangeFieldClasses, - RangePosition, - UseDateRangeFieldProps, -} from '../models'; - -export type UseMultiInputDateRangeFieldParams< - TEnableAccessibleFieldDOMStructure extends boolean, - TTextFieldSlotProps extends {}, -> = UseMultiInputRangeFieldParams< - UseMultiInputDateRangeFieldProps, - TTextFieldSlotProps ->; - -export interface UseMultiInputDateRangeFieldProps< - TEnableAccessibleFieldDOMStructure extends boolean, -> extends Omit< - UseDateRangeFieldProps, - 'unstableFieldRef' | 'clearable' | 'onClear' - >, - MultiInputFieldRefs {} - -export type UseMultiInputDateRangeFieldComponentProps< - TEnableAccessibleFieldDOMStructure extends boolean, - TChildProps extends {}, -> = Omit> & - UseMultiInputDateRangeFieldProps; - -export interface MultiInputDateRangeFieldProps< - TEnableAccessibleFieldDOMStructure extends boolean = true, -> extends UseMultiInputDateRangeFieldComponentProps< - TEnableAccessibleFieldDOMStructure, - Omit - > { - autoFocus?: boolean; - /** - * Override or extend the styles applied to the component. - */ - classes?: Partial; - /** - * Overridable component slots. - * @default {} - */ - slots?: MultiInputDateRangeFieldSlots; - /** - * The props used for each component slot. - * @default {} - */ - slotProps?: MultiInputDateRangeFieldSlotProps; -} - -export interface MultiInputDateRangeFieldSlots { - /** - * Element rendered at the root. - * @default MultiInputDateRangeFieldRoot - */ - root?: React.ElementType; - /** - * Form control with an input to render a date. - * It is rendered twice: once for the start date and once for the end date. - * @default , or from '@mui/material' if `enableAccessibleFieldDOMStructure` is `false`. - */ - textField?: React.ElementType; - /** - * Element rendered between the two inputs. - * @default MultiInputDateRangeFieldSeparator - */ - separator?: React.ElementType; -} - -export interface MultiInputDateRangeFieldSlotProps { - root?: SlotComponentPropsFromProps; - textField?: SlotComponentPropsFromProps< - PickersTextFieldProps | TextFieldProps, - {}, - FieldOwnerState & { - position: RangePosition; - } - >; - separator?: SlotComponentPropsFromProps; -} diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/index.ts b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/index.ts index ac481ccd21139..28ae5b71ccc12 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/index.ts +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/index.ts @@ -1,11 +1,16 @@ +export { MultiInputDateRangeField } from './MultiInputDateRangeField'; +export type { MultiInputDateRangeFieldProps } from './MultiInputDateRangeField'; + export { - MultiInputDateRangeField, - getMultiInputDateRangeFieldUtilityClass, multiInputDateRangeFieldClasses, -} from './MultiInputDateRangeField'; -export { useMultiInputDateRangeField as unstable_useMultiInputDateRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField'; + getMultiInputDateRangeFieldUtilityClass, +} from './multiInputDateRangeFieldClasses'; +export type { + MultiInputDateRangeFieldClassKey, + MultiInputDateRangeFieldClasses, +} from './multiInputDateRangeFieldClasses'; + export type { - UseMultiInputDateRangeFieldProps, - UseMultiInputDateRangeFieldComponentProps, - MultiInputDateRangeFieldProps, -} from './MultiInputDateRangeField.types'; + MultiInputRangeFieldSlots as MultiInputDateRangeFieldSlots, + MultiInputRangeFieldSlotProps as MultiInputDateRangeFieldSlotProps, +} from '../internals/utils/createMultiInputRangeField'; diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/multiInputDateRangeFieldClasses.ts b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/multiInputDateRangeFieldClasses.ts new file mode 100644 index 0000000000000..8fe3e372bb87c --- /dev/null +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/multiInputDateRangeFieldClasses.ts @@ -0,0 +1,15 @@ +import generateUtilityClass from '@mui/utils/generateUtilityClass'; +import generateUtilityClasses from '@mui/utils/generateUtilityClasses'; +import { MultiInputRangeFieldClasses } from '../internals/utils/createMultiInputRangeField'; + +export interface MultiInputDateRangeFieldClasses extends MultiInputRangeFieldClasses {} + +export type MultiInputDateRangeFieldClassKey = keyof MultiInputRangeFieldClasses; + +export const multiInputDateRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses( + 'MuiMultiInputDateRangeField', + ['root', 'separator'], +); + +export const getMultiInputDateRangeFieldUtilityClass = (slot: string) => + generateUtilityClass('MuiMultiInputDateRangeField', slot); diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx index d74e569613ef4..e524f8e4fbf02 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx @@ -1,60 +1,28 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import clsx from 'clsx'; -import Stack, { StackProps } from '@mui/material/Stack'; -import MuiTextField from '@mui/material/TextField'; -import Typography from '@mui/material/Typography'; -import { styled, useThemeProps } from '@mui/material/styles'; -import useSlotProps from '@mui/utils/useSlotProps'; +import { useDateTimeRangeManager, UseDateTimeRangeManagerReturnValue } from '../managers'; import { - unstable_composeClasses as composeClasses, - unstable_generateUtilityClass as generateUtilityClass, - unstable_generateUtilityClasses as generateUtilityClasses, -} from '@mui/utils'; -import { cleanFieldResponse, useFieldOwnerState } from '@mui/x-date-pickers/internals'; -import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; -import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; + // The alias is needed to have the doc gen working. + createMultiInputRangeField as createMultiInputDateTimeRangeField, + MultiInputRangeFieldProps, +} from '../internals/utils/createMultiInputRangeField'; import { - MultiInputDateTimeRangeFieldProps, - MultiInputDateTimeRangeFieldSlotProps, -} from './MultiInputDateTimeRangeField.types'; -import { useMultiInputDateTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField'; -import { MultiInputRangeFieldClasses, RangePosition } from '../models'; + getMultiInputDateTimeRangeFieldUtilityClass, + MultiInputDateTimeRangeFieldClasses, +} from './multiInputDateTimeRangeFieldClasses'; -export const multiInputDateTimeRangeFieldClasses: MultiInputRangeFieldClasses = - generateUtilityClasses('MuiMultiInputDateTimeRangeField', ['root', 'separator']); - -export const getMultiInputDateTimeRangeFieldUtilityClass = (slot: string) => - generateUtilityClass('MuiMultiInputDateTimeRangeField', slot); - -const useUtilityClasses = (classes: Partial | undefined) => { - const slots = { - root: ['root'], - separator: ['separator'], - }; - - return composeClasses(slots, getMultiInputDateTimeRangeFieldUtilityClass, classes); -}; - -const MultiInputDateTimeRangeFieldRoot = styled( - React.forwardRef((props: StackProps, ref: React.Ref) => ( - - )), - { - name: 'MuiMultiInputDateTimeRangeField', - slot: 'Root', - overridesResolver: (props, styles) => styles.root, - }, -)({}); - -const MultiInputDateTimeRangeFieldSeparator = styled(Typography, { - name: 'MuiMultiInputDateTimeRangeField', - slot: 'Separator', - overridesResolver: (props, styles) => styles.separator, -})({ - lineHeight: '1.4375em', // 23px -}); +export interface MultiInputDateTimeRangeFieldProps< + TEnableAccessibleFieldDOMStructure extends boolean, +> extends MultiInputRangeFieldProps< + UseDateTimeRangeManagerReturnValue + > { + // We need to redefine the classes here, otherwise we don't have the doc generation. + /** + * Override or extend the styles applied to the component. + */ + classes?: Partial; +} type MultiInputDateTimeRangeFieldComponent = (< TEnableAccessibleFieldDOMStructure extends boolean = true, @@ -73,107 +41,10 @@ type MultiInputDateTimeRangeFieldComponent = (< * * - [MultiInputDateTimeRangeField API](https://mui.com/x/api/multi-input-date-time-range-field/) */ -const MultiInputDateTimeRangeField = React.forwardRef(function MultiInputDateTimeRangeField< - TEnableAccessibleFieldDOMStructure extends boolean = true, ->( - inProps: MultiInputDateTimeRangeFieldProps, - ref: React.Ref, -) { - const themeProps = useThemeProps({ - props: inProps, - name: 'MuiMultiInputDateTimeRangeField', - }); - - const { internalProps, forwardedProps } = useSplitFieldProps(themeProps, 'date-time'); - - const { - slots, - slotProps, - unstableStartFieldRef, - unstableEndFieldRef, - className, - classes: classesProp, - ...otherForwardedProps - } = forwardedProps; - - const ownerState = useFieldOwnerState(themeProps); - const classes = useUtilityClasses(classesProp); - - const Root = slots?.root ?? MultiInputDateTimeRangeFieldRoot; - const rootProps = useSlotProps({ - elementType: Root, - externalSlotProps: slotProps?.root, - externalForwardedProps: otherForwardedProps, - additionalProps: { - ref, - }, - ownerState, - className: clsx(className, classes.root), - }); - - const startTextFieldProps = useSlotProps< - typeof PickersTextField, - MultiInputDateTimeRangeFieldSlotProps['textField'], - {}, - MultiInputDateTimeRangeFieldProps & { - position: RangePosition; - } - >({ - elementType: PickersTextField, - externalSlotProps: slotProps?.textField, - ownerState: { ...ownerState, position: 'start' }, - }); - const endTextFieldProps = useSlotProps< - typeof PickersTextField, - MultiInputDateTimeRangeFieldSlotProps['textField'], - {}, - MultiInputDateTimeRangeFieldProps & { - position: RangePosition; - } - >({ - elementType: PickersTextField, - externalSlotProps: slotProps?.textField, - ownerState: { ...ownerState, position: 'end' }, - }); - - const Separator = slots?.separator ?? MultiInputDateTimeRangeFieldSeparator; - const separatorProps = useSlotProps({ - elementType: Separator, - externalSlotProps: slotProps?.separator, - additionalProps: { - children: ` ${internalProps.dateSeparator ?? '–'} `, - }, - ownerState, - className: classes.separator, - }); - - const fieldResponse = useMultiInputDateTimeRangeField< - TEnableAccessibleFieldDOMStructure, - typeof startTextFieldProps - >({ - sharedProps: internalProps, - startTextFieldProps, - endTextFieldProps, - unstableStartFieldRef, - unstableEndFieldRef, - }); - - const { textFieldProps: startDateProps } = cleanFieldResponse(fieldResponse.startDate); - const { textFieldProps: endDateProps } = cleanFieldResponse(fieldResponse.endDate); - - const TextField = - slots?.textField ?? - (fieldResponse.startDate.enableAccessibleFieldDOMStructure === false - ? MuiTextField - : PickersTextField); - - return ( - - - - - - ); +const MultiInputDateTimeRangeField = createMultiInputDateTimeRangeField({ + name: 'MuiMultiInputDateTimeRangeField', + getUtilityClass: getMultiInputDateTimeRangeFieldUtilityClass, + useManager: useDateTimeRangeManager, }) as MultiInputDateTimeRangeFieldComponent; MultiInputDateTimeRangeField.propTypes = { @@ -188,6 +59,7 @@ MultiInputDateTimeRangeField.propTypes = { ampm: PropTypes.bool, /** * If `true`, the `input` element is focused during the first mount. + * @default false */ autoFocus: PropTypes.bool, /** diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.types.ts b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.types.ts deleted file mode 100644 index 51675345af78b..0000000000000 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.types.ts +++ /dev/null @@ -1,89 +0,0 @@ -import * as React from 'react'; -import type { TypographyProps } from '@mui/material/Typography'; -import type { StackProps } from '@mui/material/Stack'; -import type { TextFieldProps } from '@mui/material/TextField'; -import { FieldOwnerState } from '@mui/x-date-pickers/models'; -import { SlotComponentPropsFromProps } from '@mui/x-internals/types'; -import { PickersTextFieldProps } from '@mui/x-date-pickers/PickersTextField'; -import { UseDateTimeRangeFieldProps } from '../internals/models/dateTimeRange'; -import { UseMultiInputRangeFieldParams } from '../internals/hooks/useMultiInputRangeField/useMultiInputRangeField.types'; -import { MultiInputFieldRefs, MultiInputRangeFieldClasses, RangePosition } from '../models'; - -export type UseMultiInputDateTimeRangeFieldParams< - TEnableAccessibleFieldDOMStructure extends boolean, - TTextFieldSlotProps extends {}, -> = UseMultiInputRangeFieldParams< - UseMultiInputDateTimeRangeFieldProps, - TTextFieldSlotProps ->; - -export interface UseMultiInputDateTimeRangeFieldProps< - TEnableAccessibleFieldDOMStructure extends boolean, -> extends Omit< - UseDateTimeRangeFieldProps, - 'unstableFieldRef' | 'clearable' | 'onClear' - >, - MultiInputFieldRefs {} - -export type UseMultiInputDateTimeRangeFieldComponentProps< - TEnableAccessibleFieldDOMStructure extends boolean, - TChildProps extends {}, -> = Omit< - TChildProps, - keyof UseMultiInputDateTimeRangeFieldProps -> & - UseMultiInputDateTimeRangeFieldProps; - -export interface MultiInputDateTimeRangeFieldProps< - TEnableAccessibleFieldDOMStructure extends boolean = true, -> extends UseMultiInputDateTimeRangeFieldComponentProps< - TEnableAccessibleFieldDOMStructure, - Omit - > { - autoFocus?: boolean; - /** - * Override or extend the styles applied to the component. - */ - classes?: Partial; - /** - * Overridable component slots. - * @default {} - */ - slots?: MultiInputDateTimeRangeFieldSlots; - /** - * The props used for each component slot. - * @default {} - */ - slotProps?: MultiInputDateTimeRangeFieldSlotProps; -} - -export interface MultiInputDateTimeRangeFieldSlots { - /** - * Element rendered at the root. - * @default MultiInputDateTimeRangeFieldRoot - */ - root?: React.ElementType; - /** - * Form control with an input to render a date and time. - * It is rendered twice: once for the start date time and once for the end date time. - * @default TextField from '@mui/material' or PickersTextField if `enableAccessibleFieldDOMStructure` is `true`. - */ - textField?: React.ElementType; - /** - * Element rendered between the two inputs. - * @default MultiInputDateTimeRangeFieldSeparator - */ - separator?: React.ElementType; -} - -export interface MultiInputDateTimeRangeFieldSlotProps { - root?: SlotComponentPropsFromProps; - textField?: SlotComponentPropsFromProps< - PickersTextFieldProps | TextFieldProps, - {}, - FieldOwnerState & { - position: RangePosition; - } - >; - separator?: SlotComponentPropsFromProps; -} diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/index.ts b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/index.ts index 829bda46788e9..35c2a5a9b0613 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/index.ts +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/index.ts @@ -1,11 +1,16 @@ +export { MultiInputDateTimeRangeField } from './MultiInputDateTimeRangeField'; +export type { MultiInputDateTimeRangeFieldProps } from './MultiInputDateTimeRangeField'; + export { - MultiInputDateTimeRangeField, - getMultiInputDateTimeRangeFieldUtilityClass, multiInputDateTimeRangeFieldClasses, -} from './MultiInputDateTimeRangeField'; -export { useMultiInputDateTimeRangeField as unstable_useMultiInputDateTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField'; + getMultiInputDateTimeRangeFieldUtilityClass, +} from './multiInputDateTimeRangeFieldClasses'; +export type { + MultiInputDateTimeRangeFieldClassKey, + MultiInputDateTimeRangeFieldClasses, +} from './multiInputDateTimeRangeFieldClasses'; + export type { - UseMultiInputDateTimeRangeFieldProps, - UseMultiInputDateTimeRangeFieldComponentProps, - MultiInputDateTimeRangeFieldProps, -} from './MultiInputDateTimeRangeField.types'; + MultiInputRangeFieldSlots as MultiInputDateTimeRangeFieldSlots, + MultiInputRangeFieldSlotProps as MultiInputDateTimeRangeFieldSlotProps, +} from '../internals/utils/createMultiInputRangeField'; diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/multiInputDateTimeRangeFieldClasses.ts b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/multiInputDateTimeRangeFieldClasses.ts new file mode 100644 index 0000000000000..d05a7de8eac5f --- /dev/null +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/multiInputDateTimeRangeFieldClasses.ts @@ -0,0 +1,13 @@ +import generateUtilityClass from '@mui/utils/generateUtilityClass'; +import generateUtilityClasses from '@mui/utils/generateUtilityClasses'; +import { MultiInputRangeFieldClasses } from '../internals/utils/createMultiInputRangeField'; + +export interface MultiInputDateTimeRangeFieldClasses extends MultiInputRangeFieldClasses {} + +export type MultiInputDateTimeRangeFieldClassKey = keyof MultiInputRangeFieldClasses; + +export const multiInputDateTimeRangeFieldClasses: MultiInputRangeFieldClasses = + generateUtilityClasses('MuiMultiInputDateTimeRangeField', ['root', 'separator']); + +export const getMultiInputDateTimeRangeFieldUtilityClass = (slot: string) => + generateUtilityClass('MuiMultiInputDateTimeRangeField', slot); diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx index f71baf65aac82..49d4fb104ffd3 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx @@ -1,62 +1,27 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import { clsx } from 'clsx'; -import Stack, { StackProps } from '@mui/material/Stack'; -import MuiTextField from '@mui/material/TextField'; -import Typography from '@mui/material/Typography'; -import { styled, useThemeProps } from '@mui/material/styles'; -import useSlotProps from '@mui/utils/useSlotProps'; +import { useTimeRangeManager, UseTimeRangeManagerReturnValue } from '../managers'; import { - unstable_composeClasses as composeClasses, - unstable_generateUtilityClass as generateUtilityClass, - unstable_generateUtilityClasses as generateUtilityClasses, -} from '@mui/utils'; -import { cleanFieldResponse, useFieldOwnerState } from '@mui/x-date-pickers/internals'; -import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; -import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; + // The alias is needed to have the doc gen working. + createMultiInputRangeField as createMultiInputTimeRangeField, + MultiInputRangeFieldProps, +} from '../internals/utils/createMultiInputRangeField'; import { - MultiInputTimeRangeFieldProps, - MultiInputTimeRangeFieldSlotProps, -} from './MultiInputTimeRangeField.types'; -import { useMultiInputTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField'; -import { MultiInputRangeFieldClasses, RangePosition } from '../models'; + getMultiInputTimeRangeFieldUtilityClass, + MultiInputTimeRangeFieldClasses, +} from './multiInputTimeRangeFieldClasses'; -export const multiInputTimeRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses( - 'MuiMultiInputTimeRangeField', - ['root', 'separator'], -); - -export const getMultiInputTimeRangeFieldUtilityClass = (slot: string) => - generateUtilityClass('MuiMultiInputTimeRangeField', slot); - -const useUtilityClasses = (classes: Partial | undefined) => { - const slots = { - root: ['root'], - separator: ['separator'], - }; - - return composeClasses(slots, getMultiInputTimeRangeFieldUtilityClass, classes); -}; - -const MultiInputTimeRangeFieldRoot = styled( - React.forwardRef((props: StackProps, ref: React.Ref) => ( - - )), - { - name: 'MuiMultiInputTimeRangeField', - slot: 'Root', - overridesResolver: (props, styles) => styles.root, - }, -)({}); - -const MultiInputTimeRangeFieldSeparator = styled(Typography, { - name: 'MuiMultiInputTimeRangeField', - slot: 'Separator', - overridesResolver: (props, styles) => styles.separator, -})({ - lineHeight: '1.4375em', // 23px -}); +export interface MultiInputTimeRangeFieldProps + extends MultiInputRangeFieldProps< + UseTimeRangeManagerReturnValue + > { + // We need to redefine the classes here, otherwise we don't have the doc generation. + /** + * Override or extend the styles applied to the component. + */ + classes?: Partial; +} type MultiInputTimeRangeFieldComponent = (< TEnableAccessibleFieldDOMStructure extends boolean = true, @@ -75,108 +40,10 @@ type MultiInputTimeRangeFieldComponent = (< * * - [MultiInputTimeRangeField API](https://mui.com/x/api/multi-input-time-range-field/) */ -const MultiInputTimeRangeField = React.forwardRef(function MultiInputTimeRangeField< - TEnableAccessibleFieldDOMStructure extends boolean = true, ->( - inProps: MultiInputTimeRangeFieldProps, - ref: React.Ref, -) { - const themeProps = useThemeProps({ - props: inProps, - name: 'MuiMultiInputTimeRangeField', - }); - - const { internalProps, forwardedProps } = useSplitFieldProps(themeProps, 'time'); - - const { - slots, - slotProps, - unstableStartFieldRef, - unstableEndFieldRef, - className, - classes: classesProp, - ...otherForwardedProps - } = forwardedProps; - - const ownerState = useFieldOwnerState(themeProps); - const classes = useUtilityClasses(classesProp); - - const Root = slots?.root ?? MultiInputTimeRangeFieldRoot; - const rootProps = useSlotProps({ - elementType: Root, - externalSlotProps: slotProps?.root, - externalForwardedProps: otherForwardedProps, - additionalProps: { - ref, - }, - ownerState, - className: clsx(className, classes.root), - }); - - const startTextFieldProps = useSlotProps< - typeof PickersTextField, - MultiInputTimeRangeFieldSlotProps['textField'], - {}, - MultiInputTimeRangeFieldProps & { - position: RangePosition; - } - >({ - elementType: PickersTextField, - externalSlotProps: slotProps?.textField, - ownerState: { ...ownerState, position: 'start' }, - }); - - const endTextFieldProps = useSlotProps< - typeof PickersTextField, - MultiInputTimeRangeFieldSlotProps['textField'], - {}, - MultiInputTimeRangeFieldProps & { - position: RangePosition; - } - >({ - elementType: PickersTextField, - externalSlotProps: slotProps?.textField, - ownerState: { ...ownerState, position: 'end' }, - }); - - const Separator = slots?.separator ?? MultiInputTimeRangeFieldSeparator; - const separatorProps = useSlotProps({ - elementType: Separator, - externalSlotProps: slotProps?.separator, - additionalProps: { - children: ` ${internalProps.dateSeparator ?? '–'} `, - }, - ownerState, - className: classes.separator, - }); - - const fieldResponse = useMultiInputTimeRangeField< - TEnableAccessibleFieldDOMStructure, - typeof startTextFieldProps - >({ - sharedProps: internalProps, - startTextFieldProps, - endTextFieldProps, - unstableStartFieldRef, - unstableEndFieldRef, - }); - - const { textFieldProps: startDateProps } = cleanFieldResponse(fieldResponse.startDate); - const { textFieldProps: endDateProps } = cleanFieldResponse(fieldResponse.endDate); - - const TextField = - slots?.textField ?? - (fieldResponse.startDate.enableAccessibleFieldDOMStructure === false - ? MuiTextField - : PickersTextField); - - return ( - - - - - - ); +const MultiInputTimeRangeField = createMultiInputTimeRangeField({ + name: 'MuiMultiInputTimeRangeField', + getUtilityClass: getMultiInputTimeRangeFieldUtilityClass, + useManager: useTimeRangeManager, }) as MultiInputTimeRangeFieldComponent; MultiInputTimeRangeField.propTypes = { @@ -191,6 +58,7 @@ MultiInputTimeRangeField.propTypes = { ampm: PropTypes.bool, /** * If `true`, the `input` element is focused during the first mount. + * @default false */ autoFocus: PropTypes.bool, /** @@ -359,7 +227,7 @@ MultiInputTimeRangeField.propTypes = { */ slotProps: PropTypes.object, /** - * Overridable slots. + * Overridable component slots. * @default {} */ slots: PropTypes.object, diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.types.ts b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.types.ts deleted file mode 100644 index 08708712d12de..0000000000000 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.types.ts +++ /dev/null @@ -1,86 +0,0 @@ -import * as React from 'react'; -import type { TypographyProps } from '@mui/material/Typography'; -import type { StackProps } from '@mui/material/Stack'; -import type { TextFieldProps } from '@mui/material/TextField'; -import { FieldOwnerState } from '@mui/x-date-pickers/models'; -import { SlotComponentPropsFromProps } from '@mui/x-internals/types'; -import { PickersTextFieldProps } from '@mui/x-date-pickers/PickersTextField'; -import { UseTimeRangeFieldProps } from '../internals/models/timeRange'; -import { UseMultiInputRangeFieldParams } from '../internals/hooks/useMultiInputRangeField/useMultiInputRangeField.types'; -import { MultiInputFieldRefs, MultiInputRangeFieldClasses, RangePosition } from '../models'; - -export type UseMultiInputTimeRangeFieldParams< - TEnableAccessibleFieldDOMStructure extends boolean, - TTextFieldSlotProps extends {}, -> = UseMultiInputRangeFieldParams< - UseMultiInputTimeRangeFieldProps, - TTextFieldSlotProps ->; - -export interface UseMultiInputTimeRangeFieldProps< - TEnableAccessibleFieldDOMStructure extends boolean, -> extends Omit< - UseTimeRangeFieldProps, - 'unstableFieldRef' | 'clearable' | 'onClear' - >, - MultiInputFieldRefs {} - -export type UseMultiInputTimeRangeFieldComponentProps< - TEnableAccessibleFieldDOMStructure extends boolean, - TChildProps extends {}, -> = Omit> & - UseMultiInputTimeRangeFieldProps; - -export interface MultiInputTimeRangeFieldProps< - TEnableAccessibleFieldDOMStructure extends boolean = true, -> extends UseMultiInputTimeRangeFieldComponentProps< - TEnableAccessibleFieldDOMStructure, - Omit - > { - autoFocus?: boolean; - /** - * Override or extend the styles applied to the component. - */ - classes?: Partial; - /** - * Overridable slots. - * @default {} - */ - slots?: MultiInputTimeRangeFieldSlots; - /** - * The props used for each component slot. - * @default {} - */ - slotProps?: MultiInputTimeRangeFieldSlotProps; -} - -export interface MultiInputTimeRangeFieldSlots { - /** - * Element rendered at the root. - * @default MultiInputTimeRangeFieldRoot - */ - root?: React.ElementType; - /** - * Form control with an input to render a time. - * It is rendered twice: once for the start time and once for the end time. - * @default TextField from '@mui/material' or PickersTextField if `enableAccessibleFieldDOMStructure` is `true`. - */ - textField?: React.ElementType; - /** - * Element rendered between the two inputs. - * @default MultiInputTimeRangeFieldSeparator - */ - separator?: React.ElementType; -} - -export interface MultiInputTimeRangeFieldSlotProps { - root?: SlotComponentPropsFromProps; - textField?: SlotComponentPropsFromProps< - PickersTextFieldProps | TextFieldProps, - {}, - FieldOwnerState & { - position: RangePosition; - } - >; - separator?: SlotComponentPropsFromProps; -} diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/index.ts b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/index.ts index d1d7744242ee1..6099c1f5878d8 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/index.ts +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/index.ts @@ -1,11 +1,16 @@ +export { MultiInputTimeRangeField } from './MultiInputTimeRangeField'; +export type { MultiInputTimeRangeFieldProps } from './MultiInputTimeRangeField'; + export { - MultiInputTimeRangeField, - getMultiInputTimeRangeFieldUtilityClass, multiInputTimeRangeFieldClasses, -} from './MultiInputTimeRangeField'; -export { useMultiInputTimeRangeField as unstable_useMultiInputTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField'; + getMultiInputTimeRangeFieldUtilityClass, +} from './multiInputTimeRangeFieldClasses'; +export type { + MultiInputTimeRangeFieldClassKey, + MultiInputTimeRangeFieldClasses, +} from './multiInputTimeRangeFieldClasses'; + export type { - UseMultiInputTimeRangeFieldProps, - UseMultiInputTimeRangeFieldComponentProps, - MultiInputTimeRangeFieldProps, -} from './MultiInputTimeRangeField.types'; + MultiInputRangeFieldSlots as MultiInputTimeRangeFieldSlots, + MultiInputRangeFieldSlotProps as MultiInputTimeRangeFieldSlotProps, +} from '../internals/utils/createMultiInputRangeField'; diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/multiInputTimeRangeFieldClasses.ts b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/multiInputTimeRangeFieldClasses.ts new file mode 100644 index 0000000000000..bf15c75ec7fde --- /dev/null +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/multiInputTimeRangeFieldClasses.ts @@ -0,0 +1,15 @@ +import generateUtilityClass from '@mui/utils/generateUtilityClass'; +import generateUtilityClasses from '@mui/utils/generateUtilityClasses'; +import { MultiInputRangeFieldClasses } from '../internals/utils/createMultiInputRangeField'; + +export interface MultiInputTimeRangeFieldClasses extends MultiInputRangeFieldClasses {} + +export type MultiInputTimeRangeFieldClassKey = keyof MultiInputRangeFieldClasses; + +export const multiInputTimeRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses( + 'MuiMultiInputTimeRangeField', + ['root', 'separator'], +); + +export const getMultiInputTimeRangeFieldUtilityClass = (slot: string) => + generateUtilityClass('MuiMultiInputTimeRangeField', slot); 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 7828b1643c3c0..efbcdf224df24 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts @@ -1,24 +1,14 @@ import { - PickerRangeValue, - UseFieldInternalProps, ExportedPickerFieldUIProps, PickerFieldUISlots, PickerFieldUISlotProps, } from '@mui/x-date-pickers/internals'; import { BuiltInFieldTextFieldProps } from '@mui/x-date-pickers/models'; -import type { DateRangeValidationError, UseDateRangeFieldProps } from '../models'; +import { DateRangeManagerFieldInternalProps } from '../managers/useDateRangeManager'; export interface UseSingleInputDateRangeFieldProps< TEnableAccessibleFieldDOMStructure extends boolean, -> extends UseDateRangeFieldProps, - Pick< - UseFieldInternalProps< - PickerRangeValue, - TEnableAccessibleFieldDOMStructure, - DateRangeValidationError - >, - 'unstableFieldRef' - >, +> extends DateRangeManagerFieldInternalProps, // TODO v8: Remove once the range fields open with a button. Omit {} 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 d7f51a40420b5..576a1b9c59d08 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.types.ts @@ -2,24 +2,13 @@ import { ExportedPickerFieldUIProps, PickerFieldUISlots, PickerFieldUISlotProps, - PickerRangeValue, - UseFieldInternalProps, } from '@mui/x-date-pickers/internals'; import { BuiltInFieldTextFieldProps } from '@mui/x-date-pickers/models'; -import { UseDateTimeRangeFieldProps } from '../internals/models'; -import { DateTimeRangeValidationError } from '../models'; +import { DateTimeRangeManagerFieldInternalProps } from '../managers/useDateTimeRangeManager'; export interface UseSingleInputDateTimeRangeFieldProps< TEnableAccessibleFieldDOMStructure extends boolean, -> extends UseDateTimeRangeFieldProps, - Pick< - UseFieldInternalProps< - PickerRangeValue, - TEnableAccessibleFieldDOMStructure, - DateTimeRangeValidationError - >, - 'unstableFieldRef' - >, +> extends DateTimeRangeManagerFieldInternalProps, // TODO v8: Remove once the range fields open with a button. Omit {} 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 56fcb66f9b5f9..ae1a386ea7d4a 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts @@ -2,24 +2,13 @@ import { ExportedPickerFieldUIProps, PickerFieldUISlots, PickerFieldUISlotProps, - PickerRangeValue, - UseFieldInternalProps, } from '@mui/x-date-pickers/internals'; import { BuiltInFieldTextFieldProps } from '@mui/x-date-pickers/models'; -import { UseTimeRangeFieldProps } from '../internals/models'; -import { TimeRangeValidationError } from '../models'; +import { TimeRangeManagerFieldInternalProps } from '../managers/useTimeRangeManager'; export interface UseSingleInputTimeRangeFieldProps< TEnableAccessibleFieldDOMStructure extends boolean, -> extends UseTimeRangeFieldProps, - Pick< - UseFieldInternalProps< - PickerRangeValue, - TEnableAccessibleFieldDOMStructure, - TimeRangeValidationError - >, - 'unstableFieldRef' - >, +> extends TimeRangeManagerFieldInternalProps, // TODO v8: Remove once the range fields open with a button. Omit {} diff --git a/packages/x-date-pickers-pro/src/hooks/index.ts b/packages/x-date-pickers-pro/src/hooks/index.ts index 1a00cfc2ec27b..9ac0fdf9beb14 100644 --- a/packages/x-date-pickers-pro/src/hooks/index.ts +++ b/packages/x-date-pickers-pro/src/hooks/index.ts @@ -1 +1,2 @@ export { usePickerRangePositionContext } from './usePickerRangePositionContext'; +export { useMultiInputRangeField as unstable_useMultiInputRangeField } from './useMultiInputRangeField'; diff --git a/packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/index.ts b/packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/index.ts new file mode 100644 index 0000000000000..d1c290e53e6d8 --- /dev/null +++ b/packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/index.ts @@ -0,0 +1 @@ +export { useMultiInputRangeField } from './useMultiInputRangeField'; diff --git a/packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/useMultiInputRangeField.ts b/packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/useMultiInputRangeField.ts new file mode 100644 index 0000000000000..a7517a9a0d74e --- /dev/null +++ b/packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/useMultiInputRangeField.ts @@ -0,0 +1,199 @@ +'use client'; +import useEventCallback from '@mui/utils/useEventCallback'; +import { + FieldChangeHandler, + FieldChangeHandlerContext, + PickerManagerEnableAccessibleFieldDOMStructure, + PickerManagerError, + PickerManagerFieldInternalProps, + PickerRangeValue, + PickerValue, + useControlledValueWithTimezone, + useFieldInternalPropsWithDefaults, + UseFieldResponse, +} from '@mui/x-date-pickers/internals'; +import { useValidation } from '@mui/x-date-pickers/validation'; +import { useMultiInputRangeFieldTextFieldProps } from './useMultiInputRangeFieldTextFieldProps'; +import { useMultiInputRangeFieldSelectedSections } from './useMultiInputRangeFieldSelectedSections'; +import { PickerAnyRangeManager } from '../../internals/models/managers'; + +/** + * Basic example: + * + * ```tsx + * import Box from '@mui/material/Box'; + * import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; + * import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; + * import { useDateRangeManager } from '@mui/x-date-pickers-pro/managers'; + * + * function MultiInputField(props) { + * const manager = useDateRangeManager(); + * const { internalProps, forwardedProps } = useSplitFieldProps(props, 'date'); + * const { startDate, endDate } = useMultiInputRangeField({ + * manager, + * internalProps, + * startForwardedProps: forwardedProps, + * endForwardedProps: forwardedProps, + * }); + * + * return ( + * + * + * {' – '} + * + * + * ); + * } + * ``` + * + * @param {UseMultiInputRangeFieldParameters} parameters The parameters of the hook. + * @param {TManager} parameters.manager The manager of the field. + * @param {PickerManagerFieldInternalProps} parameters.internalProps The internal props of the field. + * @param {TForwardedProps} parameters.startForwardedProps The forwarded props of the start field. + * @param {TForwardedProps} parameters.endForwardedProps The forwarded props of the end field. + * @returns {UseMultiInputRangeFieldReturnValue} The props to pass to the start and the end components. + */ +export function useMultiInputRangeField< + TManager extends PickerAnyRangeManager, + TForwardedProps extends { [key: string]: any }, +>( + parameters: UseMultiInputRangeFieldParameters, +): UseMultiInputRangeFieldReturnValue { + type TError = PickerManagerError; + + const { manager, internalProps, startForwardedProps, endForwardedProps } = parameters; + + const internalPropsWithDefaults = useFieldInternalPropsWithDefaults({ + manager, + internalProps, + }); + + const { + value: valueProp, + defaultValue, + format, + formatDensity, + shouldRespectLeadingZeros, + onChange, + disabled, + readOnly, + selectedSections, + onSelectedSectionsChange, + timezone: timezoneProp, + enableAccessibleFieldDOMStructure, + autoFocus, + referenceDate, + unstableStartFieldRef, + unstableEndFieldRef, + } = internalPropsWithDefaults; + + const { value, handleValueChange, timezone } = useControlledValueWithTimezone({ + name: 'useMultiInputRangeField', + timezone: timezoneProp, + value: valueProp, + defaultValue, + referenceDate, + onChange, + valueManager: manager.internal_valueManager, + }); + + const { validationError, getValidationErrorForNewValue } = useValidation({ + props: internalPropsWithDefaults, + value, + timezone, + validator: manager.validator, + onError: internalPropsWithDefaults.onError, + }); + + const buildChangeHandler = (index: 0 | 1): FieldChangeHandler => { + return (newSingleValue, rawContext) => { + const newRange: PickerRangeValue = + index === 0 ? [newSingleValue, value[1]] : [value[0], newSingleValue]; + + const context: FieldChangeHandlerContext = { + ...rawContext, + validationError: getValidationErrorForNewValue(newRange), + }; + + handleValueChange(newRange, context); + }; + }; + + const handleStartDateChange = useEventCallback(buildChangeHandler(0)); + const handleEndDateChange = useEventCallback(buildChangeHandler(1)); + + const selectedSectionsResponse = useMultiInputRangeFieldSelectedSections({ + selectedSections, + onSelectedSectionsChange, + unstableStartFieldRef, + unstableEndFieldRef, + }); + + const sharedProps = { + disabled, + readOnly, + timezone, + format, + formatDensity, + shouldRespectLeadingZeros, + enableAccessibleFieldDOMStructure, + }; + + const startDateProps = useMultiInputRangeFieldTextFieldProps({ + valueType: manager.valueType, + fieldProps: { + error: !!validationError[0], + ...startForwardedProps, + ...selectedSectionsResponse.start, + ...sharedProps, + value: valueProp === undefined ? undefined : valueProp[0], + defaultValue: defaultValue === undefined ? undefined : defaultValue[0], + onChange: handleStartDateChange, + autoFocus, // Do not add on end field. + }, + }); + + const endDateProps = useMultiInputRangeFieldTextFieldProps({ + valueType: manager.valueType, + fieldProps: { + error: !!validationError[1], + ...endForwardedProps, + ...selectedSectionsResponse.end, + ...sharedProps, + value: valueProp === undefined ? undefined : valueProp[1], + defaultValue: defaultValue === undefined ? undefined : defaultValue[1], + onChange: handleEndDateChange, + }, + }); + + return { + startDate: startDateProps, + endDate: endDateProps, + enableAccessibleFieldDOMStructure, + }; +} + +interface UseMultiInputRangeFieldParameters< + TManager extends PickerAnyRangeManager, + TForwardedProps extends {}, +> { + manager: TManager; + internalProps: PickerManagerFieldInternalProps; + startForwardedProps: TForwardedProps; + endForwardedProps: TForwardedProps; +} + +interface UseMultiInputRangeFieldReturnValue< + TManager extends PickerAnyRangeManager, + TForwardedProps extends {}, +> { + startDate: Omit< + UseFieldResponse, TForwardedProps>, + 'clearable' | 'onClear' + >; + endDate: Omit< + UseFieldResponse, TForwardedProps>, + 'clearable' | 'onClear' + >; + enableAccessibleFieldDOMStructure: PickerManagerEnableAccessibleFieldDOMStructure; +} diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputFieldSelectedSections.ts b/packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/useMultiInputRangeFieldSelectedSections.ts similarity index 68% rename from packages/x-date-pickers-pro/src/internals/hooks/useMultiInputFieldSelectedSections.ts rename to packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/useMultiInputRangeFieldSelectedSections.ts index 59956a8c633b1..1d66461f7e622 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputFieldSelectedSections.ts +++ b/packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/useMultiInputRangeFieldSelectedSections.ts @@ -1,3 +1,4 @@ +'use client'; import * as React from 'react'; import useForkRef from '@mui/utils/useForkRef'; import useEventCallback from '@mui/utils/useEventCallback'; @@ -7,15 +8,14 @@ import { UseFieldInternalProps, } from '@mui/x-date-pickers/internals'; import { FieldRef, FieldSelectedSections } from '@mui/x-date-pickers/models'; +import { MultiInputFieldRefs } from '../../models'; -interface UseMultiInputFieldSelectedSectionsParams +interface UseMultiInputRangeFieldSelectedSectionsParameters extends Pick< - UseFieldInternalProps, - 'selectedSections' | 'onSelectedSectionsChange' - > { - unstableStartFieldRef?: React.Ref>; - unstableEndFieldRef?: React.Ref>; -} + UseFieldInternalProps, + 'selectedSections' | 'onSelectedSectionsChange' + >, + MultiInputFieldRefs {} interface UseMultiInputFieldSelectedSectionsResponseItem { unstableFieldRef?: React.Ref>; @@ -28,14 +28,14 @@ interface UseMultiInputFieldSelectedSectionsResponse { end: UseMultiInputFieldSelectedSectionsResponseItem; } -export const useMultiInputFieldSelectedSections = ( - params: UseMultiInputFieldSelectedSectionsParams, +export const useMultiInputRangeFieldSelectedSections = ( + parameters: UseMultiInputRangeFieldSelectedSectionsParameters, ): UseMultiInputFieldSelectedSectionsResponse => { const unstableEndFieldRef = React.useRef>(null); - const handleUnstableEndFieldRef = useForkRef(params.unstableEndFieldRef, unstableEndFieldRef); + const handleUnstableEndFieldRef = useForkRef(parameters.unstableEndFieldRef, unstableEndFieldRef); const [startSelectedSection, setStartSelectedSection] = React.useState( - params.selectedSections ?? null, + parameters.selectedSections ?? null, ); const [endSelectedSection, setEndSelectedSection] = React.useState(null); @@ -51,7 +51,7 @@ export const useMultiInputFieldSelectedSections = ( (newSelectedSections: FieldSelectedSections) => { setStartSelectedSection(newSelectedSections); if (getActiveField() === 'start') { - params.onSelectedSectionsChange?.(newSelectedSections); + parameters.onSelectedSectionsChange?.(newSelectedSections); } }, ); @@ -60,7 +60,7 @@ export const useMultiInputFieldSelectedSections = ( (newSelectedSections: FieldSelectedSections) => { setEndSelectedSection(newSelectedSections); if (getActiveField() === 'end') { - params.onSelectedSectionsChange?.(newSelectedSections); + parameters.onSelectedSectionsChange?.(newSelectedSections); } }, ); @@ -69,18 +69,18 @@ export const useMultiInputFieldSelectedSections = ( return { start: { - unstableFieldRef: params.unstableStartFieldRef, + unstableFieldRef: parameters.unstableStartFieldRef, selectedSections: - activeField === 'start' && params.selectedSections !== undefined - ? params.selectedSections + activeField === 'start' && parameters.selectedSections !== undefined + ? parameters.selectedSections : startSelectedSection, onSelectedSectionsChange: handleStartSelectedSectionChange, }, end: { unstableFieldRef: handleUnstableEndFieldRef, selectedSections: - activeField === 'end' && params.selectedSections !== undefined - ? params.selectedSections + activeField === 'end' && parameters.selectedSections !== undefined + ? parameters.selectedSections : endSelectedSection, onSelectedSectionsChange: handleEndSelectedSectionChange, }, diff --git a/packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/useMultiInputRangeFieldTextFieldProps.ts b/packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/useMultiInputRangeFieldTextFieldProps.ts new file mode 100644 index 0000000000000..9886629d185a2 --- /dev/null +++ b/packages/x-date-pickers-pro/src/hooks/useMultiInputRangeField/useMultiInputRangeFieldTextFieldProps.ts @@ -0,0 +1,105 @@ +import { + useDateManager, + UseDateManagerReturnValue, + useDateTimeManager, + UseDateTimeManagerReturnValue, + useTimeManager, + UseTimeManagerReturnValue, +} from '@mui/x-date-pickers/managers'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; +import { PickerValueType } from '@mui/x-date-pickers/models'; +import { + PickerAnyManager, + PickerManagerEnableAccessibleFieldDOMStructure, + PickerManagerFieldInternalProps, + PickerValue, + useField, + useFieldInternalPropsWithDefaults, + UseFieldResponse, +} from '@mui/x-date-pickers/internals'; +import { PickerAnyRangeManager } from '../../internals/models/managers'; +import { + UseDateRangeManagerReturnValue, + UseDateTimeRangeManagerReturnValue, + UseTimeRangeManagerReturnValue, +} from '../../managers'; + +/** + * @ignore - internal hook. + */ +export function useMultiInputRangeFieldTextFieldProps< + TManager extends PickerAnyRangeManager, + TForwardedProps extends { [key: string]: any }, +>(parameters: UseMultiInputRangeFieldTextFieldProps) { + type TEnableAccessibleFieldDOMStructure = + PickerManagerEnableAccessibleFieldDOMStructure; + + const { fieldProps, valueType } = parameters; + + let useManager: ({ + enableAccessibleFieldDOMStructure, + }: { + enableAccessibleFieldDOMStructure: boolean | undefined; + }) => PickerAnyManager; + switch (valueType) { + case 'date': { + useManager = useDateManager; + break; + } + case 'time': { + useManager = useTimeManager; + break; + } + case 'date-time': { + useManager = useDateTimeManager; + break; + } + default: { + throw new Error(`Unknown valueType: ${valueType}`); + } + } + + const manager = useManager({ + enableAccessibleFieldDOMStructure: fieldProps.enableAccessibleFieldDOMStructure, + }); + + const { forwardedProps, internalProps } = useSplitFieldProps(fieldProps, 'date'); + const internalPropsWithDefaults = useFieldInternalPropsWithDefaults({ + manager, + internalProps, + }); + + const { clearable, onClear, ...fieldResponse } = useField< + PickerValue, + TEnableAccessibleFieldDOMStructure, + typeof forwardedProps, + typeof internalPropsWithDefaults + >({ + forwardedProps, + internalProps: internalPropsWithDefaults, + valueManager: manager.internal_valueManager, + fieldValueManager: manager.internal_fieldValueManager, + validator: manager.validator, + valueType: manager.valueType, + // TODO v8: Add a real aria label before moving the opening logic to the field on range pickers. + getOpenPickerButtonAriaLabel: () => '', + }) as UseFieldResponse; + + return fieldResponse; +} + +interface UseMultiInputRangeFieldTextFieldProps { + valueType: PickerValueType; + fieldProps: PickerManagerFieldInternalProps>; +} + +type GetDerivedManager = + TManager extends UseDateRangeManagerReturnValue + ? UseDateManagerReturnValue + : TManager extends UseTimeRangeManagerReturnValue + ? UseTimeManagerReturnValue + : TManager extends UseDateTimeRangeManagerReturnValue< + infer TEnableAccessibleFieldDOMStructure + > + ? UseDateTimeManagerReturnValue + : never; 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 deleted file mode 100644 index e2b0b8483f184..0000000000000 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField.ts +++ /dev/null @@ -1,149 +0,0 @@ -import useEventCallback from '@mui/utils/useEventCallback'; -import { unstable_useDateField as useDateField } from '@mui/x-date-pickers/DateField'; -import { - FieldChangeHandler, - FieldChangeHandlerContext, - PickerRangeValue, - PickerValue, - UseFieldResponse, - useControlledValueWithTimezone, - useFieldInternalPropsWithDefaults, -} from '@mui/x-date-pickers/internals'; -import { useValidation } from '@mui/x-date-pickers/validation'; -import { DateValidationError } from '@mui/x-date-pickers/models'; -import { UseMultiInputDateRangeFieldParams } from '../../../MultiInputDateRangeField/MultiInputDateRangeField.types'; -import { validateDateRange } from '../../../validation'; -import { rangeValueManager } from '../../utils/valueManagers'; -import type { UseMultiInputRangeFieldResponse } from './useMultiInputRangeField.types'; -import { DateRangeValidationError } from '../../../models'; -import { useMultiInputFieldSelectedSections } from '../useMultiInputFieldSelectedSections'; -import { useDateRangeManager } from '../../../managers'; - -export const useMultiInputDateRangeField = < - TEnableAccessibleFieldDOMStructure extends boolean, - TTextFieldSlotProps extends {}, ->({ - sharedProps, - startTextFieldProps, - unstableStartFieldRef, - endTextFieldProps, - unstableEndFieldRef, -}: UseMultiInputDateRangeFieldParams< - TEnableAccessibleFieldDOMStructure, - TTextFieldSlotProps ->): UseMultiInputRangeFieldResponse => { - const manager = useDateRangeManager(sharedProps); - const sharedPropsWithDefaults = useFieldInternalPropsWithDefaults({ - manager, - internalProps: sharedProps, - }); - - const { - value: valueProp, - defaultValue, - referenceDate, - format, - formatDensity, - shouldRespectLeadingZeros, - onChange, - disabled, - readOnly, - selectedSections, - onSelectedSectionsChange, - timezone: timezoneProp, - enableAccessibleFieldDOMStructure, - autoFocus, - } = sharedPropsWithDefaults; - - const { value, handleValueChange, timezone } = useControlledValueWithTimezone({ - name: 'useMultiInputDateRangeField', - timezone: timezoneProp, - value: valueProp, - defaultValue, - referenceDate, - onChange, - valueManager: rangeValueManager, - }); - - const { validationError, getValidationErrorForNewValue } = useValidation({ - props: sharedPropsWithDefaults, - value, - timezone, - validator: validateDateRange, - 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]; - - const context: FieldChangeHandlerContext = { - ...rawContext, - validationError: getValidationErrorForNewValue(newDateRange), - }; - - handleValueChange(newDateRange, context); - }; - }; - - const handleStartDateChange = useEventCallback(buildChangeHandler(0)); - const handleEndDateChange = useEventCallback(buildChangeHandler(1)); - - const selectedSectionsResponse = useMultiInputFieldSelectedSections({ - selectedSections, - onSelectedSectionsChange, - unstableStartFieldRef, - unstableEndFieldRef, - }); - - const startFieldProps = { - error: !!validationError[0], - ...startTextFieldProps, - ...selectedSectionsResponse.start, - disabled, - readOnly, - format, - formatDensity, - shouldRespectLeadingZeros, - timezone, - value: valueProp === undefined ? undefined : valueProp[0], - defaultValue: defaultValue === undefined ? undefined : defaultValue[0], - onChange: handleStartDateChange, - enableAccessibleFieldDOMStructure, - autoFocus, // Do not add on end field. - }; - - const endFieldProps = { - error: !!validationError[1], - ...endTextFieldProps, - ...selectedSectionsResponse.end, - format, - formatDensity, - shouldRespectLeadingZeros, - disabled, - readOnly, - timezone, - value: valueProp === undefined ? undefined : valueProp[1], - defaultValue: defaultValue === undefined ? undefined : defaultValue[1], - onChange: handleEndDateChange, - enableAccessibleFieldDOMStructure, - }; - - const startDateResponse = useDateField< - TEnableAccessibleFieldDOMStructure, - typeof startFieldProps - >(startFieldProps) as UseFieldResponse; - - const endDateResponse = useDateField( - endFieldProps, - ) as UseFieldResponse; - - return { - startDate: startDateResponse, - endDate: endDateResponse, - }; -}; 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 deleted file mode 100644 index 840ef757f2e9e..0000000000000 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts +++ /dev/null @@ -1,150 +0,0 @@ -import useEventCallback from '@mui/utils/useEventCallback'; -import { unstable_useDateTimeField as useDateTimeField } from '@mui/x-date-pickers/DateTimeField'; -import { - FieldChangeHandler, - FieldChangeHandlerContext, - PickerRangeValue, - PickerValue, - UseFieldResponse, - useControlledValueWithTimezone, - useFieldInternalPropsWithDefaults, -} from '@mui/x-date-pickers/internals'; -import { useValidation } from '@mui/x-date-pickers/validation'; -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 { useMultiInputFieldSelectedSections } from '../useMultiInputFieldSelectedSections'; -import { useDateTimeRangeManager } from '../../../managers'; - -export const useMultiInputDateTimeRangeField = < - TEnableAccessibleFieldDOMStructure extends boolean, - TTextFieldSlotProps extends {}, ->({ - sharedProps, - startTextFieldProps, - unstableStartFieldRef, - endTextFieldProps, - unstableEndFieldRef, -}: UseMultiInputDateTimeRangeFieldParams< - TEnableAccessibleFieldDOMStructure, - TTextFieldSlotProps ->): UseMultiInputRangeFieldResponse => { - const manager = useDateTimeRangeManager(sharedProps); - const sharedPropsWithDefaults = useFieldInternalPropsWithDefaults({ - manager, - internalProps: sharedProps, - }); - - const { - value: valueProp, - defaultValue, - referenceDate, - format, - formatDensity, - shouldRespectLeadingZeros, - onChange, - disabled, - readOnly, - selectedSections, - onSelectedSectionsChange, - timezone: timezoneProp, - enableAccessibleFieldDOMStructure, - autoFocus, - } = sharedPropsWithDefaults; - - const { value, handleValueChange, timezone } = useControlledValueWithTimezone({ - name: 'useMultiInputDateTimeRangeField', - timezone: timezoneProp, - value: valueProp, - defaultValue, - referenceDate, - onChange, - valueManager: rangeValueManager, - }); - - const { validationError, getValidationErrorForNewValue } = useValidation({ - props: sharedPropsWithDefaults, - value, - timezone, - validator: validateDateTimeRange, - 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]; - - const context: FieldChangeHandlerContext = { - ...rawContext, - validationError: getValidationErrorForNewValue(newDateRange), - }; - - handleValueChange(newDateRange, context); - }; - }; - - const handleStartDateChange = useEventCallback(buildChangeHandler(0)); - const handleEndDateChange = useEventCallback(buildChangeHandler(1)); - - const selectedSectionsResponse = useMultiInputFieldSelectedSections({ - selectedSections, - onSelectedSectionsChange, - unstableStartFieldRef, - unstableEndFieldRef, - }); - - const startFieldProps = { - error: !!validationError[0], - ...startTextFieldProps, - ...selectedSectionsResponse.start, - disabled, - readOnly, - format, - formatDensity, - shouldRespectLeadingZeros, - timezone, - value: valueProp === undefined ? undefined : valueProp[0], - defaultValue: defaultValue === undefined ? undefined : defaultValue[0], - onChange: handleStartDateChange, - enableAccessibleFieldDOMStructure, - autoFocus, // Do not add on end field. - }; - - const endFieldProps = { - error: !!validationError[1], - ...endTextFieldProps, - ...selectedSectionsResponse.end, - format, - formatDensity, - shouldRespectLeadingZeros, - disabled, - readOnly, - timezone, - value: valueProp === undefined ? undefined : valueProp[1], - defaultValue: defaultValue === undefined ? undefined : defaultValue[1], - onChange: handleEndDateChange, - enableAccessibleFieldDOMStructure, - }; - - const startDateResponse = useDateTimeField< - TEnableAccessibleFieldDOMStructure, - typeof startFieldProps - >(startFieldProps) as UseFieldResponse; - - const endDateResponse = useDateTimeField< - TEnableAccessibleFieldDOMStructure, - typeof endFieldProps - >(endFieldProps) as UseFieldResponse; - - return { - startDate: startDateResponse, - endDate: endDateResponse, - }; -}; diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputRangeField.types.ts b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputRangeField.types.ts deleted file mode 100644 index b2a961644c39a..0000000000000 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputRangeField.types.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { UseFieldResponse } from '@mui/x-date-pickers/internals'; -import { MultiInputFieldRefs } from '../../../models'; - -export interface UseMultiInputRangeFieldParams< - TSharedProps extends {}, - TTextFieldSlotProps extends {}, -> extends MultiInputFieldRefs { - sharedProps: TSharedProps; - startTextFieldProps: TTextFieldSlotProps; - endTextFieldProps: TTextFieldSlotProps; -} - -export interface UseMultiInputRangeFieldResponse< - TEnableAccessibleFieldDOMStructure extends boolean, - TForwardedProps extends {}, -> { - startDate: UseFieldResponse; - endDate: UseFieldResponse; -} 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 deleted file mode 100644 index 33c54bae45ae1..0000000000000 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts +++ /dev/null @@ -1,149 +0,0 @@ -import useEventCallback from '@mui/utils/useEventCallback'; -import { unstable_useTimeField as useTimeField } from '@mui/x-date-pickers/TimeField'; -import { - FieldChangeHandler, - FieldChangeHandlerContext, - PickerRangeValue, - PickerValue, - UseFieldResponse, - useControlledValueWithTimezone, - useFieldInternalPropsWithDefaults, -} 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 { rangeValueManager } from '../../utils/valueManagers'; -import type { UseMultiInputRangeFieldResponse } from './useMultiInputRangeField.types'; -import { TimeRangeValidationError } from '../../../models'; -import { useMultiInputFieldSelectedSections } from '../useMultiInputFieldSelectedSections'; -import { useTimeRangeManager } from '../../../managers'; - -export const useMultiInputTimeRangeField = < - TEnableAccessibleFieldDOMStructure extends boolean, - TTextFieldSlotProps extends {}, ->({ - sharedProps, - startTextFieldProps, - unstableStartFieldRef, - endTextFieldProps, - unstableEndFieldRef, -}: UseMultiInputTimeRangeFieldParams< - TEnableAccessibleFieldDOMStructure, - TTextFieldSlotProps ->): UseMultiInputRangeFieldResponse => { - const manager = useTimeRangeManager(sharedProps); - const sharedPropsWithDefaults = useFieldInternalPropsWithDefaults({ - manager, - internalProps: sharedProps, - }); - - const { - value: valueProp, - defaultValue, - referenceDate, - format, - formatDensity, - shouldRespectLeadingZeros, - onChange, - disabled, - readOnly, - selectedSections, - onSelectedSectionsChange, - timezone: timezoneProp, - enableAccessibleFieldDOMStructure, - autoFocus, - } = sharedPropsWithDefaults; - - const { value, handleValueChange, timezone } = useControlledValueWithTimezone({ - name: 'useMultiInputTimeRangeField', - timezone: timezoneProp, - value: valueProp, - defaultValue, - onChange, - valueManager: rangeValueManager, - referenceDate, - }); - - const { validationError, getValidationErrorForNewValue } = useValidation({ - props: sharedPropsWithDefaults, - value, - timezone, - 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]; - - const context: FieldChangeHandlerContext = { - ...rawContext, - validationError: getValidationErrorForNewValue(newDateRange), - }; - - handleValueChange(newDateRange, context); - }; - }; - - const handleStartDateChange = useEventCallback(buildChangeHandler(0)); - const handleEndDateChange = useEventCallback(buildChangeHandler(1)); - - const selectedSectionsResponse = useMultiInputFieldSelectedSections({ - selectedSections, - onSelectedSectionsChange, - unstableStartFieldRef, - unstableEndFieldRef, - }); - - const startFieldProps = { - error: !!validationError[0], - ...startTextFieldProps, - ...selectedSectionsResponse.start, - disabled, - readOnly, - format, - formatDensity, - shouldRespectLeadingZeros, - timezone, - value: valueProp === undefined ? undefined : valueProp[0], - defaultValue: defaultValue === undefined ? undefined : defaultValue[0], - onChange: handleStartDateChange, - enableAccessibleFieldDOMStructure, - autoFocus, // Do not add on end field. - }; - - const endFieldProps = { - error: !!validationError[1], - ...endTextFieldProps, - ...selectedSectionsResponse.end, - format, - formatDensity, - shouldRespectLeadingZeros, - disabled, - readOnly, - timezone, - value: valueProp === undefined ? undefined : valueProp[1], - defaultValue: defaultValue === undefined ? undefined : defaultValue[1], - onChange: handleEndDateChange, - enableAccessibleFieldDOMStructure, - }; - - const startDateResponse = useTimeField< - TEnableAccessibleFieldDOMStructure, - typeof startFieldProps - >(startFieldProps) as UseFieldResponse; - - const endDateResponse = useTimeField( - endFieldProps, - ) as UseFieldResponse; - - return { - startDate: startDateResponse, - endDate: endDateResponse, - }; -}; 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 dddac7c0a86bc..989dc2d7e49af 100644 --- a/packages/x-date-pickers-pro/src/internals/models/dateTimeRange.ts +++ b/packages/x-date-pickers-pro/src/internals/models/dateTimeRange.ts @@ -1,28 +1,4 @@ -import { MakeOptional } from '@mui/x-internals/types'; -import { - UseFieldInternalProps, - DateOrTimeViewWithMeridiem, - AmPmProps, - PickerRangeValue, -} from '@mui/x-date-pickers/internals'; -import { DateTimeRangeValidationError, RangeFieldSeparatorProps } from '../../models'; -import { ExportedValidateDateTimeRangeProps } from '../../validation/validateDateTimeRange'; - -export interface UseDateTimeRangeFieldProps - extends MakeOptional< - Omit< - UseFieldInternalProps< - PickerRangeValue, - TEnableAccessibleFieldDOMStructure, - DateTimeRangeValidationError - >, - 'unstableFieldRef' - >, - 'format' - >, - RangeFieldSeparatorProps, - ExportedValidateDateTimeRangeProps, - AmPmProps {} +import { DateOrTimeViewWithMeridiem } from '@mui/x-date-pickers/internals'; export type DateTimeRangePickerView = Exclude; diff --git a/packages/x-date-pickers-pro/src/internals/models/index.ts b/packages/x-date-pickers-pro/src/internals/models/index.ts index 58cda92f0c10d..e53e96818e04a 100644 --- a/packages/x-date-pickers-pro/src/internals/models/index.ts +++ b/packages/x-date-pickers-pro/src/internals/models/index.ts @@ -1,4 +1,3 @@ export * from './dateRange'; export * from './dateTimeRange'; -export * from './timeRange'; export * from './rangePickerProps'; diff --git a/packages/x-date-pickers-pro/src/internals/models/managers.ts b/packages/x-date-pickers-pro/src/internals/models/managers.ts new file mode 100644 index 0000000000000..74ac8a47c5350 --- /dev/null +++ b/packages/x-date-pickers-pro/src/internals/models/managers.ts @@ -0,0 +1,4 @@ +import { PickerRangeValue } from '@mui/x-date-pickers/internals'; +import { PickerManager } from '@mui/x-date-pickers/models'; + +export type PickerAnyRangeManager = PickerManager; diff --git a/packages/x-date-pickers-pro/src/internals/models/timeRange.ts b/packages/x-date-pickers-pro/src/internals/models/timeRange.ts deleted file mode 100644 index 171ad2c8c7cdb..0000000000000 --- a/packages/x-date-pickers-pro/src/internals/models/timeRange.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { MakeOptional } from '@mui/x-internals/types'; -import { UseFieldInternalProps, AmPmProps, PickerRangeValue } from '@mui/x-date-pickers/internals'; -import { TimeRangeValidationError, RangeFieldSeparatorProps } from '../../models'; -import type { ExportedValidateTimeRangeProps } from '../../validation/validateTimeRange'; - -export interface UseTimeRangeFieldProps - extends MakeOptional< - Omit< - UseFieldInternalProps< - PickerRangeValue, - TEnableAccessibleFieldDOMStructure, - TimeRangeValidationError - >, - 'unstableFieldRef' - >, - 'format' - >, - RangeFieldSeparatorProps, - ExportedValidateTimeRangeProps, - AmPmProps {} diff --git a/packages/x-date-pickers-pro/src/internals/utils/createMultiInputRangeField/createMultiInputRangeField.tsx b/packages/x-date-pickers-pro/src/internals/utils/createMultiInputRangeField/createMultiInputRangeField.tsx new file mode 100644 index 0000000000000..f25b62d655624 --- /dev/null +++ b/packages/x-date-pickers-pro/src/internals/utils/createMultiInputRangeField/createMultiInputRangeField.tsx @@ -0,0 +1,139 @@ +'use client'; +import * as React from 'react'; +import clsx from 'clsx'; +import Stack, { StackProps } from '@mui/material/Stack'; +import MuiTextField from '@mui/material/TextField'; +import Typography from '@mui/material/Typography'; +import { styled, useThemeProps } from '@mui/material/styles'; +import composeClasses from '@mui/utils/composeClasses'; +import useSlotProps from '@mui/utils/useSlotProps'; +import { cleanFieldResponse, useFieldOwnerState } from '@mui/x-date-pickers/internals'; +import { useSplitFieldProps } from '@mui/x-date-pickers/hooks'; +import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; +import { + CreateMultiInputRangeFieldParameters, + CreateMultiInputRangeFieldReturnValue, + MultiInputRangeFieldProps, +} from './createMultiInputRangeField.types'; +import { useMultiInputRangeField } from '../../../hooks/useMultiInputRangeField'; +import { PickerAnyRangeManager } from '../../models/managers'; + +export function createMultiInputRangeField({ + useManager, + name, + getUtilityClass, +}: CreateMultiInputRangeFieldParameters): CreateMultiInputRangeFieldReturnValue { + const useUtilityClasses = (classes: MultiInputRangeFieldProps['classes']) => { + const slots = { + root: ['root'], + separator: ['separator'], + }; + + return composeClasses(slots, getUtilityClass, classes); + }; + + const MultiInputRangeFieldRoot = styled( + React.forwardRef((props: StackProps, ref: React.Ref) => ( + + )), + { + name, + slot: 'Root', + overridesResolver: (props, styles) => styles.root, + }, + )({}); + + const MultiInputRangeFieldSeparator = styled(Typography, { + name, + slot: 'Separator', + overridesResolver: (props, styles) => styles.separator, + })({ + lineHeight: '1.4375em', // 23px + }); + + const MultiInputRangeField = React.forwardRef(function MultiInputRangeField( + props: MultiInputRangeFieldProps, + ref: React.Ref, + ) { + const themeProps = useThemeProps({ + props, + // eslint-disable-next-line material-ui/mui-name-matches-component-name + name, + }); + + const manager = useManager({ + enableAccessibleFieldDOMStructure: props.enableAccessibleFieldDOMStructure, + dateSeparator: props.dateSeparator, + }); + const { internalProps, forwardedProps } = useSplitFieldProps(themeProps, manager.valueType); + + const { + slots, + slotProps, + className, + classes: classesProp, + ...otherForwardedProps + } = forwardedProps; + + const classes = useUtilityClasses(classesProp); + const ownerState = useFieldOwnerState(internalProps as any); + + const Root = slots?.root ?? MultiInputRangeFieldRoot; + const rootProps = useSlotProps({ + elementType: Root, + externalSlotProps: slotProps?.root, + externalForwardedProps: otherForwardedProps, + additionalProps: { ref }, + ownerState, + className: clsx(className, classes.root), + }); + + const startTextFieldProps = useSlotProps({ + elementType: PickersTextField, + externalSlotProps: slotProps?.textField, + ownerState: { ...ownerState, position: 'start' }, + }); + const endTextFieldProps = useSlotProps({ + elementType: PickersTextField, + externalSlotProps: slotProps?.textField, + ownerState: { ...ownerState, position: 'end' }, + }); + + const { startDate, endDate, enableAccessibleFieldDOMStructure } = useMultiInputRangeField({ + manager, + internalProps, + startForwardedProps: startTextFieldProps, + endForwardedProps: endTextFieldProps, + }); + + const Separator = slots?.separator ?? MultiInputRangeFieldSeparator; + const separatorProps = useSlotProps({ + elementType: Separator, + externalSlotProps: slotProps?.separator, + additionalProps: { + children: internalProps.dateSeparator ?? '–', + }, + ownerState, + className: classes.separator, + }); + + const { textFieldProps: startDateProps } = cleanFieldResponse(startDate); + const { textFieldProps: endDateProps } = cleanFieldResponse(endDate); + + const TextField = + slots?.textField ?? + (enableAccessibleFieldDOMStructure === false ? MuiTextField : PickersTextField); + + return ( + + + + + + ); + } as any) as any; + + MultiInputRangeField.fieldType = 'multi-input'; + + return MultiInputRangeField; +} diff --git a/packages/x-date-pickers-pro/src/internals/utils/createMultiInputRangeField/createMultiInputRangeField.types.ts b/packages/x-date-pickers-pro/src/internals/utils/createMultiInputRangeField/createMultiInputRangeField.types.ts new file mode 100644 index 0000000000000..fbffbb8f9328a --- /dev/null +++ b/packages/x-date-pickers-pro/src/internals/utils/createMultiInputRangeField/createMultiInputRangeField.types.ts @@ -0,0 +1,96 @@ +import type { TypographyProps } from '@mui/material/Typography'; +import type { StackProps } from '@mui/material/Stack'; +import type { TextFieldProps } from '@mui/material/TextField'; +import { SlotComponentPropsFromProps } from '@mui/x-internals/types'; +import { PickersTextFieldProps } from '@mui/x-date-pickers/PickersTextField'; +import { FieldOwnerState } from '@mui/x-date-pickers/models'; +import { + PickerManagerEnableAccessibleFieldDOMStructure, + PickerManagerFieldInternalProps, +} from '@mui/x-date-pickers/internals'; +import { + FieldType, + MultiInputFieldRefs, + RangeFieldSeparatorProps, + RangePosition, +} from '../../../models'; +import { PickerAnyRangeManager } from '../../models/managers'; + +export type MultiInputRangeFieldProps = + MultiInputFieldRefs & + RangeFieldSeparatorProps & + Omit, 'unstableFieldRef' | 'clearable' | 'onClear'> & + Omit> & { + /** + * If `true`, the field is focused during the first mount. + * @default false + */ + autoFocus?: boolean; + className?: string; + /** + * Override or extend the styles applied to the component. + */ + classes?: Partial; + /** + * Overridable component slots. + * @default {} + */ + slots?: MultiInputRangeFieldSlots; + /** + * The props used for each component slot. + * @default {} + */ + slotProps?: MultiInputRangeFieldSlotProps; + }; + +export interface MultiInputRangeFieldSlots { + /** + * Element rendered at the root. + * @default MultiInputRangeFieldRoot + */ + root?: React.ElementType; + /** + * Form control with an input to render a date. + * It is rendered twice: once for the start date and once for the end date. + * @default , or from '@mui/material' if `enableAccessibleFieldDOMStructure` is `false`. + */ + textField?: React.ElementType; + /** + * Element rendered between the two inputs. + * @default MultiInputRangeFieldSeparator + */ + separator?: React.ElementType; +} + +export interface MultiInputRangeFieldSlotProps { + root?: SlotComponentPropsFromProps; + textField?: SlotComponentPropsFromProps< + PickersTextFieldProps | TextFieldProps, + {}, + FieldOwnerState & { + position: RangePosition; + } + >; + separator?: SlotComponentPropsFromProps; +} + +export interface MultiInputRangeFieldClasses { + /** Styles applied to the root element. */ + root: string; + /** Styles applied to the separator element. */ + separator: string; +} + +export interface CreateMultiInputRangeFieldParameters { + name: string; + getUtilityClass: (slot: string) => string; + useManager: ( + params: RangeFieldSeparatorProps & { + enableAccessibleFieldDOMStructure: PickerManagerEnableAccessibleFieldDOMStructure; + }, + ) => TManager; +} + +export type CreateMultiInputRangeFieldReturnValue = (( + props: MultiInputRangeFieldProps & React.RefAttributes, +) => React.JSX.Element) & { fieldType?: FieldType }; diff --git a/packages/x-date-pickers-pro/src/internals/utils/createMultiInputRangeField/index.ts b/packages/x-date-pickers-pro/src/internals/utils/createMultiInputRangeField/index.ts new file mode 100644 index 0000000000000..0fde2f8501e65 --- /dev/null +++ b/packages/x-date-pickers-pro/src/internals/utils/createMultiInputRangeField/index.ts @@ -0,0 +1,9 @@ +export { createMultiInputRangeField } from './createMultiInputRangeField'; +export type { + MultiInputRangeFieldProps, + MultiInputRangeFieldSlots, + MultiInputRangeFieldSlotProps, + MultiInputRangeFieldClasses, +} from './createMultiInputRangeField.types'; + +export { useMultiInputRangeField as unstable_useMultiInputRangeField } from '../../../hooks/useMultiInputRangeField/useMultiInputRangeField'; diff --git a/packages/x-date-pickers-pro/src/managers/index.ts b/packages/x-date-pickers-pro/src/managers/index.ts index 07a939c8a1be5..b5f8aa4f35d27 100644 --- a/packages/x-date-pickers-pro/src/managers/index.ts +++ b/packages/x-date-pickers-pro/src/managers/index.ts @@ -2,16 +2,19 @@ export { useDateRangeManager } from './useDateRangeManager'; export type { UseDateRangeManagerReturnValue, UseDateRangeManagerParameters, + DateRangeManagerFieldInternalProps, } from './useDateRangeManager'; export { useTimeRangeManager } from './useTimeRangeManager'; export type { UseTimeRangeManagerReturnValue, UseTimeRangeManagerParameters, + TimeRangeManagerFieldInternalProps, } from './useTimeRangeManager'; export { useDateTimeRangeManager } from './useDateTimeRangeManager'; export type { UseDateTimeRangeManagerReturnValue, UseDateTimeRangeManagerParameters, + DateTimeRangeManagerFieldInternalProps, } from './useDateTimeRangeManager'; diff --git a/packages/x-date-pickers-pro/src/managers/useDateRangeManager.ts b/packages/x-date-pickers-pro/src/managers/useDateRangeManager.ts index 4e08aeaee8301..02a5dc432e4ae 100644 --- a/packages/x-date-pickers-pro/src/managers/useDateRangeManager.ts +++ b/packages/x-date-pickers-pro/src/managers/useDateRangeManager.ts @@ -55,8 +55,9 @@ export type UseDateRangeManagerReturnValue >; -interface DateRangeManagerFieldInternalProps - extends MakeOptional< +export interface DateRangeManagerFieldInternalProps< + TEnableAccessibleFieldDOMStructure extends boolean, +> extends MakeOptional< UseFieldInternalProps< PickerRangeValue, TEnableAccessibleFieldDOMStructure, diff --git a/packages/x-date-pickers-pro/src/managers/useDateTimeRangeManager.ts b/packages/x-date-pickers-pro/src/managers/useDateTimeRangeManager.ts index dd99267e4f869..b1beb5e12b903 100644 --- a/packages/x-date-pickers-pro/src/managers/useDateTimeRangeManager.ts +++ b/packages/x-date-pickers-pro/src/managers/useDateTimeRangeManager.ts @@ -57,8 +57,9 @@ export type UseDateTimeRangeManagerReturnValue >; -interface DateTimeRangeManagerFieldInternalProps - extends MakeOptional< +export interface DateTimeRangeManagerFieldInternalProps< + TEnableAccessibleFieldDOMStructure extends boolean, +> extends MakeOptional< UseFieldInternalProps< PickerRangeValue, TEnableAccessibleFieldDOMStructure, diff --git a/packages/x-date-pickers-pro/src/managers/useTimeRangeManager.ts b/packages/x-date-pickers-pro/src/managers/useTimeRangeManager.ts index 4563793170fec..72a582f2f01c4 100644 --- a/packages/x-date-pickers-pro/src/managers/useTimeRangeManager.ts +++ b/packages/x-date-pickers-pro/src/managers/useTimeRangeManager.ts @@ -56,8 +56,9 @@ export type UseTimeRangeManagerReturnValue >; -interface TimeRangeManagerFieldInternalProps - extends MakeOptional< +export interface TimeRangeManagerFieldInternalProps< + TEnableAccessibleFieldDOMStructure extends boolean, +> extends MakeOptional< UseFieldInternalProps< PickerRangeValue, TEnableAccessibleFieldDOMStructure, diff --git a/packages/x-date-pickers-pro/src/models/dateRange.ts b/packages/x-date-pickers-pro/src/models/dateRange.ts deleted file mode 100644 index 0e29e30990cc1..0000000000000 --- a/packages/x-date-pickers-pro/src/models/dateRange.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { MakeOptional } from '@mui/x-internals/types'; -import { PickerRangeValue, UseFieldInternalProps } from '@mui/x-date-pickers/internals'; -import { RangeFieldSeparatorProps } from './fields'; -import { DateRangeValidationError } from './validation'; -import type { ExportedValidateDateRangeProps } from '../validation/validateDateRange'; - -export interface UseDateRangeFieldProps - extends MakeOptional< - Omit< - UseFieldInternalProps< - PickerRangeValue, - TEnableAccessibleFieldDOMStructure, - DateRangeValidationError - >, - 'unstableFieldRef' - >, - 'format' - >, - RangeFieldSeparatorProps, - ExportedValidateDateRangeProps {} diff --git a/packages/x-date-pickers-pro/src/models/index.ts b/packages/x-date-pickers-pro/src/models/index.ts index f3b7d852521cc..13f5f47a95c70 100644 --- a/packages/x-date-pickers-pro/src/models/index.ts +++ b/packages/x-date-pickers-pro/src/models/index.ts @@ -1,7 +1,5 @@ -export * from './dateRange'; 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/multiInputRangeFieldClasses.ts b/packages/x-date-pickers-pro/src/models/multiInputRangeFieldClasses.ts deleted file mode 100644 index 6fd1999a0bd74..0000000000000 --- a/packages/x-date-pickers-pro/src/models/multiInputRangeFieldClasses.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface MultiInputRangeFieldClasses { - /** Styles applied to the root element. */ - root: string; - /** Styles applied to the separator element. */ - separator: string; -} - -export type MultiInputRangeFieldClassKey = keyof MultiInputRangeFieldClasses; diff --git a/packages/x-date-pickers-pro/src/themeAugmentation/overrides.d.ts b/packages/x-date-pickers-pro/src/themeAugmentation/overrides.d.ts index 8b53b859f7c33..5c894cf2c3aab 100644 --- a/packages/x-date-pickers-pro/src/themeAugmentation/overrides.d.ts +++ b/packages/x-date-pickers-pro/src/themeAugmentation/overrides.d.ts @@ -1,11 +1,13 @@ import { DateRangePickerDayClassKey } from '../DateRangePickerDay'; import { DateRangeCalendarClassKey } from '../DateRangeCalendar'; import { DateRangePickerToolbarClassKey } from '../DateRangePicker'; -import { MultiInputRangeFieldClassKey } from '../models'; import { DateTimeRangePickerTabsClassKey, DateTimeRangePickerToolbarClassKey, } from '../DateTimeRangePicker'; +import { MultiInputDateRangeFieldClassKey } from '../MultiInputDateRangeField'; +import { MultiInputDateTimeRangeFieldClassKey } from '../MultiInputDateTimeRangeField'; +import { MultiInputTimeRangeFieldClassKey } from '../MultiInputTimeRangeField'; // prettier-ignore export interface PickersProComponentNameToClassKey { @@ -17,9 +19,9 @@ export interface PickersProComponentNameToClassKey { MuiDateTimeRangePickerToolbar: DateTimeRangePickerToolbarClassKey; // Multi input range fields - MuiMultiInputDateRangeField: MultiInputRangeFieldClassKey; - MuiMultiInputDateTimeRangeField: MultiInputRangeFieldClassKey; - MuiMultiInputTimeRangeField: MultiInputRangeFieldClassKey; + MuiMultiInputDateRangeField: MultiInputDateRangeFieldClassKey; + MuiMultiInputDateTimeRangeField: MultiInputDateTimeRangeFieldClassKey; + MuiMultiInputTimeRangeField: MultiInputTimeRangeFieldClassKey; } declare module '@mui/material/styles' { diff --git a/packages/x-date-pickers-pro/src/themeAugmentation/props.d.ts b/packages/x-date-pickers-pro/src/themeAugmentation/props.d.ts index c2254363c7acd..51ad2f83c479b 100644 --- a/packages/x-date-pickers-pro/src/themeAugmentation/props.d.ts +++ b/packages/x-date-pickers-pro/src/themeAugmentation/props.d.ts @@ -1,14 +1,14 @@ import { DateRangePickerDayProps } from '../DateRangePickerDay'; -import { MultiInputDateRangeFieldProps } from '../MultiInputDateRangeField/MultiInputDateRangeField.types'; -import { SingleInputDateRangeFieldProps } from '../SingleInputDateRangeField/SingleInputDateRangeField.types'; import { DateRangeCalendarProps } from '../DateRangeCalendar'; import { DateRangePickerProps } from '../DateRangePicker'; import { ExportedDateRangePickerToolbarProps } from '../DateRangePicker/DateRangePickerToolbar'; import { DesktopDateRangePickerProps } from '../DesktopDateRangePicker'; import { MobileDateRangePickerProps } from '../MobileDateRangePicker'; import { StaticDateRangePickerProps } from '../StaticDateRangePicker'; +import { MultiInputDateRangeFieldProps } from '../MultiInputDateRangeField'; import { MultiInputDateTimeRangeFieldProps } from '../MultiInputDateTimeRangeField'; import { MultiInputTimeRangeFieldProps } from '../MultiInputTimeRangeField'; +import { SingleInputDateRangeFieldProps } from '../SingleInputDateRangeField'; import { SingleInputDateTimeRangeFieldProps } from '../SingleInputDateTimeRangeField'; import { SingleInputTimeRangeFieldProps } from '../SingleInputTimeRangeField'; import { DateTimeRangePickerProps } from '../DateTimeRangePicker'; diff --git a/packages/x-date-pickers/src/hooks/useSplitFieldProps.ts b/packages/x-date-pickers/src/hooks/useSplitFieldProps.ts index 7e1ca2953b58d..e256af657f3bc 100644 --- a/packages/x-date-pickers/src/hooks/useSplitFieldProps.ts +++ b/packages/x-date-pickers/src/hooks/useSplitFieldProps.ts @@ -20,10 +20,13 @@ const SHARED_FIELD_INTERNAL_PROP_NAMES = [ 'selectedSections', 'onSelectedSectionsChange', 'unstableFieldRef', + 'unstableStartFieldRef', + 'unstableEndFieldRef', 'enableAccessibleFieldDOMStructure', 'disabled', 'readOnly', 'dateSeparator', + 'autoFocus', ] as const; type InternalPropNames = @@ -37,7 +40,7 @@ type InternalPropNames = * - `internalProps` which are used by the various hooks called by the field component. * - `forwardedProps` which are passed to the underlying component. * Note that some forwarded props might be used by the hooks as well. - * For instance, hooks like `useDateField` need props like `autoFocus` to know how to behave. + * For instance, hooks like `useDateField` need props like `onKeyDown` to merge the default event handler and the one provided by the application. * @template TProps, TValueType * @param {TProps} props The props received by the field component. * @param {TValueType} valueType The type of the field value ('date', 'time', or 'date-time'). @@ -51,7 +54,7 @@ export const useSplitFieldProps = < ) => { return React.useMemo(() => { const forwardedProps = { ...props } as Omit>; - const internalProps = {} as Pick>; + const internalProps = {} as ExtractInternalProps; const extractProp = (propName: string) => { if (forwardedProps.hasOwnProperty(propName)) { @@ -76,3 +79,12 @@ export const useSplitFieldProps = < return { forwardedProps, internalProps }; }, [props, valueType]); }; + +/** + * Extract the internal props from the props received by the field component. + * This makes sure that the internal props not defined in the props are not present in the result. + */ +type ExtractInternalProps< + TValueType extends PickerValueType, + TProps extends { [key in InternalPropNames]?: any }, +> = { [K in keyof TProps]: K extends InternalPropNames ? TProps[K] : never }; diff --git a/packages/x-date-pickers/src/internals/components/PickerFieldUI.tsx b/packages/x-date-pickers/src/internals/components/PickerFieldUI.tsx index 3f78963434412..dd09ac31ff41b 100644 --- a/packages/x-date-pickers/src/internals/components/PickerFieldUI.tsx +++ b/packages/x-date-pickers/src/internals/components/PickerFieldUI.tsx @@ -6,7 +6,7 @@ import MuiIconButton, { IconButtonProps } from '@mui/material/IconButton'; import MuiInputAdornment, { InputAdornmentProps } from '@mui/material/InputAdornment'; import { SvgIconProps } from '@mui/material/SvgIcon'; import useSlotProps from '@mui/utils/useSlotProps'; -import { SlotComponentPropsFromProps } from '@mui/x-internals/types'; +import { MakeOptional, SlotComponentPropsFromProps } from '@mui/x-internals/types'; import { FieldOwnerState } from '../../models'; import { useFieldOwnerState, UseFieldOwnerStateParameters } from '../hooks/useFieldOwnerState'; import { usePickerTranslations } from '../../hooks'; @@ -16,7 +16,10 @@ import type { UseFieldResponse } from '../hooks/useField'; import { PickersTextField, PickersTextFieldProps } from '../../PickersTextField'; export const cleanFieldResponse = < - TFieldResponse extends UseFieldResponse, + TFieldResponse extends MakeOptional< + UseFieldResponse, + 'onClear' | 'clearable' + >, >({ enableAccessibleFieldDOMStructure, ...fieldResponse 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 3f92bef606d7b..20c19b1e83602 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useField.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useField.ts @@ -47,6 +47,7 @@ export const useField = < enableAccessibleFieldDOMStructure = true, disabled = false, readOnly = false, + autoFocus = false, }, forwardedProps: { onKeyDown, error, clearable, onClear }, fieldValueManager, @@ -289,6 +290,7 @@ export const useField = < const commonAdditionalProps: UseFieldCommonAdditionalProps = { disabled, readOnly, + autoFocus, openPickerAriaLabel, }; 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 2b9dbd7d3598c..f9cc1c0856f72 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 @@ -126,7 +126,9 @@ export interface UseFieldInternalProps< } export interface UseFieldCommonAdditionalProps - extends Required, 'disabled' | 'readOnly'>> { + extends Required< + Pick, 'disabled' | 'readOnly' | 'autoFocus'> + > { /** * The aria label to set on the button that opens the picker. */ @@ -166,7 +168,6 @@ interface UseFieldV6AdditionalProps export interface UseFieldV7ForwardedProps { focused?: boolean; - autoFocus?: boolean; sectionListRef?: React.Ref; onBlur?: () => void; onClick?: React.MouseEventHandler; diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useFieldV7TextField.ts b/packages/x-date-pickers/src/internals/hooks/useField/useFieldV7TextField.ts index 0a54c6bef5dc5..806cc8e6cabb4 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useFieldV7TextField.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useFieldV7TextField.ts @@ -16,7 +16,7 @@ import { useUtils } from '../useUtils'; export const useFieldV7TextField: UseFieldTextField = (params) => { const { - internalProps: { disabled, readOnly = false }, + internalProps: { disabled, readOnly = false, autoFocus = false }, forwardedProps: { sectionListRef: inSectionListRef, onBlur, @@ -25,7 +25,6 @@ export const useFieldV7TextField: UseFieldTextField = (params) => { onInput, onPaste, focused: focusedProp, - autoFocus = false, }, fieldValueManager, applyCharacterEditing, diff --git a/packages/x-date-pickers/src/internals/index.ts b/packages/x-date-pickers/src/internals/index.ts index 85394bf31fdd6..6d138c66b4d30 100644 --- a/packages/x-date-pickers/src/internals/index.ts +++ b/packages/x-date-pickers/src/internals/index.ts @@ -114,6 +114,12 @@ export type { ExportedUseViewsOptions, UseViewsOptions } from './hooks/useViews' export { useViews } from './hooks/useViews'; export { usePreviousMonthDisabled, useNextMonthDisabled } from './hooks/date-helpers-hooks'; +export type { + PickerAnyManager, + PickerManagerFieldInternalProps, + PickerManagerEnableAccessibleFieldDOMStructure, + PickerManagerError, +} from './models/manager'; export type { RangePosition } from './models/pickers'; export type { BaseSingleInputFieldProps, FieldRangeSection } from './models/fields'; export type { BasePickerProps, BasePickerInputProps } from './models/props/basePickerProps'; diff --git a/packages/x-date-pickers/src/internals/models/manager.ts b/packages/x-date-pickers/src/internals/models/manager.ts index 135e3177648f5..13842fa8468b1 100644 --- a/packages/x-date-pickers/src/internals/models/manager.ts +++ b/packages/x-date-pickers/src/internals/models/manager.ts @@ -30,3 +30,6 @@ export type PickerManagerFieldInternalProps = export type PickerManagerFieldInternalPropsWithDefaults = PickerManagerProperties['fieldInternalPropsWithDefaults']; + +export type PickerManagerEnableAccessibleFieldDOMStructure = + PickerManagerProperties['enableAccessibleFieldDOMStructure']; diff --git a/packages/x-date-pickers/src/managers/index.ts b/packages/x-date-pickers/src/managers/index.ts index 085026d5225fa..d8f86861b7968 100644 --- a/packages/x-date-pickers/src/managers/index.ts +++ b/packages/x-date-pickers/src/managers/index.ts @@ -1,11 +1,20 @@ export { useDateManager } from './useDateManager'; -export type { UseDateManagerReturnValue, UseDateManagerParameters } from './useDateManager'; +export type { + UseDateManagerReturnValue, + UseDateManagerParameters, + DateManagerFieldInternalProps, +} from './useDateManager'; export { useTimeManager } from './useTimeManager'; -export type { UseTimeManagerReturnValue, UseTimeManagerParameters } from './useTimeManager'; +export type { + UseTimeManagerReturnValue, + UseTimeManagerParameters, + TimeManagerFieldInternalProps, +} from './useTimeManager'; export { useDateTimeManager } from './useDateTimeManager'; export type { UseDateTimeManagerReturnValue, UseDateTimeManagerParameters, + DateTimeManagerFieldInternalProps, } from './useDateTimeManager'; diff --git a/packages/x-date-pickers/src/managers/useDateManager.ts b/packages/x-date-pickers/src/managers/useDateManager.ts index b99686fbd4d85..415187e9dac8c 100644 --- a/packages/x-date-pickers/src/managers/useDateManager.ts +++ b/packages/x-date-pickers/src/managers/useDateManager.ts @@ -74,7 +74,7 @@ export type UseDateManagerReturnValue >; -interface DateManagerFieldInternalProps +export interface DateManagerFieldInternalProps extends MakeOptional< UseFieldInternalProps, 'format' diff --git a/packages/x-date-pickers/src/managers/useDateTimeManager.ts b/packages/x-date-pickers/src/managers/useDateTimeManager.ts index dc8b37c307152..282ea55e2dad0 100644 --- a/packages/x-date-pickers/src/managers/useDateTimeManager.ts +++ b/packages/x-date-pickers/src/managers/useDateTimeManager.ts @@ -92,8 +92,9 @@ export type UseDateTimeManagerReturnValue >; -interface DateTimeManagerFieldInternalProps - extends MakeOptional< +export interface DateTimeManagerFieldInternalProps< + TEnableAccessibleFieldDOMStructure extends boolean, +> extends MakeOptional< UseFieldInternalProps< PickerValue, TEnableAccessibleFieldDOMStructure, diff --git a/packages/x-date-pickers/src/managers/useTimeManager.ts b/packages/x-date-pickers/src/managers/useTimeManager.ts index 5ce9df999af2c..10acbeb24d153 100644 --- a/packages/x-date-pickers/src/managers/useTimeManager.ts +++ b/packages/x-date-pickers/src/managers/useTimeManager.ts @@ -74,7 +74,7 @@ export type UseTimeManagerReturnValue >; -interface TimeManagerFieldInternalProps +export interface TimeManagerFieldInternalProps extends MakeOptional< UseFieldInternalProps, 'format' diff --git a/scripts/x-date-pickers-pro.exports.json b/scripts/x-date-pickers-pro.exports.json index 7ac4157713712..9b2c60de65c17 100644 --- a/scripts/x-date-pickers-pro.exports.json +++ b/scripts/x-date-pickers-pro.exports.json @@ -32,6 +32,7 @@ { "name": "DateCalendarSlots", "kind": "Interface" }, { "name": "DateField", "kind": "Variable" }, { "name": "DateFieldProps", "kind": "TypeAlias" }, + { "name": "DateManagerFieldInternalProps", "kind": "Interface" }, { "name": "DateOrTimeView", "kind": "TypeAlias" }, { "name": "DatePicker", "kind": "Variable" }, { "name": "DatePickerFieldProps", "kind": "TypeAlias" }, @@ -52,6 +53,7 @@ { "name": "DateRangeCalendarSlotProps", "kind": "Interface" }, { "name": "DateRangeCalendarSlots", "kind": "Interface" }, { "name": "DateRangeIcon", "kind": "Variable" }, + { "name": "DateRangeManagerFieldInternalProps", "kind": "Interface" }, { "name": "DateRangePicker", "kind": "Variable" }, { "name": "DateRangePickerDay", "kind": "Variable" }, { "name": "dateRangePickerDayClasses", "kind": "Variable" }, @@ -71,6 +73,7 @@ { "name": "DateRangeViewRendererProps", "kind": "Interface" }, { "name": "DateTimeField", "kind": "Variable" }, { "name": "DateTimeFieldProps", "kind": "TypeAlias" }, + { "name": "DateTimeManagerFieldInternalProps", "kind": "Interface" }, { "name": "DateTimePicker", "kind": "Variable" }, { "name": "DateTimePickerFieldProps", "kind": "TypeAlias" }, { "name": "DateTimePickerProps", "kind": "Interface" }, @@ -86,6 +89,7 @@ { "name": "DateTimePickerToolbarClasses", "kind": "Interface" }, { "name": "DateTimePickerToolbarClassKey", "kind": "TypeAlias" }, { "name": "DateTimePickerToolbarProps", "kind": "Interface" }, + { "name": "DateTimeRangeManagerFieldInternalProps", "kind": "Interface" }, { "name": "DateTimeRangePicker", "kind": "Variable" }, { "name": "DateTimeRangePickerFieldProps", "kind": "TypeAlias" }, { "name": "DateTimeRangePickerProps", "kind": "Interface" }, @@ -221,18 +225,28 @@ { "name": "MuiPickersAdapterContext", "kind": "Variable" }, { "name": "MultiInputDateRangeField", "kind": "Variable" }, { "name": "multiInputDateRangeFieldClasses", "kind": "Variable" }, + { "name": "MultiInputDateRangeFieldClasses", "kind": "Interface" }, + { "name": "MultiInputDateRangeFieldClassKey", "kind": "TypeAlias" }, { "name": "MultiInputDateRangeFieldProps", "kind": "Interface" }, + { "name": "MultiInputDateRangeFieldSlotProps", "kind": "Interface" }, + { "name": "MultiInputDateRangeFieldSlots", "kind": "Interface" }, { "name": "MultiInputDateTimeRangeField", "kind": "Variable" }, { "name": "multiInputDateTimeRangeFieldClasses", "kind": "Variable" }, + { "name": "MultiInputDateTimeRangeFieldClasses", "kind": "Interface" }, + { "name": "MultiInputDateTimeRangeFieldClassKey", "kind": "TypeAlias" }, { "name": "MultiInputDateTimeRangeFieldProps", "kind": "Interface" }, + { "name": "MultiInputDateTimeRangeFieldSlotProps", "kind": "Interface" }, + { "name": "MultiInputDateTimeRangeFieldSlots", "kind": "Interface" }, { "name": "MultiInputFieldRefs", "kind": "Interface" }, { "name": "MultiInputFieldSlotRootProps", "kind": "Interface" }, { "name": "MultiInputFieldSlotTextFieldProps", "kind": "Interface" }, - { "name": "MultiInputRangeFieldClasses", "kind": "Interface" }, - { "name": "MultiInputRangeFieldClassKey", "kind": "TypeAlias" }, { "name": "MultiInputTimeRangeField", "kind": "Variable" }, { "name": "multiInputTimeRangeFieldClasses", "kind": "Variable" }, + { "name": "MultiInputTimeRangeFieldClasses", "kind": "Interface" }, + { "name": "MultiInputTimeRangeFieldClassKey", "kind": "TypeAlias" }, { "name": "MultiInputTimeRangeFieldProps", "kind": "Interface" }, + { "name": "MultiInputTimeRangeFieldSlotProps", "kind": "Interface" }, + { "name": "MultiInputTimeRangeFieldSlots", "kind": "Interface" }, { "name": "MultiSectionDigitalClock", "kind": "Variable" }, { "name": "multiSectionDigitalClockClasses", "kind": "Variable" }, { "name": "MultiSectionDigitalClockClasses", "kind": "Interface" }, @@ -371,6 +385,7 @@ { "name": "TimeField", "kind": "Variable" }, { "name": "TimeFieldProps", "kind": "TypeAlias" }, { "name": "TimeIcon", "kind": "Variable" }, + { "name": "TimeManagerFieldInternalProps", "kind": "Interface" }, { "name": "TimePicker", "kind": "Variable" }, { "name": "TimePickerFieldProps", "kind": "TypeAlias" }, { "name": "TimePickerProps", "kind": "Interface" }, @@ -381,6 +396,7 @@ { "name": "TimePickerToolbarClasses", "kind": "Interface" }, { "name": "TimePickerToolbarClassKey", "kind": "TypeAlias" }, { "name": "TimePickerToolbarProps", "kind": "Interface" }, + { "name": "TimeRangeManagerFieldInternalProps", "kind": "Interface" }, { "name": "TimeRangeValidationError", "kind": "TypeAlias" }, { "name": "TimeStepOptions", "kind": "Interface" }, { "name": "TimeValidationError", "kind": "TypeAlias" }, @@ -394,9 +410,7 @@ { "name": "Unstable_PickersSectionListSectionSeparator", "kind": "Variable" }, { "name": "unstable_useDateField", "kind": "Variable" }, { "name": "unstable_useDateTimeField", "kind": "Variable" }, - { "name": "unstable_useMultiInputDateRangeField", "kind": "Variable" }, - { "name": "unstable_useMultiInputDateTimeRangeField", "kind": "Variable" }, - { "name": "unstable_useMultiInputTimeRangeField", "kind": "Variable" }, + { "name": "unstable_useMultiInputRangeField", "kind": "Function" }, { "name": "unstable_useSingleInputDateRangeField", "kind": "Variable" }, { "name": "unstable_useSingleInputDateTimeRangeField", "kind": "Variable" }, { "name": "unstable_useSingleInputTimeRangeField", "kind": "Variable" }, @@ -409,7 +423,6 @@ { "name": "useDateManager", "kind": "Function" }, { "name": "UseDateManagerParameters", "kind": "Interface" }, { "name": "UseDateManagerReturnValue", "kind": "TypeAlias" }, - { "name": "UseDateRangeFieldProps", "kind": "Interface" }, { "name": "useDateRangeManager", "kind": "Function" }, { "name": "UseDateRangeManagerParameters", "kind": "Interface" }, { "name": "UseDateRangeManagerReturnValue", "kind": "TypeAlias" }, @@ -421,12 +434,6 @@ { "name": "UseDateTimeRangeManagerParameters", "kind": "Interface" }, { "name": "UseDateTimeRangeManagerReturnValue", "kind": "TypeAlias" }, { "name": "useIsValidValue", "kind": "Function" }, - { "name": "UseMultiInputDateRangeFieldComponentProps", "kind": "TypeAlias" }, - { "name": "UseMultiInputDateRangeFieldProps", "kind": "Interface" }, - { "name": "UseMultiInputDateTimeRangeFieldComponentProps", "kind": "TypeAlias" }, - { "name": "UseMultiInputDateTimeRangeFieldProps", "kind": "Interface" }, - { "name": "UseMultiInputTimeRangeFieldComponentProps", "kind": "TypeAlias" }, - { "name": "UseMultiInputTimeRangeFieldProps", "kind": "Interface" }, { "name": "useParsedFormat", "kind": "Variable" }, { "name": "usePickerActionsContext", "kind": "Variable" }, { "name": "usePickerContext", "kind": "Variable" }, diff --git a/scripts/x-date-pickers.exports.json b/scripts/x-date-pickers.exports.json index f39968054d183..08c260e8a3783 100644 --- a/scripts/x-date-pickers.exports.json +++ b/scripts/x-date-pickers.exports.json @@ -31,6 +31,7 @@ { "name": "DateCalendarSlots", "kind": "Interface" }, { "name": "DateField", "kind": "Variable" }, { "name": "DateFieldProps", "kind": "TypeAlias" }, + { "name": "DateManagerFieldInternalProps", "kind": "Interface" }, { "name": "DateOrTimeView", "kind": "TypeAlias" }, { "name": "DatePicker", "kind": "Variable" }, { "name": "DatePickerFieldProps", "kind": "TypeAlias" }, @@ -45,6 +46,7 @@ { "name": "DateRangeIcon", "kind": "Variable" }, { "name": "DateTimeField", "kind": "Variable" }, { "name": "DateTimeFieldProps", "kind": "TypeAlias" }, + { "name": "DateTimeManagerFieldInternalProps", "kind": "Interface" }, { "name": "DateTimePicker", "kind": "Variable" }, { "name": "DateTimePickerFieldProps", "kind": "TypeAlias" }, { "name": "DateTimePickerProps", "kind": "Interface" }, @@ -271,6 +273,7 @@ { "name": "TimeField", "kind": "Variable" }, { "name": "TimeFieldProps", "kind": "TypeAlias" }, { "name": "TimeIcon", "kind": "Variable" }, + { "name": "TimeManagerFieldInternalProps", "kind": "Interface" }, { "name": "TimePicker", "kind": "Variable" }, { "name": "TimePickerFieldProps", "kind": "TypeAlias" }, { "name": "TimePickerProps", "kind": "Interface" },