Skip to content

Commit

Permalink
[fields] Improve useSplitFieldProps and make it public (#14514)
Browse files Browse the repository at this point in the history
  • Loading branch information
flaviendelangle authored Sep 11, 2024
1 parent a198b26 commit 309106d
Show file tree
Hide file tree
Showing 15 changed files with 106 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,16 @@ import {
unstable_generateUtilityClass as generateUtilityClass,
unstable_generateUtilityClasses as generateUtilityClasses,
} from '@mui/utils';
import {
splitFieldInternalAndForwardedProps,
convertFieldResponseIntoMuiTextFieldProps,
} from '@mui/x-date-pickers/internals';
import { convertFieldResponseIntoMuiTextFieldProps } from '@mui/x-date-pickers/internals';
import { useSplitFieldProps } from '@mui/x-date-pickers/hooks';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { PickersTextField } from '@mui/x-date-pickers/PickersTextField';
import {
MultiInputDateRangeFieldProps,
MultiInputDateRangeFieldSlotProps,
} from './MultiInputDateRangeField.types';
import { useMultiInputDateRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField';
import { MultiInputRangeFieldClasses, RangePosition, UseDateRangeFieldProps } from '../models';
import { MultiInputRangeFieldClasses, RangePosition } from '../models';

export const multiInputDateRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses(
'MuiMultiInputDateRangeField',
Expand Down Expand Up @@ -91,10 +89,7 @@ const MultiInputDateRangeField = React.forwardRef(function MultiInputDateRangeFi
name: 'MuiMultiInputDateRangeField',
});

const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps<
typeof themeProps,
keyof Omit<UseDateRangeFieldProps<any, any>, 'clearable' | 'onClear'>
>(themeProps, 'date');
const { internalProps, forwardedProps } = useSplitFieldProps(themeProps, 'date');

const {
slots,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,15 @@ import {
unstable_generateUtilityClass as generateUtilityClass,
unstable_generateUtilityClasses as generateUtilityClasses,
} from '@mui/utils';
import {
splitFieldInternalAndForwardedProps,
convertFieldResponseIntoMuiTextFieldProps,
} from '@mui/x-date-pickers/internals';
import { convertFieldResponseIntoMuiTextFieldProps } from '@mui/x-date-pickers/internals';
import { useSplitFieldProps } from '@mui/x-date-pickers/hooks';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { PickersTextField } from '@mui/x-date-pickers/PickersTextField';
import {
MultiInputDateTimeRangeFieldProps,
MultiInputDateTimeRangeFieldSlotProps,
} from './MultiInputDateTimeRangeField.types';
import { useMultiInputDateTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField';
import { UseDateTimeRangeFieldProps } from '../internals/models/dateTimeRange';
import { MultiInputRangeFieldClasses, RangePosition } from '../models';

export const multiInputDateTimeRangeFieldClasses: MultiInputRangeFieldClasses =
Expand Down Expand Up @@ -90,10 +87,7 @@ const MultiInputDateTimeRangeField = React.forwardRef(function MultiInputDateTim
name: 'MuiMultiInputDateTimeRangeField',
});

const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps<
typeof themeProps,
keyof Omit<UseDateTimeRangeFieldProps<any, any>, 'clearable' | 'onClear'>
>(themeProps, 'date-time');
const { internalProps, forwardedProps } = useSplitFieldProps(themeProps, 'date-time');

const {
slots,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,15 @@ import {
unstable_generateUtilityClass as generateUtilityClass,
unstable_generateUtilityClasses as generateUtilityClasses,
} from '@mui/utils';
import {
splitFieldInternalAndForwardedProps,
convertFieldResponseIntoMuiTextFieldProps,
} from '@mui/x-date-pickers/internals';
import { convertFieldResponseIntoMuiTextFieldProps } from '@mui/x-date-pickers/internals';
import { useSplitFieldProps } from '@mui/x-date-pickers/hooks';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { PickersTextField } from '@mui/x-date-pickers/PickersTextField';
import {
MultiInputTimeRangeFieldProps,
MultiInputTimeRangeFieldSlotProps,
} from './MultiInputTimeRangeField.types';
import { useMultiInputTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField';
import { UseTimeRangeFieldProps } from '../internals/models/timeRange';
import { MultiInputRangeFieldClasses, RangePosition } from '../models';

export const multiInputTimeRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses(
Expand Down Expand Up @@ -92,10 +89,7 @@ const MultiInputTimeRangeField = React.forwardRef(function MultiInputTimeRangeFi
name: 'MuiMultiInputTimeRangeField',
});

const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps<
typeof themeProps,
keyof Omit<UseTimeRangeFieldProps<any, any>, 'clearable' | 'onClear'>
>(themeProps, 'time');
const { internalProps, forwardedProps } = useSplitFieldProps(themeProps, 'time');

const {
slots,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import * as React from 'react';
import {
useField,
splitFieldInternalAndForwardedProps,
useDefaultizedDateField,
} from '@mui/x-date-pickers/internals';
import { useField, useDefaultizedDateField } from '@mui/x-date-pickers/internals';
import { useSplitFieldProps } from '@mui/x-date-pickers/hooks';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { UseSingleInputDateRangeFieldProps } from './SingleInputDateRangeField.types';
import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers';
Expand All @@ -23,10 +20,7 @@ export const useSingleInputDateRangeField = <
TAllProps
>(inProps);

const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps<
typeof props,
keyof UseSingleInputDateRangeFieldProps<TDate, TEnableAccessibleFieldDOMStructure>
>(props, 'date');
const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date');

const fieldValueManager = React.useMemo(
() => getRangeFieldValueManager<TDate>({ dateSeparator: internalProps.dateSeparator }),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import * as React from 'react';
import {
useField,
splitFieldInternalAndForwardedProps,
useDefaultizedDateTimeField,
} from '@mui/x-date-pickers/internals';
import { useField, useDefaultizedDateTimeField } from '@mui/x-date-pickers/internals';
import { useSplitFieldProps } from '@mui/x-date-pickers/hooks';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { UseSingleInputDateTimeRangeFieldProps } from './SingleInputDateTimeRangeField.types';
import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers';
Expand All @@ -26,10 +23,7 @@ export const useSingleInputDateTimeRangeField = <
TAllProps
>(inProps);

const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps<
typeof props,
keyof UseSingleInputDateTimeRangeFieldProps<any, any>
>(props, 'date-time');
const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date-time');

const fieldValueManager = React.useMemo(
() => getRangeFieldValueManager<TDate>({ dateSeparator: internalProps.dateSeparator }),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import * as React from 'react';
import {
useField,
splitFieldInternalAndForwardedProps,
useDefaultizedTimeField,
} from '@mui/x-date-pickers/internals';
import { useField, useDefaultizedTimeField } from '@mui/x-date-pickers/internals';
import { useSplitFieldProps } from '@mui/x-date-pickers/hooks';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { UseSingleInputTimeRangeFieldProps } from './SingleInputTimeRangeField.types';
import { rangeValueManager, getRangeFieldValueManager } from '../internals/utils/valueManagers';
Expand All @@ -23,10 +20,7 @@ export const useSingleInputTimeRangeField = <
TAllProps
>(inProps);

const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps<
typeof props,
keyof UseSingleInputTimeRangeFieldProps<any, any>
>(props, 'time');
const { forwardedProps, internalProps } = useSplitFieldProps(props, 'time');

const fieldValueManager = React.useMemo(
() => getRangeFieldValueManager<TDate>({ dateSeparator: internalProps.dateSeparator }),
Expand Down
7 changes: 2 additions & 5 deletions packages/x-date-pickers/src/DateField/useDateField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import { useField } from '../internals/hooks/useField';
import { UseDateFieldProps } from './DateField.types';
import { validateDate } from '../internals/utils/validation/validateDate';
import { splitFieldInternalAndForwardedProps } from '../internals/utils/fields';
import { useSplitFieldProps } from '../hooks';
import { FieldSection, PickerValidDate } from '../models';
import { useDefaultizedDateField } from '../internals/hooks/defaultizedFieldProps';

Expand All @@ -22,10 +22,7 @@ export const useDateField = <
TAllProps
>(inProps);

const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps<
typeof props,
keyof UseDateFieldProps<TDate, TEnableAccessibleFieldDOMStructure>
>(props, 'date');
const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date');

return useField<
TDate | null,
Expand Down
7 changes: 2 additions & 5 deletions packages/x-date-pickers/src/DateTimeField/useDateTimeField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import { useField } from '../internals/hooks/useField';
import { UseDateTimeFieldProps } from './DateTimeField.types';
import { validateDateTime } from '../internals/utils/validation/validateDateTime';
import { splitFieldInternalAndForwardedProps } from '../internals/utils/fields';
import { useSplitFieldProps } from '../hooks';
import { FieldSection, PickerValidDate } from '../models';
import { useDefaultizedDateTimeField } from '../internals/hooks/defaultizedFieldProps';

Expand All @@ -22,10 +22,7 @@ export const useDateTimeField = <
TAllProps
>(inProps);

const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps<
typeof props,
keyof UseDateTimeFieldProps<any, TEnableAccessibleFieldDOMStructure>
>(props, 'date-time');
const { forwardedProps, internalProps } = useSplitFieldProps(props, 'date-time');

return useField<
TDate | null,
Expand Down
7 changes: 2 additions & 5 deletions packages/x-date-pickers/src/TimeField/useTimeField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import { useField } from '../internals/hooks/useField';
import { UseTimeFieldProps } from './TimeField.types';
import { validateTime } from '../internals/utils/validation/validateTime';
import { splitFieldInternalAndForwardedProps } from '../internals/utils/fields';
import { useSplitFieldProps } from '../hooks';
import { PickerValidDate, FieldSection } from '../models';
import { useDefaultizedTimeField } from '../internals/hooks/defaultizedFieldProps';

Expand All @@ -22,10 +22,7 @@ export const useTimeField = <
TAllProps
>(inProps);

const { forwardedProps, internalProps } = splitFieldInternalAndForwardedProps<
typeof props,
keyof UseTimeFieldProps<any, TEnableAccessibleFieldDOMStructure>
>(props, 'time');
const { forwardedProps, internalProps } = useSplitFieldProps(props, 'time');

return useField<
TDate | null,
Expand Down
2 changes: 2 additions & 0 deletions packages/x-date-pickers/src/hooks/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ export type {
} from './useClearableField';

export { usePickersTranslations } from './usePickersTranslations';

export { useSplitFieldProps } from './useSplitFieldProps';
77 changes: 77 additions & 0 deletions packages/x-date-pickers/src/hooks/useSplitFieldProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as React from 'react';
import { FieldValueType } from '../models';
import {
DATE_TIME_VALIDATION_PROP_NAMES,
DATE_VALIDATION_PROP_NAMES,
TIME_VALIDATION_PROP_NAMES,
} from '../internals/utils/validation/extractValidationProps';

const SHARED_FIELD_INTERNAL_PROP_NAMES = [
'value',
'defaultValue',
'referenceDate',
'format',
'formatDensity',
'onChange',
'timezone',
'onError',
'shouldRespectLeadingZeros',
'selectedSections',
'onSelectedSectionsChange',
'unstableFieldRef',
'enableAccessibleFieldDOMStructure',
'disabled',
'readOnly',
'dateSeparator',
] as const;

type InternalPropNames<TValueType extends FieldValueType> =
| (typeof SHARED_FIELD_INTERNAL_PROP_NAMES)[number]
| (TValueType extends 'date' | 'date-time' ? (typeof DATE_VALIDATION_PROP_NAMES)[number] : never)
| (TValueType extends 'time' | 'date-time' ? (typeof TIME_VALIDATION_PROP_NAMES)[number] : never)
| (TValueType extends 'date-time' ? (typeof DATE_TIME_VALIDATION_PROP_NAMES)[number] : never);

/**
* Split the props received by the field component into:
* - `internalProps` which are used by the various hooks called by the field component.
* - `forwardedProps` which are passed to the underlying component.
* Note that some forwarded props might be used by the hooks as well.
* For instance, hooks like `useDateField` need props like `autoFocus` to know how to behave.
* @template TProps, TValueType
* @param {TProps} props The props received by the field component.
* @param {TValueType} valueType The type of the field value ('date', 'time', or 'date-time').
*/
export const useSplitFieldProps = <
TValueType extends FieldValueType,
TProps extends { [key in InternalPropNames<TValueType>]?: any },
>(
props: TProps,
valueType: TValueType,
) => {
return React.useMemo(() => {
const forwardedProps = { ...props } as Omit<TProps, InternalPropNames<TValueType>>;
const internalProps = {} as Pick<TProps, InternalPropNames<TValueType>>;

const extractProp = (propName: string) => {
if (forwardedProps.hasOwnProperty(propName)) {
// @ts-ignore
internalProps[propName] = forwardedProps[propName];
delete forwardedProps[propName as keyof typeof forwardedProps];
}
};

SHARED_FIELD_INTERNAL_PROP_NAMES.forEach(extractProp);

if (valueType === 'date') {
DATE_VALIDATION_PROP_NAMES.forEach(extractProp);
} else if (valueType === 'time') {
TIME_VALIDATION_PROP_NAMES.forEach(extractProp);
} else if (valueType === 'date-time') {
DATE_VALIDATION_PROP_NAMES.forEach(extractProp);
TIME_VALIDATION_PROP_NAMES.forEach(extractProp);
DATE_TIME_VALIDATION_PROP_NAMES.forEach(extractProp);
}

return { forwardedProps, internalProps };
}, [props, valueType]);
};
1 change: 0 additions & 1 deletion packages/x-date-pickers/src/internals/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ export {
formatMeridiem,
} from './utils/date-utils';
export { resolveTimeViewsResponse, resolveDateTimeFormat } from './utils/date-time-utils';
export { splitFieldInternalAndForwardedProps } from './utils/fields';
export { getDefaultReferenceDate } from './utils/getDefaultReferenceDate';
export {
executeInTheNextEventLoopTick,
Expand Down
58 changes: 0 additions & 58 deletions packages/x-date-pickers/src/internals/utils/fields.ts

This file was deleted.

1 change: 1 addition & 0 deletions scripts/x-date-pickers-pro.exports.json
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@
{ "name": "UseSingleInputDateRangeFieldProps", "kind": "Interface" },
{ "name": "UseSingleInputDateTimeRangeFieldProps", "kind": "Interface" },
{ "name": "UseSingleInputTimeRangeFieldProps", "kind": "Interface" },
{ "name": "useSplitFieldProps", "kind": "Variable" },
{ "name": "UseTimeFieldComponentProps", "kind": "TypeAlias" },
{ "name": "UseTimeFieldProps", "kind": "Interface" },
{ "name": "YearCalendar", "kind": "Variable" },
Expand Down
Loading

0 comments on commit 309106d

Please sign in to comment.