Skip to content

Commit

Permalink
[pickers] Create a new context to pass the range position props to th…
Browse files Browse the repository at this point in the history
…e layout components and to the views
  • Loading branch information
flaviendelangle committed Dec 11, 2024
1 parent 767e185 commit 879440a
Show file tree
Hide file tree
Showing 48 changed files with 327 additions and 403 deletions.
38 changes: 38 additions & 0 deletions docs/data/migration/migration-pickers-v7/migration-pickers-v7.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,18 @@ const theme = createTheme({
+console.log(variant);
```

- The component passed to the `layout` slot no longer receives a `rangePosition` and `onRangePositionChange` in range pickers, instead you can use the `usePickerRangePositionContext` hook:

```diff
+import { usePickerRangePositionContext } from '@mui/x-date-pickers-pro/hooks';

-const { rangePosition } = props;
+const { rangePosition } = usePickerRangePositionContext();

-const { onRangePositionChange } = props;
+const { onRangePositionChange } = usePickerRangePositionContext();
```

### Slot: `toolbar`

- The component passed to the `toolbar` slot no longer receives a `disabled` prop, instead you can use the `usePickerContext` hook:
Expand All @@ -351,6 +363,32 @@ const theme = createTheme({
+console.log(readOnly);
```

- The component passed to the `toolbar` slot no longer receives a `rangePosition` and `onRangePositionChange` in range pickers, instead you can use the `usePickerRangePositionContext` hook:

```diff
+import { usePickerRangePositionContext } from '@mui/x-date-pickers-pro/hooks';

-const { rangePosition } = props;
+const { rangePosition } = usePickerRangePositionContext();

-const { onRangePositionChange } = props;
+const { onRangePositionChange } = usePickerRangePositionContext();
```

## Slot: `tabs`

- The component passed to the `tabs` slot no longer receives a `rangePosition` and `onRangePositionChange` in range pickers, instead you can use the `usePickerRangePositionContext` hook:

```diff
+import { usePickerRangePositionContext } from '@mui/x-date-pickers-pro/hooks';

-const { rangePosition } = props;
+const { rangePosition } = usePickerRangePositionContext();

-const { onRangePositionChange } = props;
+const { onRangePositionChange } = usePickerRangePositionContext();
```

## Renamed variables and types

The following variables and types have been renamed to have a coherent `Picker` / `Pickers` prefix:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import {
PickersRangeCalendarHeader,
PickersRangeCalendarHeaderProps,
} from '../PickersRangeCalendarHeader';
import { useNullablePickerRangePositionContext } from '../internals/hooks/useNullablePickerRangePositionContext';

const releaseInfo = getReleaseInfo();

Expand Down Expand Up @@ -187,8 +188,8 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar(
reduceAnimations,
onMonthChange,
rangePosition: rangePositionProp,
defaultRangePosition: inDefaultRangePosition,
onRangePositionChange: inOnRangePositionChange,
defaultRangePosition: defaultRangePositionProp,
onRangePositionChange: onRangePositionChangeProp,
calendars,
currentMonthCalendarPosition = 1,
slots,
Expand All @@ -214,6 +215,8 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar(
...other
} = props;

const rangePositionContext = useNullablePickerRangePositionContext();

const { value, handleValueChange, timezone } = useControlledValueWithTimezone<
PickerRangeValue,
NonNullable<typeof onChange>
Expand Down Expand Up @@ -241,9 +244,9 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar(
const id = useId();

const { rangePosition, onRangePositionChange } = useRangePosition({
rangePosition: rangePositionProp,
defaultRangePosition: inDefaultRangePosition,
onRangePositionChange: inOnRangePositionChange,
rangePosition: rangePositionProp ?? rangePositionContext?.rangePosition,
defaultRangePosition: defaultRangePositionProp,
onRangePositionChange: onRangePositionChangeProp ?? rangePositionContext?.onRangePositionChange,
});

const handleDatePositionChange = useEventCallback((position: RangePosition) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import {
useToolbarOwnerState,
} from '@mui/x-date-pickers/internals';
import { usePickerTranslations } from '@mui/x-date-pickers/hooks';
import { UseRangePositionResponse } from '../internals/hooks/useRangePosition';
import {
DateRangePickerToolbarClasses,
getDateRangePickerToolbarUtilityClass,
} from './dateRangePickerToolbarClasses';
import { usePickerRangePositionContext } from '../hooks';

const useUtilityClasses = (classes: Partial<DateRangePickerToolbarClasses> | undefined) => {
const slots = {
Expand All @@ -33,8 +33,7 @@ const useUtilityClasses = (classes: Partial<DateRangePickerToolbarClasses> | und

export interface DateRangePickerToolbarProps
extends ExportedDateRangePickerToolbarProps,
Omit<BaseToolbarProps<PickerRangeValue, 'day'>, 'onChange' | 'isLandscape'>,
Pick<UseRangePositionResponse, 'rangePosition' | 'onRangePositionChange'> {}
Omit<BaseToolbarProps<PickerRangeValue, 'day'>, 'onChange' | 'isLandscape'> {}

export interface ExportedDateRangePickerToolbarProps extends ExportedBaseToolbarProps {
/**
Expand Down Expand Up @@ -82,8 +81,6 @@ const DateRangePickerToolbar = React.forwardRef(function DateRangePickerToolbar(

const {
value: [start, end],
rangePosition,
onRangePositionChange,
toolbarFormat,
className,
classes: classesProp,
Expand All @@ -95,6 +92,7 @@ const DateRangePickerToolbar = React.forwardRef(function DateRangePickerToolbar(

const translations = usePickerTranslations();
const ownerState = useToolbarOwnerState();
const { rangePosition, onRangePositionChange } = usePickerRangePositionContext();
const classes = useUtilityClasses(classesProp);

const startDateValue = start
Expand Down Expand Up @@ -148,14 +146,12 @@ DateRangePickerToolbar.propTypes = {
* @default `true` for Desktop, `false` for Mobile.
*/
hidden: PropTypes.bool,
onRangePositionChange: PropTypes.func.isRequired,
/**
* Callback called when a toolbar is clicked
* @template TView
* @param {TView} view The view to open
*/
onViewChange: PropTypes.func.isRequired,
rangePosition: PropTypes.oneOf(['end', 'start']).isRequired,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/x-date-pickers-pro/src/DateRangePicker/shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export interface BaseDateRangePickerProps
* If `undefined`, internally defined view will be used.
*/
viewRenderers?: Partial<
PickerViewRendererLookup<PickerRangeValue, 'day', DateRangeViewRendererProps<'day'>, {}>
PickerViewRendererLookup<PickerRangeValue, 'day', DateRangeViewRendererProps<'day'>>
>;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import {
DateTimeRangePickerTabsClasses,
getDateTimeRangePickerTabsUtilityClass,
} from './dateTimeRangePickerTabsClasses';
import { UseRangePositionResponse } from '../internals/hooks/useRangePosition';
import { RangePosition } from '../models';
import { usePickerRangePositionContext } from '../hooks';

type TabValue = 'start-date' | 'start-time' | 'end-date' | 'end-time';

Expand Down Expand Up @@ -66,8 +66,7 @@ export interface ExportedDateTimeRangePickerTabsProps extends ExportedBaseTabsPr

export interface DateTimeRangePickerTabsProps
extends ExportedDateTimeRangePickerTabsProps,
BaseTabsProps<DateOrTimeViewWithMeridiem>,
Pick<UseRangePositionResponse, 'rangePosition' | 'onRangePositionChange'> {}
BaseTabsProps<DateOrTimeViewWithMeridiem> {}

const useUtilityClasses = (classes: Partial<DateTimeRangePickerTabsClasses> | undefined) => {
const slots = {
Expand Down Expand Up @@ -118,8 +117,6 @@ const DateTimeRangePickerTabs = function DateTimeRangePickerTabs(
timeIcon = <TimeIcon />,
view,
hidden = typeof window === 'undefined' || window.innerHeight < 667,
rangePosition,
onRangePositionChange,
className,
classes: classesProp,
sx,
Expand All @@ -128,6 +125,8 @@ const DateTimeRangePickerTabs = function DateTimeRangePickerTabs(
const translations = usePickerTranslations();
const { ownerState } = usePickerPrivateContext();
const classes = useUtilityClasses(classesProp);
const { rangePosition, onRangePositionChange } = usePickerRangePositionContext();

const value = React.useMemo(() => viewToTab(view, rangePosition), [view, rangePosition]);
const isPreviousHidden = value === 'start-date';
const isNextHidden = value === 'end-time';
Expand Down Expand Up @@ -236,14 +235,12 @@ DateTimeRangePickerTabs.propTypes = {
* @default `window.innerHeight < 667` for `DesktopDateTimeRangePicker` and `MobileDateTimeRangePicker`
*/
hidden: PropTypes.bool,
onRangePositionChange: PropTypes.func.isRequired,
/**
* Callback called when a tab is clicked.
* @template TView
* @param {TView} view The view to open
*/
onViewChange: PropTypes.func.isRequired,
rangePosition: PropTypes.oneOf(['end', 'start']).isRequired,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,64 +8,51 @@ import {
TimeViewWithMeridiem,
BaseClockProps,
PickerRangeValue,
PickerViewsRendererProps,
} from '@mui/x-date-pickers/internals';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { UseRangePositionResponse } from '../internals/hooks/useRangePosition';
import { isRangeValid } from '../internals/utils/date-utils';
import { calculateRangeChange } from '../internals/utils/date-range-manager';
import { usePickerRangePositionContext } from '../hooks';

export type DateTimeRangePickerTimeWrapperProps<
TView extends TimeViewWithMeridiem,
TComponentProps extends DefaultizedProps<
Omit<BaseClockProps<TView>, 'value' | 'defaultValue' | 'onChange'>,
Omit<BaseClockProps<TimeViewWithMeridiem>, 'value' | 'defaultValue' | 'onChange'>,
'views'
>,
> = Pick<UseRangePositionResponse, 'rangePosition' | 'onRangePositionChange'> &
Omit<
TComponentProps,
'views' | 'view' | 'onViewChange' | 'value' | 'defaultValue' | 'onChange'
> & {
view: TView;
onViewChange?: (view: TView) => void;
views: readonly TView[];
value?: PickerRangeValue;
defaultValue?: PickerRangeValue;
onChange?: (
value: PickerRangeValue,
selectionState: PickerSelectionState,
selectedView: TView,
) => void;
viewRenderer?: PickerViewRenderer<PickerRangeValue, TView, TComponentProps, any> | null;
openTo?: TView;
};
> = Omit<
TComponentProps,
'views' | 'view' | 'onViewChange' | 'value' | 'defaultValue' | 'onChange'
> & {
view: TimeViewWithMeridiem;
onViewChange?: (view: TimeViewWithMeridiem) => void;
views: readonly TimeViewWithMeridiem[];
value?: PickerRangeValue;
defaultValue?: PickerRangeValue;
onChange?: (
value: PickerRangeValue,
selectionState: PickerSelectionState,
selectedView: TimeViewWithMeridiem,
) => void;
viewRenderer?: PickerViewRenderer<PickerRangeValue, TComponentProps> | null;
openTo?: TimeViewWithMeridiem;
};

/**
* @ignore - internal component.
*/
function DateTimeRangePickerTimeWrapper<
TView extends TimeViewWithMeridiem,
TComponentProps extends DefaultizedProps<
Omit<BaseClockProps<TView>, 'value' | 'defaultValue' | 'onChange'>,
Omit<BaseClockProps<TimeViewWithMeridiem>, 'value' | 'defaultValue' | 'onChange'>,
'views'
>,
>(
props: DateTimeRangePickerTimeWrapperProps<TView, TComponentProps>,
ref: React.Ref<HTMLDivElement>,
) {
>(props: DateTimeRangePickerTimeWrapperProps<TComponentProps>, ref: React.Ref<HTMLDivElement>) {
const utils = useUtils();

const {
rangePosition,
onRangePositionChange,
viewRenderer,
value,
onChange,
defaultValue,
onViewChange,
views,
className,
...other
} = props;
const { viewRenderer, value, onChange, defaultValue, onViewChange, views, className, ...other } =
props;

const { rangePosition, onRangePositionChange } = usePickerRangePositionContext();

if (!viewRenderer) {
return null;
Expand All @@ -77,7 +64,7 @@ function DateTimeRangePickerTimeWrapper<
const handleOnChange = (
newDate: PickerValidDate | null,
selectionState: PickerSelectionState,
selectedView: TView,
selectedView: TimeViewWithMeridiem,
) => {
if (!onChange || !value) {
return;
Expand Down Expand Up @@ -106,7 +93,7 @@ function DateTimeRangePickerTimeWrapper<
value: currentValue,
onChange: handleOnChange,
defaultValue: currentDefaultValue,
});
} as any as PickerViewsRendererProps<PickerRangeValue, TimeViewWithMeridiem, TComponentProps>);
}

export { DateTimeRangePickerTimeWrapper };
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import {
import { usePickerContext, usePickerTranslations } from '@mui/x-date-pickers/hooks';
import { PickerValidDate } from '@mui/x-date-pickers/models';
import { DateTimePickerToolbar } from '@mui/x-date-pickers/DateTimePicker';
import { UseRangePositionResponse } from '../internals/hooks/useRangePosition';
import {
DateTimeRangePickerToolbarClasses,
getDateTimeRangePickerToolbarUtilityClass,
} from './dateTimeRangePickerToolbarClasses';
import { calculateRangeChange } from '../internals/utils/date-range-manager';
import { usePickerRangePositionContext } from '../hooks';

const useUtilityClasses = (classes: Partial<DateTimeRangePickerToolbarClasses> | undefined) => {
const slots = {
Expand All @@ -38,7 +38,6 @@ type DateTimeRangeViews = Exclude<DateOrTimeViewWithMeridiem, 'year' | 'month'>;

export interface DateTimeRangePickerToolbarProps
extends BaseToolbarProps<PickerRangeValue, DateTimeRangeViews>,
Pick<UseRangePositionResponse, 'rangePosition' | 'onRangePositionChange'>,
ExportedDateTimeRangePickerToolbarProps {
ampm?: boolean;
}
Expand Down Expand Up @@ -89,8 +88,6 @@ const DateTimeRangePickerToolbar = React.forwardRef(function DateTimeRangePicker

const {
value: [start, end],
rangePosition,
onRangePositionChange,
className,
classes: classesProp,
onViewChange,
Expand All @@ -111,6 +108,7 @@ const DateTimeRangePickerToolbar = React.forwardRef(function DateTimeRangePicker
const { disabled, readOnly } = usePickerContext();
const translations = usePickerTranslations();
const ownerState = useToolbarOwnerState();
const { rangePosition, onRangePositionChange } = usePickerRangePositionContext();
const classes = useUtilityClasses(classesProp);

const commonToolbarProps = {
Expand Down
23 changes: 10 additions & 13 deletions packages/x-date-pickers-pro/src/DateTimeRangePicker/shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,16 @@ export interface BaseDateTimeRangePickerSlotProps
toolbar?: ExportedDateTimeRangePickerToolbarProps;
}

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

export interface BaseDateTimeRangePickerProps
extends Omit<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const DesktopDateRangePicker = React.forwardRef(function DesktopDateRangePicker<
DesktopDateRangePickerProps<TEnableAccessibleFieldDOMStructure>
>(inProps, 'MuiDesktopDateRangePicker');

const viewRenderers: PickerViewRendererLookup<PickerRangeValue, 'day', any, {}> = {
const viewRenderers: PickerViewRendererLookup<PickerRangeValue, any, any> = {
day: renderDateRangeViewCalendar,
...defaultizedProps.viewRenderers,
};
Expand Down
Loading

0 comments on commit 879440a

Please sign in to comment.