Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pickers] Use renderer interceptor on DateTimePicker #12441

Merged
10 changes: 10 additions & 0 deletions docs/data/migration/migration-pickers-v6/migration-pickers-v6.md
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,16 @@ Before v7, it was possible to import locales from the package root (that is `imp
+import { frFR } from '@mui/x-date-pickers/locales';
```

## Remove `dateTimeViewRenderers` export

The `dateTimeViewRenderers` export has been removed in favor of reusing existing time view renderers (`renderTimeViewClock`, `renderDigitalClockTimeView` and `renderMultiSectionDigitalClockTimeView`) and date view renderer (`renderDateViewCalendar`) to render the `DesktopDateTimePicker`.

If you were relying on this import, you can refer to the implementation of the `DesktopDateTimePicker` to see how to combine the renderers yourself.

:::info
The additional side-effect of this change is that passing `renderTimeViewClock` to time view renderers will no longer revert to the old behavior of rendering only date or time view.
:::

## Adapters internal changes

:::success
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ import {
useUtils,
TimeViewWithMeridiem,
BaseClockProps,
DefaultizedProps,
} from '@mui/x-date-pickers/internals';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { DateTimeRangePickerView } from '../internals/models';
import { DateRange } from '../models';
import { UseRangePositionResponse } from '../internals/hooks/useRangePosition';
import { isRangeValid } from '../internals/utils/date-utils';
import { calculateRangeChange } from '../internals/utils/date-range-manager';

export type DateTimeRangePickerTimeWrapperProps<
TDate extends PickerValidDate,
TView extends DateTimeRangePickerView,
TComponentProps extends Omit<
BaseClockProps<TDate, TimeViewWithMeridiem>,
'value' | 'defaultValue' | 'onChange'
TView extends TimeViewWithMeridiem,
TComponentProps extends DefaultizedProps<
Omit<BaseClockProps<TDate, TView>, 'value' | 'defaultValue' | 'onChange'>,
'views'
>,
> = Pick<UseRangePositionResponse, 'rangePosition' | 'onRangePositionChange'> &
Omit<
Expand All @@ -36,7 +36,7 @@ export type DateTimeRangePickerTimeWrapperProps<
selectionState: PickerSelectionState,
selectedView: TView,
) => void;
viewRenderer?: PickerViewRenderer<DateRange<TDate>, TView, any, TComponentProps> | null;
viewRenderer?: PickerViewRenderer<DateRange<TDate>, TView, TComponentProps, any> | null;
openTo?: TView;
};

Expand All @@ -45,10 +45,10 @@ export type DateTimeRangePickerTimeWrapperProps<
*/
function DateTimeRangePickerTimeWrapper<
TDate extends PickerValidDate,
TView extends DateTimeRangePickerView,
TComponentProps extends Omit<
BaseClockProps<TDate, TimeViewWithMeridiem>,
'value' | 'defaultValue' | 'onChange'
TView extends TimeViewWithMeridiem,
TComponentProps extends DefaultizedProps<
Omit<BaseClockProps<TDate, TView>, 'value' | 'defaultValue' | 'onChange'>,
'views'
>,
>(
props: DateTimeRangePickerTimeWrapperProps<TDate, TView, TComponentProps>,
Expand Down
29 changes: 17 additions & 12 deletions packages/x-date-pickers-pro/src/DateTimeRangePicker/shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
resolveTimeViewsResponse,
UseViewsOptions,
DateTimeValidationProps,
DateOrTimeViewWithMeridiem,
} from '@mui/x-date-pickers/internals';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { TimeViewRendererProps } from '@mui/x-date-pickers/timeViewRenderers';
Expand Down Expand Up @@ -73,6 +74,21 @@ export interface BaseDateTimeRangePickerSlotProps<TDate extends PickerValidDate>
toolbar?: ExportedDateTimeRangePickerToolbarProps;
}

export type DateTimeRangePickerRenderers<
TDate extends PickerValidDate,
TView extends DateOrTimeViewWithMeridiem,
TAdditionalProps extends {} = {},
> = PickerViewRendererLookup<
DateRange<TDate>,
TView,
Omit<DateRangeViewRendererProps<TDate, 'day'>, 'view' | 'slots' | 'slotProps'> &
Omit<
TimeViewRendererProps<TimeViewWithMeridiem, BaseClockProps<TDate, TimeViewWithMeridiem>>,
'view' | 'slots' | 'slotProps'
> & { view: TView },
TAdditionalProps
>;

export interface BaseDateTimeRangePickerProps<TDate extends PickerValidDate>
extends Omit<
BasePickerInputProps<
Expand Down Expand Up @@ -105,18 +121,7 @@ export interface BaseDateTimeRangePickerProps<TDate extends PickerValidDate>
* If `null`, the section will only have field editing.
* If `undefined`, internally defined view will be the used.
*/
viewRenderers?: Partial<
PickerViewRendererLookup<
DateRange<TDate>,
DateTimeRangePickerView,
Omit<DateRangeViewRendererProps<TDate, 'day'>, 'view' | 'slots' | 'slotProps'> &
Omit<
TimeViewRendererProps<TimeViewWithMeridiem, BaseClockProps<TDate, TimeViewWithMeridiem>>,
'view' | 'slots' | 'slotProps'
> & { view: DateTimeRangePickerView },
{}
>
>;
viewRenderers?: Partial<DateTimeRangePickerRenderers<TDate, DateTimeRangePickerView>>;
}

