@mui/x-date-pickers 7.20.0 → 7.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/AdapterDayjs/AdapterDayjs.js +2 -0
  2. package/CHANGELOG.md +200 -31
  3. package/DateCalendar/DayCalendar.js +3 -4
  4. package/DateCalendar/useCalendarState.d.ts +3 -1
  5. package/DateCalendar/useCalendarState.js +27 -2
  6. package/DigitalClock/DigitalClock.js +10 -12
  7. package/MultiSectionDigitalClock/MultiSectionDigitalClockSection.js +2 -8
  8. package/PickersSectionList/PickersSectionList.d.ts +9 -0
  9. package/PickersSectionList/PickersSectionList.js +30 -9
  10. package/index.js +1 -1
  11. package/internals/hooks/useDesktopPicker/useDesktopPicker.js +3 -7
  12. package/internals/hooks/useDesktopPicker/useDesktopPicker.types.d.ts +2 -5
  13. package/internals/hooks/useField/useField.js +1 -1
  14. package/internals/hooks/usePicker/usePicker.js +8 -1
  15. package/internals/hooks/usePicker/usePicker.types.d.ts +2 -1
  16. package/internals/hooks/usePicker/usePickerOwnerState.d.ts +9 -0
  17. package/internals/hooks/usePicker/usePickerOwnerState.js +13 -0
  18. package/internals/utils/utils.js +2 -2
  19. package/models/pickers.d.ts +18 -0
  20. package/modern/AdapterDayjs/AdapterDayjs.js +2 -0
  21. package/modern/DateCalendar/DayCalendar.js +3 -4
  22. package/modern/DateCalendar/useCalendarState.js +27 -2
  23. package/modern/DigitalClock/DigitalClock.js +10 -12
  24. package/modern/MultiSectionDigitalClock/MultiSectionDigitalClockSection.js +2 -8
  25. package/modern/PickersSectionList/PickersSectionList.js +30 -9
  26. package/modern/index.js +1 -1
  27. package/modern/internals/hooks/useDesktopPicker/useDesktopPicker.js +3 -7
  28. package/modern/internals/hooks/useField/useField.js +1 -1
  29. package/modern/internals/hooks/usePicker/usePicker.js +8 -1
  30. package/modern/internals/hooks/usePicker/usePickerOwnerState.js +13 -0
  31. package/modern/internals/utils/utils.js +2 -2
  32. package/node/AdapterDayjs/AdapterDayjs.js +2 -0
  33. package/node/DateCalendar/DayCalendar.js +3 -4
  34. package/node/DateCalendar/useCalendarState.js +27 -2
  35. package/node/DigitalClock/DigitalClock.js +10 -12
  36. package/node/MultiSectionDigitalClock/MultiSectionDigitalClockSection.js +2 -8
  37. package/node/PickersSectionList/PickersSectionList.js +30 -9
  38. package/node/index.js +1 -1
  39. package/node/internals/hooks/useDesktopPicker/useDesktopPicker.js +3 -7
  40. package/node/internals/hooks/useField/useField.js +1 -1
  41. package/node/internals/hooks/usePicker/usePicker.js +8 -1
  42. package/node/internals/hooks/usePicker/usePickerOwnerState.js +20 -0
  43. package/node/internals/utils/utils.js +2 -2
  44. package/package.json +2 -2
@@ -49,15 +49,6 @@ const useUtilityClasses = ownerState => {
49
49
  };
50
50
  return composeClasses(slots, getPickersSectionListUtilityClass, classes);
51
51
  };
52
- /**
53
- * Demos:
54
- *
55
- * - [Custom field](https://mui.com/x/react-date-pickers/custom-field/)
56
- *
57
- * API:
58
- *
59
- * - [PickersSectionList API](https://mui.com/x/api/date-pickers/pickers-section-list/)
60
- */
61
52
  function PickersSection(props) {
62
53
  const {
63
54
  slots,
@@ -105,6 +96,36 @@ function PickersSection(props) {
105
96
  children: [/*#__PURE__*/_jsx(SectionSeparator, _extends({}, sectionSeparatorBeforeProps)), /*#__PURE__*/_jsx(SectionContent, _extends({}, sectionContentProps)), /*#__PURE__*/_jsx(SectionSeparator, _extends({}, sectionSeparatorAfterProps))]
106
97
  }));
107
98
  }
