Skip to content

Commit 7dfca29

Browse files
[pickers] Simplify the usePicker file structure (#16680)
Signed-off-by: Flavien DELANGLE <[email protected]> Co-authored-by: Michel Engelen <[email protected]>
1 parent 83ad21f commit 7dfca29

File tree

36 files changed

+1115
-1443
lines changed

36 files changed

+1115
-1443
lines changed

packages/x-date-pickers-pro/src/internals/hooks/models/useRangePicker.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,31 @@
11
import {
2-
UsePickerParams,
2+
UsePickerParameters,
33
BasePickerProps,
4-
UsePickerViewsProps,
5-
UsePickerValueNonStaticProps,
6-
UsePickerProviderNonStaticProps,
4+
UsePickerProps,
5+
UsePickerNonStaticProps,
76
DateOrTimeViewWithMeridiem,
87
PickerRangeValue,
98
} from '@mui/x-date-pickers/internals';
109
import { BaseRangeNonStaticPickerProps } from '../../models';
1110
import { UseRangePositionProps } from '../useRangePosition';
1211

1312
export interface RangeOnlyPickerProps
14-
extends UsePickerValueNonStaticProps,
15-
UsePickerProviderNonStaticProps,
13+
extends UsePickerNonStaticProps,
1614
BaseRangeNonStaticPickerProps,
1715
UseRangePositionProps {}
1816

1917
export interface UseRangePickerProps<
2018
TView extends DateOrTimeViewWithMeridiem,
2119
TError,
22-
TExternalProps extends UsePickerViewsProps<any, TView, any>,
20+
TExternalProps extends UsePickerProps<PickerRangeValue, TView, TError, any>,
2321
> extends RangeOnlyPickerProps,
2422
BasePickerProps<PickerRangeValue, TView, TError, TExternalProps> {}
2523

2624
export interface UseRangePickerParams<
2725
TView extends DateOrTimeViewWithMeridiem,
2826
TExternalProps extends UseRangePickerProps<TView, any, TExternalProps>,
2927
> extends Pick<
30-
UsePickerParams<PickerRangeValue, TView, TExternalProps>,
28+
UsePickerParameters<PickerRangeValue, TView, TExternalProps>,
3129
'valueManager' | 'valueType' | 'validator' | 'rendererInterceptor' | 'ref'
3230
> {
3331
props: TExternalProps;

packages/x-date-pickers-pro/src/internals/hooks/useDesktopRangePicker/useDesktopRangePicker.types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { PickerFieldSlotProps, PickerOwnerState } from '@mui/x-date-pickers/mode
33
import {
44
PickerPopperSlots,
55
PickerPopperSlotProps,
6-
UsePickerViewsProps,
6+
UsePickerProps,
77
DateOrTimeViewWithMeridiem,
88
PickerRangeValue,
99
PickerFieldUISlotsFromContext,
@@ -53,7 +53,7 @@ export interface UseDesktopRangePickerProps<
5353
TView extends DateOrTimeViewWithMeridiem,
5454
TEnableAccessibleFieldDOMStructure extends boolean,
5555
TError,
56-
TExternalProps extends UsePickerViewsProps<any, TView, any>,
56+
TExternalProps extends UsePickerProps<PickerRangeValue, TView, TError, any>,
5757
> extends UseRangePickerProps<TView, TError, TExternalProps> {
5858
/**
5959
* Overridable component slots.

packages/x-date-pickers-pro/src/internals/hooks/useMobileRangePicker/useMobileRangePicker.types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { PickerFieldSlotProps, PickerOwnerState } from '@mui/x-date-pickers/mode
33
import {
44
PickersModalDialogSlots,
55
PickersModalDialogSlotProps,
6-
UsePickerViewsProps,
6+
UsePickerProps,
77
DateOrTimeViewWithMeridiem,
88
PickerRangeValue,
99
PickerFieldUISlotsFromContext,
@@ -54,7 +54,7 @@ export interface UseMobileRangePickerProps<
5454
TView extends DateOrTimeViewWithMeridiem,
5555
TEnableAccessibleFieldDOMStructure extends boolean,
5656
TError,
57-
TExternalProps extends UsePickerViewsProps<any, TView, any>,
57+
TExternalProps extends UsePickerProps<PickerRangeValue, TView, TError, any>,
5858
> extends UseRangePickerProps<TView, TError, TExternalProps> {
5959
/**
6060
* Overridable component slots.

packages/x-date-pickers-pro/src/internals/hooks/useStaticRangePicker/useStaticRangePicker.types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
22
BasePickerProps,
3-
UsePickerParams,
3+
UsePickerParameters,
44
ExportedBaseToolbarProps,
55
StaticOnlyPickerProps,
66
DateOrTimeViewWithMeridiem,
@@ -43,7 +43,7 @@ export interface UseStaticRangePickerParams<
4343
TView extends DateOrTimeViewWithMeridiem,
4444
TExternalProps extends UseStaticRangePickerProps<TView, any, TExternalProps>,
4545
> extends Pick<
46-
UsePickerParams<PickerRangeValue, TView, TExternalProps>,
46+
UsePickerParameters<PickerRangeValue, TView, TExternalProps>,
4747
'valueManager' | 'valueType' | 'validator' | 'ref'
4848
> {
4949
props: TExternalProps;

packages/x-date-pickers/src/DatePicker/shared.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
DatePickerToolbarProps,
1818
ExportedDatePickerToolbarProps,
1919
} from './DatePickerToolbar';
20-
import { PickerViewRendererLookup } from '../internals/hooks/usePicker/usePickerViews';
20+
import { PickerViewRendererLookup } from '../internals/hooks/usePicker';
2121
import { DateViewRendererProps } from '../dateViewRenderers';
2222
import { PickerValue } from '../internals/models';
2323
import { ValidateDatePropsToDefault } from '../validation/validateDate';

packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
PickerToolbarOwnerState,
2929
useToolbarOwnerState,
3030
} from '../internals/hooks/useToolbarOwnerState';
31-
import { SetValueActionOptions } from '../internals/hooks/usePicker/usePickerValue.types';
31+
import { SetValueActionOptions } from '../internals/components/PickerProvider';
3232

3333
export interface ExportedDateTimePickerToolbarProps extends ExportedBaseToolbarProps {
3434
/**

packages/x-date-pickers/src/DateTimePicker/shared.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
DateTimePickerToolbarProps,
1919
ExportedDateTimePickerToolbarProps,
2020
} from './DateTimePickerToolbar';
21-
import { PickerViewRendererLookup } from '../internals/hooks/usePicker/usePickerViews';
21+
import { PickerViewRendererLookup } from '../internals/hooks/usePicker';
2222
import { DateViewRendererProps } from '../dateViewRenderers';
2323
import { TimeViewRendererProps } from '../timeViewRenderers';
2424
import { applyDefaultViewProps } from '../internals/utils/views';

packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { VIEW_HEIGHT } from '../internals/constants/dimensions';
3333
import {
3434
PickerRendererInterceptorProps,
3535
PickerViewRendererLookup,
36-
} from '../internals/hooks/usePicker/usePickerViews';
36+
} from '../internals/hooks/usePicker';
3737
import { isInternalTimeView } from '../internals/utils/time-utils';
3838
import { isDatePickerView } from '../internals/utils/date-utils';
3939

packages/x-date-pickers/src/MobileDateTimePicker/MobileDateTimePicker.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { useMobilePicker } from '../internals/hooks/useMobilePicker';
1414
import { renderDateViewCalendar } from '../dateViewRenderers';
1515
import { renderTimeViewClock } from '../timeViewRenderers';
1616
import { resolveDateTimeFormat } from '../internals/utils/date-time-utils';
17-
import { PickerViewRendererLookup } from '../internals/hooks/usePicker/usePickerViews';
17+
import { PickerViewRendererLookup } from '../internals/hooks/usePicker';
1818
import { PickerValue } from '../internals/models';
1919

2020
type MobileDateTimePickerComponent = (<TEnableAccessibleFieldDOMStructure extends boolean = true>(

packages/x-date-pickers/src/StaticDateTimePicker/StaticDateTimePicker.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { singleItemValueManager } from '../internals/utils/valueManagers';
99
import { useStaticPicker } from '../internals/hooks/useStaticPicker';
1010
import { DateOrTimeView } from '../models';
1111
import { validateDateTime } from '../validation';
12-
import { PickerViewRendererLookup } from '../internals/hooks/usePicker/usePickerViews';
12+
import { PickerViewRendererLookup } from '../internals/hooks/usePicker';
1313
import { PickerValue } from '../internals/models';
1414

1515
type StaticDateTimePickerComponent = ((

packages/x-date-pickers/src/TimePicker/shared.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
TimePickerToolbar,
1212
} from './TimePickerToolbar';
1313
import { TimeValidationError } from '../models';
14-
import { PickerViewRendererLookup } from '../internals/hooks/usePicker/usePickerViews';
14+
import { PickerViewRendererLookup } from '../internals/hooks/usePicker';
1515
import { TimeViewRendererProps } from '../timeViewRenderers';
1616
import { applyDefaultViewProps } from '../internals/utils/views';
1717
import { BaseClockProps, ExportedBaseClockProps } from '../internals/models/props/time';

packages/x-date-pickers/src/internals/components/PickerPopper/PickerPopper.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ export function PickerPopper(inProps: PickerPopperProps) {
332332
const { children, placement = 'bottom-start', slots, slotProps, classes: classesProp } = props;
333333

334334
const { open, triggerRef, popupRef, reduceAnimations } = usePickerContext();
335-
const { dismissViews, doesTheCurrentViewHasAnUI, viewContainerRole } = usePickerPrivateContext();
335+
const { dismissViews, getCurrentViewMode, viewContainerRole } = usePickerPrivateContext();
336336

337337
React.useEffect(() => {
338338
function handleKeyDown(nativeEvent: KeyboardEvent) {
@@ -350,7 +350,7 @@ export function PickerPopper(inProps: PickerPopperProps) {
350350

351351
const lastFocusedElementRef = React.useRef<Element | null>(null);
352352
React.useEffect(() => {
353-
if (viewContainerRole === 'tooltip' || !doesTheCurrentViewHasAnUI()) {
353+
if (viewContainerRole === 'tooltip' || getCurrentViewMode() === 'field') {
354354
return;
355355
}
356356

@@ -368,7 +368,7 @@ export function PickerPopper(inProps: PickerPopperProps) {
368368
}
369369
});
370370
}
371-
}, [open, viewContainerRole, doesTheCurrentViewHasAnUI]);
371+
}, [open, viewContainerRole, getCurrentViewMode]);
372372

373373
const classes = useUtilityClasses(classesProp);
374374
const { ownerState: pickerOwnerState, rootRefObject } = usePickerPrivateContext();

packages/x-date-pickers/src/internals/components/PickerProvider.tsx

Lines changed: 142 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as React from 'react';
22
import { SxProps } from '@mui/system';
33
import { Theme } from '@mui/material/styles';
44

5-
import { PickerOwnerState } from '../../models';
5+
import { PickerChangeImportance, PickerOwnerState, PickersTimezone } from '../../models';
66
import { PickersInputLocaleText } from '../../locales';
77
import { LocalizationProvider } from '../../LocalizationProvider';
88
import {
@@ -11,22 +11,13 @@ import {
1111
PickerValidValue,
1212
PickerVariant,
1313
} from '../models';
14-
import type {
15-
UsePickerValueActionsContextValue,
16-
UsePickerValueContextValue,
17-
UsePickerValuePrivateContextValue,
18-
} from '../hooks/usePicker/usePickerValue.types';
19-
import {
20-
UsePickerViewsActionsContextValue,
21-
UsePickerViewsContextValue,
22-
UsePickerViewsPrivateContextValue,
23-
} from '../hooks/usePicker/usePickerViews';
2414
import { IsValidValueContext } from '../../hooks/useIsValidValue';
2515
import {
2616
PickerFieldPrivateContext,
2717
PickerFieldPrivateContextValue,
2818
} from '../hooks/useNullableFieldPrivateContext';
2919
import { PickerContext } from '../../hooks/usePickerContext';
20+
import type { PickersShortcutsItemContext } from '../../PickersShortcuts';
3021

3122
export const PickerActionsContext = React.createContext<PickerActionsContextValue<
3223
any,
@@ -45,7 +36,7 @@ export const PickerPrivateContext = React.createContext<PickerPrivateContextValu
4536
},
4637
dismissViews: () => {},
4738
hasUIView: true,
48-
doesTheCurrentViewHasAnUI: () => true,
39+
getCurrentViewMode: () => 'UI',
4940
rootRefObject: { current: null },
5041
viewContainerRole: null,
5142
labelId: undefined,
@@ -100,8 +91,24 @@ export interface PickerContextValue<
10091
TValue extends PickerValidValue,
10192
TView extends DateOrTimeViewWithMeridiem,
10293
TError,
103-
> extends UsePickerValueContextValue<TValue, TError>,
104-
UsePickerViewsContextValue<TView> {
94+
> extends PickerActionsContextValue<TValue, TView, TError> {
95+
/**
96+
* The current value of the picker.
97+
*/
98+
value: TValue;
99+
/**
100+
* The timezone to use when rendering the dates.
101+
* If a `timezone` prop is provided, it will be used.
102+
* If the `value` prop contains a valid date, its timezone will be used.
103+
* If no `value` prop is provided, but the `defaultValue` contains a valid date, its timezone will be used.
104+
* If no `value` or `defaultValue` is provided, but the `referenceDate` is provided, its timezone will be used.
105+
* Otherwise, the timezone will be the default one of your date library.
106+
*/
107+
timezone: PickersTimezone;
108+
/**
109+
* Whether the picker is open.
110+
*/
111+
open: boolean;
105112
/**
106113
* Whether the picker is disabled.
107114
*/
@@ -116,6 +123,25 @@ export interface PickerContextValue<
116123
* If the picker does not have a field (if it is a static picker) or is not open, the view should be focused.
117124
*/
118125
autoFocus: boolean;
126+
/**
127+
* The views that the picker has to render.
128+
* It is equal to the picker `views` prop—if defined.
129+
* Otherwise, a default set of views is provided based on the component you are using:
130+
* - Date Pickers: ['year', 'day']
131+
* - Time Pickers: ['hours', 'minutes']
132+
* - Date Time Pickers: ['year', 'day', 'hours', 'minutes']
133+
* - Date Range Pickers: ['day']
134+
* - Date Time Range Pickers: ['day', 'hours', 'minutes']
135+
*/
136+
views: readonly TView[];
137+
/**
138+
* The currently rendered view.
139+
*/
140+
view: TView | null;
141+
/**
142+
* The view showed when first opening the picker.
143+
*/
144+
initialView: TView | null;
119145
/**
120146
* The responsive variant of the picker.
121147
* It is equal to "desktop" when using a desktop picker (like <DesktopDatePicker />).
@@ -202,12 +228,87 @@ export interface PickerActionsContextValue<
202228
TValue extends PickerValidValue,
203229
TView extends DateOrTimeViewWithMeridiem,
204230
TError = string | null,
205-
> extends UsePickerValueActionsContextValue<TValue, TError>,
206-
UsePickerViewsActionsContextValue<TView> {}
231+
> {
232+
/**
233+
* Set the current value of the picker.
234+
* @param {TValue} value The new value of the picker.
235+
* @param {SetValueActionOptions<TError>} options The options to customize the behavior of this update.
236+
*/
237+
setValue: (value: TValue, options?: SetValueActionOptions<TError>) => void;
238+
/**
239+
* Set the current open state of the Picker.
240+
* It can be a function that will receive the current open state as parameter.
241+
* ```ts
242+
* setOpen(true); // Opens the picker.
243+
* setOpen(false); // Closes the picker.
244+
* setOpen((prevOpen) => !prevOpen); // Toggles the open state.
245+
* ```
246+
* @param {React.SetStateAction<boolean>} action The new open state of the Picker.
247+
*/
248+
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
249+
/**
250+
* Set the current view.
251+
* @template TView
252+
* @param {TView} view The view to render
253+
*/
254+
setView: (view: TView) => void;
255+
/**
256+
* Set the current value of the picker to be empty.
257+
* The value will be `null` on single pickers and `[null, null]` on range pickers.
258+
*/
259+
clearValue: () => void;
260+
/**
261+
* Set the current value of the picker to be the current date.
262+
* The value will be `today` on single pickers and `[today, today]` on range pickers.
263+
* With `today` being the current date, with its time set to `00:00:00` on Date Pickers and its time set to the current time on Time and Date Pickers.
264+
*/
265+
setValueToToday: () => void;
266+
/**
267+
* Accept the current value of the picker.
268+
* Will call `onAccept` if defined.
269+
* If the picker is re-opened, this value will be the one used to initialize the views.
270+
*/
271+
acceptValueChanges: () => void;
272+
/**
273+
* Cancel the changes made to the current value of the picker.
274+
* The value will be reset to the last accepted value.
275+
*/
276+
cancelValueChanges: () => void;
277+
}
207278

208-
export interface PickerPrivateContextValue
209-
extends UsePickerValuePrivateContextValue,
210-
UsePickerViewsPrivateContextValue {
279+
export interface SetValueActionOptions<TError = string | null> {
280+
/**
281+
* The importance of the change when picking a value:
282+
* - "accept": fires `onChange`, fires `onAccept` and closes the picker.
283+
* - "set": fires `onChange` but do not fire `onAccept` and does not close the picker.
284+
* @default "accept"
285+
*/
286+
changeImportance?: PickerChangeImportance;
287+
/**
288+
* The validation error associated to the current value.
289+
* If not defined, the validation will be computed by the picker.
290+
*/
291+
validationError?: TError;
292+
/**
293+
* The shortcut that triggered this change.
294+
* It should not be defined if the change does not come from a shortcut.
295+
*/
296+
shortcut?: PickersShortcutsItemContext;
297+
/**
298+
* Whether the value should call `onChange` and `onAccept` when the value is not controlled and has never been modified.
299+
* If `true`, the `onChange` and `onAccept` callback will only be fired if the value has been modified (and is not equal to the last published value).
300+
* If `false`, the `onChange` and `onAccept` callback will be fired when the value has never been modified (`onAccept` only if `changeImportance` is set to "accept").
301+
* @default false
302+
*/
303+
skipPublicationIfPristine?: boolean;
304+
/**
305+
* Whether the picker should close.
306+
* @default changeImportance === "accept"
307+
*/
308+
shouldClose?: boolean;
309+
}
310+
311+
export interface PickerPrivateContextValue {
211312
/**
212313
* The ownerState of the picker.
213314
*/
@@ -221,4 +322,26 @@ export interface PickerPrivateContextValue
221322
* The id of the label element.
222323
*/
223324
labelId: string | undefined;
325+
/*
326+
* Close the picker and accepts the current value if it is not equal to the last accepted value.
327+
*/
328+
dismissViews: () => void;
329+
/**
330+
* Whether at least one view has an UI (it has a view renderer associated).
331+
*/
332+
hasUIView: boolean;
333+
/**
334+
* Return the mode of the current view.
335+
* @returns {boolean} The mode of the current view.
336+
*/
337+
getCurrentViewMode: () => 'UI' | 'field';
338+
/**
339+
* The aria role associated with the view container.
340+
* It is equal to "dialog" when the view is rendered inside a `@mui/material/Dialog`.
341+
* It is equal to "dialog" when the view is rendered inside a `@mui/material/Popper` and the focus is trapped inside the view.
342+
* It is equal to "tooltip" when the view is rendered inside a `@mui/material/Popper` and the focus remains inside the field.
343+
* It is always equal to null if the picker does not have a field (static pickers).
344+
* It is always equal to null if the component you are accessing the context from is not wrapped by a picker.
345+
*/
346+
viewContainerRole: 'dialog' | 'tooltip' | null;
224347
}

0 commit comments

Comments
 (0)