type UseDateTimeRangePickerDefaultizedProps<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
isDatePickerView,
isInternalTimeView,
PickerViewRenderer,
PickerViewRendererLookup,
PickerViewsRendererProps,
} from '@mui/x-date-pickers/internals';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { resolveComponentProps } from '@mui/base/utils';
Expand All @@ -22,6 +22,7 @@ import {
import Divider from '@mui/material/Divider';
import { digitalClockClasses } from '@mui/x-date-pickers/DigitalClock';
import type { PickersActionBarAction } from '@mui/x-date-pickers/PickersActionBar';
import { DesktopDateTimePickerLayout } from '@mui/x-date-pickers/DesktopDateTimePicker';
import { rangeValueManager } from '../internals/utils/valueManagers';
import { DesktopDateTimeRangePickerProps } from './DesktopDateTimeRangePicker.types';
import { renderDateRangeViewCalendar } from '../dateRangeViewRenderers';
Expand All @@ -32,47 +33,54 @@ import {
import { validateDateTimeRange } from '../internals/utils/validation/validateDateTimeRange';
import { DateTimeRangePickerView } from '../internals/models';
import { DateRange } from '../models';
import { useDateTimeRangePickerDefaultizedProps } from '../DateTimeRangePicker/shared';
import {
DateTimeRangePickerRenderers,
useDateTimeRangePickerDefaultizedProps,
} from '../DateTimeRangePicker/shared';
import { MultiInputDateTimeRangeField } from '../MultiInputDateTimeRangeField';
import { DateTimeRangePickerTimeWrapper } from '../DateTimeRangePicker/DateTimeRangePickerTimeWrapper';
import { RANGE_VIEW_HEIGHT } from '../internals/constants/dimensions';
import { DesktopDateTimeRangePickerLayout } from './DesktopDateTimeRangePickerLayout';

const rendererInterceptor = function rendererInterceptor<
TDate extends PickerValidDate,
TEnableAccessibleFieldDOMStructure extends boolean,
>(
inViewRenderers: PickerViewRendererLookup<DateRange<TDate>, DateTimeRangePickerView, any, any>,
inViewRenderers: DateTimeRangePickerRenderers<TDate, DateTimeRangePickerView, any>,
popperView: DateTimeRangePickerView,
rendererProps: DefaultizedProps<
Omit<
UseDesktopRangePickerProps<
TDate,
DateTimeRangePickerView,
TEnableAccessibleFieldDOMStructure,
any,
any
rendererProps: PickerViewsRendererProps<
DateRange<TDate>,
DateTimeRangePickerView,
DefaultizedProps<
Omit<
UseDesktopRangePickerProps<
TDate,
DateTimeRangePickerView,
TEnableAccessibleFieldDOMStructure,
any,
any
>,
'onChange' | 'sx' | 'className'
>,
'onChange'
'rangePosition' | 'onRangePositionChange' | 'openTo'
>,
'rangePosition' | 'onRangePositionChange' | 'openTo'
{}
>,
) {
const { openTo, rangePosition, sx, ...otherProps } = rendererProps;
const { openTo, rangePosition, ...otherProps } = rendererProps;
const finalProps = {
...otherProps,
rangePosition,
focusedView: null,
sx: [
{
borderBottom: 0,
width: 'auto',
[`&.${multiSectionDigitalClockClasses.root}`]: {
borderBottom: 0,
},
[`&.${multiSectionDigitalClockClasses.root}, .${multiSectionDigitalClockSectionClasses.root}, &.${digitalClockClasses.root}`]:
{
maxHeight: RANGE_VIEW_HEIGHT,
},
},
...(Array.isArray(sx) ? sx : [sx]),
],
};
const isTimeViewActive = isInternalTimeView(popperView);
Expand All @@ -88,6 +96,7 @@ const rendererInterceptor = function rendererInterceptor<
<DateTimeRangePickerTimeWrapper
{...finalProps}
view={isTimeViewActive ? popperView : 'hours'}
views={finalProps.views.filter(isInternalTimeView)}
openTo={isInternalTimeView(openTo) ? openTo : 'hours'}
viewRenderer={
inViewRenderers[isTimeViewActive ? popperView : 'hours'] as PickerViewRenderer<
Expand Down Expand Up @@ -127,12 +136,7 @@ const DesktopDateTimeRangePicker = React.forwardRef(function DesktopDateTimeRang
? renderDigitalClockTimeView
: renderMultiSectionDigitalClockTimeView;

const viewRenderers: PickerViewRendererLookup<
DateRange<TDate>,
DateTimeRangePickerView,
any,
{}
> = {
const viewRenderers: DateTimeRangePickerRenderers<TDate, DateTimeRangePickerView, any> = {
day: renderDateRangeViewCalendar,
hours: renderTimeView,
minutes: renderTimeView,
Expand All @@ -159,7 +163,7 @@ const DesktopDateTimeRangePicker = React.forwardRef(function DesktopDateTimeRang
calendars: defaultizedProps.calendars ?? 1,
slots: {
field: MultiInputDateTimeRangeField,
layout: DesktopDateTimeRangePickerLayout,
layout: DesktopDateTimePickerLayout,
...defaultizedProps.slots,
},
slotProps: {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import {
VIEW_HEIGHT,
extractValidationProps,
isInternalTimeView,
PickerViewRendererLookup,
isDatePickerView,
PickerViewRenderer,
DefaultizedProps,
PickerViewsRendererProps,
TimeViewWithMeridiem,
} from '@mui/x-date-pickers/internals';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { resolveComponentProps } from '@mui/base/utils';
Expand All @@ -32,7 +33,10 @@ import {
import { validateDateTimeRange } from '../internals/utils/validation/validateDateTimeRange';
import { DateTimeRangePickerView } from '../internals/models';
import { DateRange } from '../models';
import { useDateTimeRangePickerDefaultizedProps } from '../DateTimeRangePicker/shared';
import {
DateTimeRangePickerRenderers,
useDateTimeRangePickerDefaultizedProps,
} from '../DateTimeRangePicker/shared';
import { MultiInputDateTimeRangeField } from '../MultiInputDateTimeRangeField';
import { DateTimeRangePickerTimeWrapper } from '../DateTimeRangePicker/DateTimeRangePickerTimeWrapper';
import { RANGE_VIEW_HEIGHT } from '../internals/constants/dimensions';
Expand All @@ -41,23 +45,25 @@ const rendererInterceptor = function rendererInterceptor<
TDate extends PickerValidDate,
TEnableAccessibleFieldDOMStructure extends boolean,
>(
inViewRenderers: PickerViewRendererLookup<DateRange<TDate>, DateTimeRangePickerView, any, any>,
inViewRenderers: DateTimeRangePickerRenderers<TDate, DateTimeRangePickerView, any>,
popperView: DateTimeRangePickerView,
rendererProps: DefaultizedProps<
Omit<
rendererProps: PickerViewsRendererProps<
DateRange<TDate>,
DateTimeRangePickerView,
DefaultizedProps<
UseMobileRangePickerProps<
TDate,
DateTimeRangePickerView,
TEnableAccessibleFieldDOMStructure,
any,
any
>,
'onChange'
'rangePosition' | 'onRangePositionChange' | 'openTo'
>,
'rangePosition' | 'onRangePositionChange' | 'openTo'
{}
>,
) {
const { view, openTo, rangePosition, sx, ...otherRendererProps } = rendererProps;
const { view, openTo, rangePosition, ...otherRendererProps } = rendererProps;
const finalProps = {
...otherRendererProps,
rangePosition,
Expand All @@ -84,7 +90,6 @@ const rendererInterceptor = function rendererInterceptor<
maxHeight: RANGE_VIEW_HEIGHT - 1,
},
},
...(Array.isArray(sx) ? sx : [sx]),
],
};
const isTimeView = isInternalTimeView(popperView);
Expand All @@ -97,15 +102,16 @@ const rendererInterceptor = function rendererInterceptor<
<DateTimeRangePickerTimeWrapper
{...finalProps}
viewRenderer={
viewRenderer as PickerViewRenderer<DateRange<TDate>, DateTimeRangePickerView, any, {}>
viewRenderer as PickerViewRenderer<DateRange<TDate>, TimeViewWithMeridiem, any, {}>
}
view={view && isInternalTimeView(view) ? view : 'hours'}
views={finalProps.views.filter(isInternalTimeView)}
openTo={isInternalTimeView(openTo) ? openTo : 'hours'}
/>
);
}
// avoiding problem of `props: never`
const typedViewRenderer = viewRenderer as PickerViewRenderer<DateRange<TDate>, 'day', any, {}>;
const typedViewRenderer = viewRenderer as PickerViewRenderer<DateRange<TDate>, 'day', any, any>;

return typedViewRenderer({
...finalProps,
Expand Down Expand Up @@ -141,12 +147,7 @@ const MobileDateTimeRangePicker = React.forwardRef(function MobileDateTimeRangeP
? renderDigitalClockTimeView
: renderMultiSectionDigitalClockTimeView;

const viewRenderers: PickerViewRendererLookup<
DateRange<TDate>,
DateTimeRangePickerView,
any,
{}
> = {
const viewRenderers: DateTimeRangePickerRenderers<TDate, DateTimeRangePickerView, any> = {
day: renderDateRangeViewCalendar,
hours: renderTimeView,
minutes: renderTimeView,
Expand Down
Loading
Loading