99
+ process.env.NODE_ENV !== "production" ? PickersSection.propTypes = {
100
+ // ----------------------------- Warning --------------------------------
101
+ // | These PropTypes are generated from the TypeScript type definitions |
102
+ // | To update them edit the TypeScript types and run "pnpm proptypes" |
103
+ // ----------------------------------------------------------------------
104
+ classes: PropTypes.object.isRequired,
105
+ element: PropTypes.shape({
106
+ after: PropTypes.object.isRequired,
107
+ before: PropTypes.object.isRequired,
108
+ container: PropTypes.object.isRequired,
109
+ content: PropTypes.object.isRequired
110
+ }).isRequired,
111
+ /**
112
+ * The props used for each component slot.
113
+ */
114
+ slotProps: PropTypes.object,
115
+ /**
116
+ * Overridable component slots.
117
+ */
118
+ slots: PropTypes.object
119
+ } : void 0;
120
+ /**
121
+ * Demos:
122
+ *
123
+ * - [Custom field](https://mui.com/x/react-date-pickers/custom-field/)
124
+ *
125
+ * API:
126
+ *
127
+ * - [PickersSectionList API](https://mui.com/x/api/date-pickers/pickers-section-list/)
128
+ */
108
129
  const PickersSectionList = /*#__PURE__*/React.forwardRef(function PickersSectionList(inProps, ref) {
109
130
  const props = useThemeProps({
110
131
  props: inProps,
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-date-pickers v7.20.0
2
+ * @mui/x-date-pickers v7.22.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -59,7 +59,8 @@ export const useDesktopPicker = _ref => {
59
59
  renderCurrentView,
60
60
  shouldRestoreFocus,
61
61
  fieldProps: pickerFieldProps,
62
- contextValue
62
+ contextValue,
63
+ ownerState
63
64
  } = usePicker(_extends({}, pickerParams, {
64
65
  props,
65
66
  fieldRef,
@@ -67,11 +68,6 @@ export const useDesktopPicker = _ref => {
67
68
  additionalViewProps: {},
68
69
  wrapperVariant: 'desktop'
69
70
  }));
70
-
71
- // TODO v8: Apply this ownerState to all the slots in this hook.
72
- const ownerStateV8 = {
73
- open
74
- };
75
71
  const InputAdornment = slots.inputAdornment ?? MuiInputAdornment;
76
72
  const _useSlotProps = useSlotProps({
77
73
  elementType: InputAdornment,
@@ -99,7 +95,7 @@ export const useDesktopPicker = _ref => {
99
95
  const openPickerIconProps = useSlotProps({
100
96
  elementType: OpenPickerIcon,
101
97
  externalSlotProps: innerSlotProps?.openPickerIcon,
102
- ownerState: ownerStateV8
98
+ ownerState
103
99
  });
104
100
  const Field = slots.field;
105
101
  const fieldProps = useSlotProps({
@@ -6,7 +6,7 @@ import { SlotComponentProps } from '@mui/utils';
6
6
  import { BaseNonStaticPickerProps, BasePickerProps, BaseNonRangeNonStaticPickerProps } from '../../models/props/basePickerProps';
7
7
  import { PickersPopperSlots, PickersPopperSlotProps } from '../../components/PickersPopper';
8
8
  import { UsePickerParams, UsePickerProps } from '../usePicker';
9
- import { BaseSingleInputFieldProps, FieldSection, PickerValidDate } from '../../../models';
9
+ import { BaseSingleInputFieldProps, FieldSection, PickerOwnerState, PickerValidDate } from '../../../models';
10
10
  import { ExportedPickersLayoutSlots, ExportedPickersLayoutSlotProps, PickersLayoutSlotProps } from '../../../PickersLayout/PickersLayout.types';
11
11
  import { UsePickerValueNonStaticProps } from '../usePicker/usePickerValue.types';
12
12
  import { UsePickerViewsNonStaticProps, UsePickerViewsProps } from '../usePicker/usePickerViews';
@@ -40,15 +40,12 @@ export interface UseDesktopPickerSlots<TDate extends PickerValidDate, TView exte
40
40
  }
41
41
  export interface UseDesktopPickerSlotProps<TDate extends PickerValidDate, TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean> extends ExportedUseDesktopPickerSlotProps<TDate, TView, TEnableAccessibleFieldDOMStructure>, Pick<PickersLayoutSlotProps<TDate | null, TDate, TView>, 'toolbar'> {
42
42
  }
43
- export interface UseDesktopPickerOwnerState {
44
- open: boolean;
45
- }
46
43
  export interface ExportedUseDesktopPickerSlotProps<TDate extends PickerValidDate, TView extends DateOrTimeViewWithMeridiem, TEnableAccessibleFieldDOMStructure extends boolean> extends PickersPopperSlotProps, ExportedPickersLayoutSlotProps<TDate | null, TDate, TView>, UseClearableFieldSlotProps {
47
44
  field?: SlotComponentPropsFromProps<BaseSingleInputFieldProps<TDate | null, TDate, FieldSection, TEnableAccessibleFieldDOMStructure, unknown>, {}, UsePickerProps<TDate | null, TDate, any, any, any, any>>;
48
45
  textField?: SlotComponentProps<typeof TextField, {}, Record<string, any>>;
49
46
  inputAdornment?: Partial<InputAdornmentProps>;
50
47
  openPickerButton?: SlotComponentProps<typeof IconButton, {}, UseDesktopPickerProps<TDate, any, TEnableAccessibleFieldDOMStructure, any, any>>;
51
- openPickerIcon?: SlotComponentPropsFromProps<Record<string, any>, {}, UseDesktopPickerOwnerState>;
48
+ openPickerIcon?: SlotComponentPropsFromProps<Record<string, any>, {}, PickerOwnerState<TDate | null>>;
52
49
  }
53
50
  export interface DesktopOnlyPickerProps extends BaseNonStaticPickerProps, BaseNonRangeNonStaticPickerProps, UsePickerValueNonStaticProps, UsePickerViewsNonStaticProps {
54
51
  /**
@@ -75,7 +75,7 @@ export const useField = params => {
75
75
  // eslint-disable-next-line default-case
76
76
  switch (true) {
77
77
  // Select all
78
- case (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'a' && !event.shiftKey && !event.altKey:
78
+ case (event.ctrlKey || event.metaKey) && String.fromCharCode(event.keyCode) === 'A' && !event.shiftKey && !event.altKey:
79
79
  {
80
80
  // prevent default to make sure that the next line "select all" while updating
81
81
  // the internal state at the same time.
@@ -2,6 +2,7 @@ import { warnOnce } from '@mui/x-internals/warning';
2
2
  import { usePickerValue } from "./usePickerValue.js";
3
3
  import { usePickerViews } from "./usePickerViews.js";
4
4
  import { usePickerLayoutProps } from "./usePickerLayoutProps.js";
5
+ import { usePickerOwnerState } from "./usePickerOwnerState.js";
5
6
  export const usePicker = ({
6
7
  props,
7
8
  valueManager,
@@ -39,6 +40,10 @@ export const usePicker = ({
39
40
  propsFromPickerValue: pickerValueResponse.layoutProps,
40
41
  propsFromPickerViews: pickerViewsResponse.layoutProps
41
42
  });
43
+ const pickerOwnerState = usePickerOwnerState({
44
+ props,
45
+ pickerValueResponse
46
+ });
42
47
  return {
43
48
  // Picker value
44
49
  open: pickerValueResponse.open,
@@ -51,6 +56,8 @@ export const usePicker = ({
51
56
  // Picker layout
52
57
  layoutProps: pickerLayoutResponse.layoutProps,
53
58
  // Picker context
54
- contextValue: pickerValueResponse.contextValue
59
+ contextValue: pickerValueResponse.contextValue,
60
+ // Picker owner state
61
+ ownerState: pickerOwnerState
55
62
  };
56
63
  };
@@ -1,7 +1,7 @@
1
1
  import { UsePickerValueParams, UsePickerValueProps, UsePickerValueBaseProps, UsePickerValueResponse } from './usePickerValue.types';
2
2
  import { UsePickerViewsProps, UsePickerViewParams, UsePickerViewsResponse, UsePickerViewsBaseProps } from './usePickerViews';
3
3
  import { UsePickerLayoutProps, UsePickerLayoutPropsResponse } from './usePickerLayoutProps';
4
- import { FieldSection, PickerValidDate } from '../../../models';
4
+ import { FieldSection, PickerOwnerState, PickerValidDate } from '../../../models';
5
5
  import { DateOrTimeViewWithMeridiem } from '../../models';
6
6
  /**
7
7
  * Props common to all picker headless implementations.
@@ -14,4 +14,5 @@ export interface UsePickerParams<TValue, TDate extends PickerValidDate, TView ex
14
14
  props: TExternalProps;
15
15
  }
16
16
  export interface UsePickerResponse<TValue, TView extends DateOrTimeViewWithMeridiem, TSection extends FieldSection, TError> extends Omit<UsePickerValueResponse<TValue, TSection, TError>, 'viewProps' | 'layoutProps'>, Omit<UsePickerViewsResponse<TView>, 'layoutProps'>, UsePickerLayoutPropsResponse<TValue, TView> {
17
+ ownerState: PickerOwnerState<TValue>;
17
18
  }
@@ -0,0 +1,9 @@
1
+ import { FieldSection, PickerOwnerState } from '../../../models';
2
+ import type { UsePickerProps } from './usePicker.types';
3
+ import { UsePickerValueResponse } from './usePickerValue.types';
4
+ interface UsePickerOwnerStateParameters<TValue> {
5
+ props: UsePickerProps<TValue, any, any, any, any, any>;
6
+ pickerValueResponse: UsePickerValueResponse<TValue, FieldSection, any>;
7
+ }
8
+ export declare function usePickerOwnerState<TValue>(parameters: UsePickerOwnerStateParameters<TValue>): PickerOwnerState<TValue>;
9
+ export {};
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+ export function usePickerOwnerState(parameters) {
3
+ const {
4
+ props,
5
+ pickerValueResponse
6
+ } = parameters;
7
+ return React.useMemo(() => ({
8
+ value: pickerValueResponse.viewProps.value,
9
+ open: pickerValueResponse.open,
10
+ disabled: props.disabled ?? false,
11
+ readOnly: props.readOnly ?? false
12
+ }), [pickerValueResponse.viewProps.value, pickerValueResponse.open, props.disabled, props.readOnly]);
13
+ }
@@ -40,7 +40,7 @@ export const getActiveElement = (root = document) => {
40
40
  * @returns {number} The index of the focused list item, or -1 if none is focused.
41
41
  */
42
42
  export const getFocusedListItemIndex = listElement => {
43
- const children = listElement.children;
44
- return Array.from(children).findIndex(child => child === getActiveElement(document));
43
+ const children = Array.from(listElement.children);
44
+ return children.indexOf(getActiveElement(document));
45
45
  };
46
46
  export const DEFAULT_DESKTOP_MODE_MEDIA_QUERY = '@media (pointer: fine)';
@@ -10,3 +10,21 @@ export interface PickerChangeHandlerContext<TError> {
10
10
  export interface PickerValidDateLookup {
11
11
  }
12
12
  export type PickerValidDate = keyof PickerValidDateLookup extends never ? any : PickerValidDateLookup[keyof PickerValidDateLookup];
13
+ export interface PickerOwnerState<TValue> {
14
+ /**
15
+ * The value currently displayed in the field and in the view.
16
+ */
17
+ value: TValue;
18
+ /**
19
+ * `true` if the picker is open, `false` otherwise.
20
+ */
21
+ open: boolean;
22
+ /**
23
+ * `true` if the picker is disabled, `false` otherwise.
24
+ */
25
+ disabled: boolean;
26
+ /**
27
+ * `true` if the picker is read-only, `false` otherwise.
28
+ */
29
+ readOnly: boolean;
30
+ }
@@ -254,6 +254,8 @@ export class AdapterDayjs {
254
254
  const timezone = this.getTimezone(value);
255
255
  if (timezone !== 'UTC') {
256
256
  const fixedValue = value.tz(this.cleanTimezone(timezone), true);
257
+ // TODO: Simplify the case when we raise the `dayjs` peer dep to 1.11.12 (https://github.com/iamkun/dayjs/releases/tag/v1.11.12)
258
+ /* istanbul ignore next */
257
259
  // @ts-ignore
258
260
  if (fixedValue.$offset === (value.$offset ?? 0)) {
259
261
  return value;
@@ -378,9 +378,8 @@ export function DayCalendar(inProps) {
378
378
  return internalFocusedDay;
379
379
  }, [currentMonth, disableFuture, disablePast, internalFocusedDay, isDateDisabled, utils, timezone]);
380
380
  const weeksToDisplay = React.useMemo(() => {
381
- const currentMonthWithTimezone = utils.setTimezone(currentMonth, timezone);
382
- const toDisplay = utils.getWeekArray(currentMonthWithTimezone);
383
- let nextMonth = utils.addMonths(currentMonthWithTimezone, 1);
381
+ const toDisplay = utils.getWeekArray(currentMonth);
382
+ let nextMonth = utils.addMonths(currentMonth, 1);
384
383
  while (fixedWeekNumber && toDisplay.length < fixedWeekNumber) {
385
384
  const additionalWeeks = utils.getWeekArray(nextMonth);
386
385
  const hasCommonWeek = utils.isSameDay(toDisplay[toDisplay.length - 1][0], additionalWeeks[0][0]);
@@ -392,7 +391,7 @@ export function DayCalendar(inProps) {
392
391
  nextMonth = utils.addMonths(nextMonth, 1);
393
392
  }
394
393
  return toDisplay;
395
- }, [currentMonth, fixedWeekNumber, utils, timezone]);
394
+ }, [currentMonth, fixedWeekNumber, utils]);
396
395
  return /*#__PURE__*/_jsxs(PickersCalendarDayRoot, {
397
396
  role: "grid",
398
397
  "aria-labelledby": gridLabelId,
@@ -15,6 +15,20 @@ export const createCalendarStateReducer = (reduceAnimations, disableSwitchToMont
15
15
  currentMonth: action.newMonth,
16
16
  isMonthSwitchingAnimating: !reduceAnimations
17
17
  });
18
+ case 'changeMonthTimezone':
19
+ {
20
+ const newTimezone = action.newTimezone;
21
+ if (utils.getTimezone(state.currentMonth) === newTimezone) {
22
+ return state;
23
+ }
24
+ let newCurrentMonth = utils.setTimezone(state.currentMonth, newTimezone);
25
+ if (utils.getMonth(newCurrentMonth) !== utils.getMonth(state.currentMonth)) {
26
+ newCurrentMonth = utils.setMonth(newCurrentMonth, utils.getMonth(state.currentMonth));
27
+ }
28
+ return _extends({}, state, {
29
+ currentMonth: newCurrentMonth
30
+ });
31
+ }
18
32
  case 'finishMonthSwitchingAnimation':
19
33
  return _extends({}, state, {
20
34
  isMonthSwitchingAnimating: false
@@ -61,14 +75,25 @@ export const useCalendarState = params => {
61
75
  referenceDate: referenceDateProp,
62
76
  granularity: SECTION_TYPE_GRANULARITY.day
63
77
  });
64
- }, [] // eslint-disable-line react-hooks/exhaustive-deps
65
- );
78
+ },
79
+ // We want the `referenceDate` to update on prop and `timezone` change (https://github.com/mui/mui-x/issues/10804)
80
+ // eslint-disable-next-line react-hooks/exhaustive-deps
81
+ [referenceDateProp, timezone]);
66
82
  const [calendarState, dispatch] = React.useReducer(reducerFn, {
67
83
  isMonthSwitchingAnimating: false,
68
84
  focusedDay: referenceDate,
69
85
  currentMonth: utils.startOfMonth(referenceDate),
70
86
  slideDirection: 'left'
71
87
  });
88
+
89
+ // Ensure that `calendarState.currentMonth` timezone is updated when `referenceDate` (or timezone changes)
90
+ // https://github.com/mui/mui-x/issues/10804
91
+ React.useEffect(() => {
92
+ dispatch({
93
+ type: 'changeMonthTimezone',
94
+ newTimezone: utils.getTimezone(referenceDate)
95
+ });
96
+ }, [referenceDate, utils]);
72
97
  const handleChangeMonth = React.useCallback(payload => {
73
98
  dispatch(_extends({
74
99
  type: 'changeMonth'
@@ -232,21 +232,22 @@ export const DigitalClock = /*#__PURE__*/React.forwardRef(function DigitalClock(
232
232
  return !containsValidTime() || !isValidValue();
233
233
  }, [disableIgnoringDatePartForTimeValidation, utils, minTime, maxTime, disableFuture, now, disablePast, minutesStep, shouldDisableTime]);
234
234
  const timeOptions = React.useMemo(() => {
235
+ const result = [];
235
236
  const startOfDay = utils.startOfDay(valueOrReferenceDate);
236
- return [startOfDay, ...Array.from({
237
- length: Math.ceil(24 * 60 / timeStep) - 1
238
- }, (_, index) => utils.addMinutes(startOfDay, timeStep * (index + 1)))];
237
+ let nextTimeStepOption = startOfDay;
238
+ while (utils.isSameDay(valueOrReferenceDate, nextTimeStepOption)) {
239
+ result.push(nextTimeStepOption);
240
+ nextTimeStepOption = utils.addMinutes(nextTimeStepOption, timeStep);
241
+ }
242
+ return result;
239
243
  }, [valueOrReferenceDate, timeStep, utils]);
240
244
  const focusedOptionIndex = timeOptions.findIndex(option => utils.isEqual(option, valueOrReferenceDate));
241
245
  const handleKeyDown = event => {
242
246
  switch (event.key) {
243
247
  case 'PageUp':
244
248
  {
245
- if (!listRef.current) {
246
- return;
247
- }
248
249
  const newIndex = getFocusedListItemIndex(listRef.current) - 5;
249
- const children = listRef.current?.children;
250
+ const children = listRef.current.children;
250
251
  const newFocusedIndex = Math.max(0, newIndex);
251
252
  const childToFocus = children[newFocusedIndex];
252
253
  if (childToFocus) {
@@ -257,11 +258,8 @@ export const DigitalClock = /*#__PURE__*/React.forwardRef(function DigitalClock(
257
258
  }
258
259
  case 'PageDown':
259
260
  {
260
- if (!listRef.current) {
261
- return;
262
- }
263
261
  const newIndex = getFocusedListItemIndex(listRef.current) + 5;
264
- const children = listRef.current?.children;
262
+ const children = listRef.current.children;
265
263
  const newFocusedIndex = Math.min(children.length - 1, newIndex);
266
264
  const childToFocus = children[newFocusedIndex];
267
265
  if (childToFocus) {
@@ -304,7 +302,7 @@ export const DigitalClock = /*#__PURE__*/React.forwardRef(function DigitalClock(
304
302
  tabIndex: tabIndex
305
303
  }, clockItemProps, {
306
304
  children: formattedValue
307
- }), formattedValue);
305
+ }), `${option.valueOf()}-${formattedValue}`);
308
306
  })
309
307
  })
310
308
  }));
@@ -143,11 +143,8 @@ export const MultiSectionDigitalClockSection = /*#__PURE__*/React.forwardRef(fun
143
143
  switch (event.key) {
144
144
  case 'PageUp':
145
145
  {
146
- if (!containerRef.current) {
147
- return;
148
- }
149
146
  const newIndex = getFocusedListItemIndex(containerRef.current) - 5;
150
- const children = containerRef.current?.children;
147
+ const children = containerRef.current.children;
151
148
  const newFocusedIndex = Math.max(0, newIndex);
152
149
  const childToFocus = children[newFocusedIndex];
153
150
  if (childToFocus) {
@@ -158,11 +155,8 @@ export const MultiSectionDigitalClockSection = /*#__PURE__*/React.forwardRef(fun
158
155
  }
159
156
  case 'PageDown':
160
157
  {
161
- if (!containerRef.current) {
162
- return;
163
- }
164
158
  const newIndex = getFocusedListItemIndex(containerRef.current) + 5;
165
- const children = containerRef.current?.children;
159
+ const children = containerRef.current.children;
166
160
  const newFocusedIndex = Math.min(children.length - 1, newIndex);
167
161
  const childToFocus = children[newFocusedIndex];
168
162
  if (childToFocus) {
@@ -49,15 +49,6 @@ const useUtilityClasses = ownerState => {
49
49
  };
50
50
  return composeClasses(slots, getPickersSectionListUtilityClass, classes);
51
51
  };
52
- /**
53
- * Demos:
54
- *
55
- * - [Custom field](https://mui.com/x/react-date-pickers/custom-field/)
56
- *
57
- * API:
58
- *
59
- * - [PickersSectionList API](https://mui.com/x/api/date-pickers/pickers-section-list/)
60
- */
61
52
  function PickersSection(props) {
62
53
  const {
63
54
  slots,
@@ -105,6 +96,36 @@ function PickersSection(props) {
105
96
  children: [/*#__PURE__*/_jsx(SectionSeparator, _extends({}, sectionSeparatorBeforeProps)), /*#__PURE__*/_jsx(SectionContent, _extends({}, sectionContentProps)), /*#__PURE__*/_jsx(SectionSeparator, _extends({}, sectionSeparatorAfterProps))]
106
97
  }));
107
98
  }
99
+ process.env.NODE_ENV !== "production" ? PickersSection.propTypes = {
100
+ // ----------------------------- Warning --------------------------------
101
+ // | These PropTypes are generated from the TypeScript type definitions |
102
+ // | To update them edit the TypeScript types and run "pnpm proptypes" |
103
+ // ----------------------------------------------------------------------
104
+ classes: PropTypes.object.isRequired,
105
+ element: PropTypes.shape({
106
+ after: PropTypes.object.isRequired,
107
+ before: PropTypes.object.isRequired,
108
+ container: PropTypes.object.isRequired,
109
+ content: PropTypes.object.isRequired
110
+ }).isRequired,
111
+ /**
112
+ * The props used for each component slot.
113
+ */
114
+ slotProps: PropTypes.object,
115
+ /**
116
+ * Overridable component slots.
117
+ */
118
+ slots: PropTypes.object
119
+ } : void 0;
120
+ /**
121
+ * Demos:
122
+ *
123
+ * - [Custom field](https://mui.com/x/react-date-pickers/custom-field/)
124
+ *
125
+ * API:
126
+ *
127
+ * - [PickersSectionList API](https://mui.com/x/api/date-pickers/pickers-section-list/)
128
+ */
108
129
  const PickersSectionList = /*#__PURE__*/React.forwardRef(function PickersSectionList(inProps, ref) {
109
130
  const props = useThemeProps({
110
131
  props: inProps,
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-date-pickers v7.20.0
2
+ * @mui/x-date-pickers v7.22.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -59,7 +59,8 @@ export const useDesktopPicker = _ref => {
59
59
  renderCurrentView,
60
60
  shouldRestoreFocus,
61
61
  fieldProps: pickerFieldProps,
62
- contextValue
62
+ contextValue,
63
+ ownerState
63
64
  } = usePicker(_extends({}, pickerParams, {
64
65
  props,
65
66
  fieldRef,
@@ -67,11 +68,6 @@ export const useDesktopPicker = _ref => {
67
68
  additionalViewProps: {},
68
69
  wrapperVariant: 'desktop'
69
70
  }));
70
-
71
- // TODO v8: Apply this ownerState to all the slots in this hook.
72
- const ownerStateV8 = {
73
- open
74
- };
75
71
  const InputAdornment = slots.inputAdornment ?? MuiInputAdornment;
76
72
  const _useSlotProps = useSlotProps({
77
73
  elementType: InputAdornment,
@@ -99,7 +95,7 @@ export const useDesktopPicker = _ref => {
99
95
  const openPickerIconProps = useSlotProps({
100
96
  elementType: OpenPickerIcon,
101
97
  externalSlotProps: innerSlotProps?.openPickerIcon,
102
- ownerState: ownerStateV8
98
+ ownerState
103
99
  });
104
100
  const Field = slots.field;
105
101
  const fieldProps = useSlotProps({
@@ -75,7 +75,7 @@ export const useField = params => {
75
75
  // eslint-disable-next-line default-case
76
76
  switch (true) {
77
77
  // Select all
78
- case (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'a' && !event.shiftKey && !event.altKey:
78
+ case (event.ctrlKey || event.metaKey) && String.fromCharCode(event.keyCode) === 'A' && !event.shiftKey && !event.altKey:
79
79
  {
80
80
  // prevent default to make sure that the next line "select all" while updating
81
81
  // the internal state at the same time.
@@ -2,6 +2,7 @@ import { warnOnce } from '@mui/x-internals/warning';
2
2
  import { usePickerValue } from "./usePickerValue.js";
3
3
  import { usePickerViews } from "./usePickerViews.js";
4
4
  import { usePickerLayoutProps } from "./usePickerLayoutProps.js";
5
+ import { usePickerOwnerState } from "./usePickerOwnerState.js";
5
6
  export const usePicker = ({
6
7
  props,
7
8
  valueManager,
@@ -39,6 +40,10 @@ export const usePicker = ({
39
40
  propsFromPickerValue: pickerValueResponse.layoutProps,
40
41
  propsFromPickerViews: pickerViewsResponse.layoutProps
41
42
  });
43
+ const pickerOwnerState = usePickerOwnerState({
44
+ props,
45
+ pickerValueResponse
46
+ });
42
47
  return {
43
48
  // Picker value
44
49
  open: pickerValueResponse.open,
@@ -51,6 +56,8 @@ export const usePicker = ({
51
56
  // Picker layout
52
57
  layoutProps: pickerLayoutResponse.layoutProps,
53
58
  // Picker context
54
- contextValue: pickerValueResponse.contextValue
59
+ contextValue: pickerValueResponse.contextValue,
60
+ // Picker owner state
61
+ ownerState: pickerOwnerState
55
62
  };
56
63
  };
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+ export function usePickerOwnerState(parameters) {
3
+ const {
4
+ props,
5
+ pickerValueResponse
6
+ } = parameters;
7
+ return React.useMemo(() => ({
8
+ value: pickerValueResponse.viewProps.value,
9
+ open: pickerValueResponse.open,
10
+ disabled: props.disabled ?? false,
11
+ readOnly: props.readOnly ?? false
12
+ }), [pickerValueResponse.viewProps.value, pickerValueResponse.open, props.disabled, props.readOnly]);
13
+ }
@@ -40,7 +40,7 @@ export const getActiveElement = (root = document) => {
40
40
  * @returns {number} The index of the focused list item, or -1 if none is focused.
41
41
  */
42
42
  export const getFocusedListItemIndex = listElement => {
43
- const children = listElement.children;
44
- return Array.from(children).findIndex(child => child === getActiveElement(document));
43
+ const children = Array.from(listElement.children);
44
+ return children.indexOf(getActiveElement(document));
45
45
  };
46
46
  export const DEFAULT_DESKTOP_MODE_MEDIA_QUERY = '@media (pointer: fine)';
@@ -262,6 +262,8 @@ class AdapterDayjs {
262
262
  const timezone = this.getTimezone(value);
263
263
  if (timezone !== 'UTC') {
264
264
  const fixedValue = value.tz(this.cleanTimezone(timezone), true);
265
+ // TODO: Simplify the case when we raise the `dayjs` peer dep to 1.11.12 (https://github.com/iamkun/dayjs/releases/tag/v1.11.12)
266
+ /* istanbul ignore next */
265
267
  // @ts-ignore
266
268
  if (fixedValue.$offset === (value.$offset ?? 0)) {
267
269
  return value;
@@ -386,9 +386,8 @@ function DayCalendar(inProps) {
386
386
  return internalFocusedDay;
387
387
  }, [currentMonth, disableFuture, disablePast, internalFocusedDay, isDateDisabled, utils, timezone]);
388
388
  const weeksToDisplay = React.useMemo(() => {
389
- const currentMonthWithTimezone = utils.setTimezone(currentMonth, timezone);
390
- const toDisplay = utils.getWeekArray(currentMonthWithTimezone);
391
- let nextMonth = utils.addMonths(currentMonthWithTimezone, 1);
389
+ const toDisplay = utils.getWeekArray(currentMonth);
390
+ let nextMonth = utils.addMonths(currentMonth, 1);
392
391
  while (fixedWeekNumber && toDisplay.length < fixedWeekNumber) {
393
392
  const additionalWeeks = utils.getWeekArray(nextMonth);
394
393
  const hasCommonWeek = utils.isSameDay(toDisplay[toDisplay.length - 1][0], additionalWeeks[0][0]);
@@ -400,7 +399,7 @@ function DayCalendar(inProps) {
400
399
  nextMonth = utils.addMonths(nextMonth, 1);
401
400
  }
402
401
  return toDisplay;
403
- }, [currentMonth, fixedWeekNumber, utils, timezone]);
402
+ }, [currentMonth, fixedWeekNumber, utils]);
404
403
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(PickersCalendarDayRoot, {
405
404
  role: "grid",
406
405
  "aria-labelledby": gridLabelId,
@@ -22,6 +22,20 @@ const createCalendarStateReducer = (reduceAnimations, disableSwitchToMonthOnDayF
22
22
  currentMonth: action.newMonth,
23
23
  isMonthSwitchingAnimating: !reduceAnimations
24
24
  });
25
+ case 'changeMonthTimezone':
26
+ {
27
+ const newTimezone = action.newTimezone;
28
+ if (utils.getTimezone(state.currentMonth) === newTimezone) {
29
+ return state;
30
+ }
31
+ let newCurrentMonth = utils.setTimezone(state.currentMonth, newTimezone);
32
+ if (utils.getMonth(newCurrentMonth) !== utils.getMonth(state.currentMonth)) {
33
+ newCurrentMonth = utils.setMonth(newCurrentMonth, utils.getMonth(state.currentMonth));
34
+ }
35
+ return (0, _extends2.default)({}, state, {
36
+ currentMonth: newCurrentMonth
37
+ });
38
+ }
25
39
  case 'finishMonthSwitchingAnimation':
26
40
  return (0, _extends2.default)({}, state, {
27
41
  isMonthSwitchingAnimating: false
@@ -69,14 +83,25 @@ const useCalendarState = params => {
69
83
  referenceDate: referenceDateProp,
70
84
  granularity: _getDefaultReferenceDate.SECTION_TYPE_GRANULARITY.day
71
85
  });
72
- }, [] // eslint-disable-line react-hooks/exhaustive-deps
73
- );
86
+ },
87
+ // We want the `referenceDate` to update on prop and `timezone` change (https://github.com/mui/mui-x/issues/10804)
88
+ // eslint-disable-next-line react-hooks/exhaustive-deps
89
+ [referenceDateProp, timezone]);
74
90
  const [calendarState, dispatch] = React.useReducer(reducerFn, {
75
91
  isMonthSwitchingAnimating: false,
76
92
  focusedDay: referenceDate,
77
93
  currentMonth: utils.startOfMonth(referenceDate),
78
94
  slideDirection: 'left'
79
95
  });
96
+
97
+ // Ensure that `calendarState.currentMonth` timezone is updated when `referenceDate` (or timezone changes)
98
+ // https://github.com/mui/mui-x/issues/10804
99
+ React.useEffect(() => {
100
+ dispatch({
101
+ type: 'changeMonthTimezone',
102
+ newTimezone: utils.getTimezone(referenceDate)
103
+ });
104
+ }, [referenceDate, utils]);
80
105
  const handleChangeMonth = React.useCallback(payload => {
81
106
  dispatch((0, _extends2.default)({
82
107
  type: 'changeMonth'