@mui/x-date-pickers 6.18.6 → 6.18.7

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 (34) hide show
  1. package/AdapterLuxon/AdapterLuxon.d.ts +32 -32
  2. package/CHANGELOG.md +43 -1
  3. package/DateCalendar/DateCalendar.js +6 -4
  4. package/DateCalendar/DateCalendar.types.d.ts +0 -8
  5. package/DigitalClock/DigitalClock.js +3 -2
  6. package/MultiSectionDigitalClock/MultiSectionDigitalClock.js +9 -13
  7. package/MultiSectionDigitalClock/MultiSectionDigitalClockSection.js +8 -12
  8. package/TimeClock/TimeClock.js +3 -2
  9. package/index.js +1 -1
  10. package/internals/hooks/useViews.d.ts +4 -4
  11. package/internals/hooks/useViews.js +13 -13
  12. package/internals/models/props/clock.d.ts +0 -9
  13. package/legacy/DateCalendar/DateCalendar.js +6 -4
  14. package/legacy/DigitalClock/DigitalClock.js +3 -2
  15. package/legacy/MultiSectionDigitalClock/MultiSectionDigitalClock.js +9 -13
  16. package/legacy/MultiSectionDigitalClock/MultiSectionDigitalClockSection.js +8 -12
  17. package/legacy/TimeClock/TimeClock.js +3 -2
  18. package/legacy/index.js +1 -1
  19. package/legacy/internals/hooks/useViews.js +13 -13
  20. package/modern/DateCalendar/DateCalendar.js +6 -4
  21. package/modern/DigitalClock/DigitalClock.js +3 -2
  22. package/modern/MultiSectionDigitalClock/MultiSectionDigitalClock.js +9 -13
  23. package/modern/MultiSectionDigitalClock/MultiSectionDigitalClockSection.js +8 -12
  24. package/modern/TimeClock/TimeClock.js +3 -2
  25. package/modern/index.js +1 -1
  26. package/modern/internals/hooks/useViews.js +13 -13
  27. package/node/DateCalendar/DateCalendar.js +6 -4
  28. package/node/DigitalClock/DigitalClock.js +3 -2
  29. package/node/MultiSectionDigitalClock/MultiSectionDigitalClock.js +9 -13
  30. package/node/MultiSectionDigitalClock/MultiSectionDigitalClockSection.js +8 -12
  31. package/node/TimeClock/TimeClock.js +3 -2
  32. package/node/index.js +1 -1
  33. package/node/internals/hooks/useViews.js +13 -13
  34. package/package.json +1 -1
@@ -38,14 +38,14 @@ export declare class AdapterLuxon implements MuiPickersAdapter<DateTime, string>
38
38
  formatTokenMap: FieldFormatTokenMap;
39
39
  constructor({ locale, formats }?: AdapterOptions<string, never>);
40
40
  private setLocaleToValue;
41
- date: (value?: any) => DateTime | null;
42
- dateWithTimezone: <T extends string | null | undefined>(value: T, timezone: PickersTimezone) => DateBuilderReturnType<T, DateTime>;
41
+ date: (value?: any) => DateTime<true> | DateTime<false> | null;
42
+ dateWithTimezone: <T extends string | null | undefined>(value: T, timezone: PickersTimezone) => DateBuilderReturnType<T, DateTime<boolean>>;
43
43
  getTimezone: (value: DateTime) => string;
44
44
  setTimezone: (value: DateTime, timezone: PickersTimezone) => DateTime;
45
45
  toJsDate: (value: DateTime) => Date;
46
- parseISO: (isoString: string) => DateTime;
46
+ parseISO: (isoString: string) => DateTime<true> | DateTime<false>;
47
47
  toISO: (value: DateTime) => string;
48
- parse: (value: string, formatString: string) => DateTime | null;
48
+ parse: (value: string, formatString: string) => DateTime<true> | DateTime<false> | null;
49
49
  getCurrentLocaleCode: () => string;
50
50
  is12HourCycleInCurrentLocale: () => boolean;
51
51
  expandFormat: (format: string) => string;
@@ -68,21 +68,21 @@ export declare class AdapterLuxon implements MuiPickersAdapter<DateTime, string>
68
68
  isBeforeYear: (value: DateTime, comparing: DateTime) => boolean;
69
69
  isBeforeDay: (value: DateTime, comparing: DateTime) => boolean;
70
70
  isWithinRange: (value: DateTime, [start, end]: [DateTime, DateTime]) => boolean;
71
- startOfYear: (value: DateTime) => DateTime;
72
- startOfMonth: (value: DateTime) => DateTime;
73
- startOfWeek: (value: DateTime) => DateTime;
74
- startOfDay: (value: DateTime) => DateTime;
75
- endOfYear: (value: DateTime) => DateTime;
76
- endOfMonth: (value: DateTime) => DateTime;
77
- endOfWeek: (value: DateTime) => DateTime;
78
- endOfDay: (value: DateTime) => DateTime;
79
- addYears: (value: DateTime, amount: number) => DateTime;
80
- addMonths: (value: DateTime, amount: number) => DateTime;
81
- addWeeks: (value: DateTime, amount: number) => DateTime;
82
- addDays: (value: DateTime, amount: number) => DateTime;
83
- addHours: (value: DateTime, amount: number) => DateTime;
84
- addMinutes: (value: DateTime, amount: number) => DateTime;
85
- addSeconds: (value: DateTime, amount: number) => DateTime;
71
+ startOfYear: (value: DateTime) => DateTime<boolean>;
72
+ startOfMonth: (value: DateTime) => DateTime<boolean>;
73
+ startOfWeek: (value: DateTime) => DateTime<boolean>;
74
+ startOfDay: (value: DateTime) => DateTime<boolean>;
75
+ endOfYear: (value: DateTime) => DateTime<boolean>;
76
+ endOfMonth: (value: DateTime) => DateTime<boolean>;
77
+ endOfWeek: (value: DateTime) => DateTime<boolean>;
78
+ endOfDay: (value: DateTime) => DateTime<boolean>;
79
+ addYears: (value: DateTime, amount: number) => DateTime<boolean>;
80
+ addMonths: (value: DateTime, amount: number) => DateTime<boolean>;
81
+ addWeeks: (value: DateTime, amount: number) => DateTime<boolean>;
82
+ addDays: (value: DateTime, amount: number) => DateTime<boolean>;
83
+ addHours: (value: DateTime, amount: number) => DateTime<boolean>;
84
+ addMinutes: (value: DateTime, amount: number) => DateTime<boolean>;
85
+ addSeconds: (value: DateTime, amount: number) => DateTime<boolean>;
86
86
  getYear: (value: DateTime) => number;
87
87
  getMonth: (value: DateTime) => number;
88
88
  getDate: (value: DateTime) => number;
@@ -90,21 +90,21 @@ export declare class AdapterLuxon implements MuiPickersAdapter<DateTime, string>
90
90
  getMinutes: (value: DateTime) => number;
91
91
  getSeconds: (value: DateTime) => number;
92
92
  getMilliseconds: (value: DateTime) => number;
93
- setYear: (value: DateTime, year: number) => DateTime;
94
- setMonth: (value: DateTime, month: number) => DateTime;
95
- setDate: (value: DateTime, date: number) => DateTime;
96
- setHours: (value: DateTime, hours: number) => DateTime;
97
- setMinutes: (value: DateTime, minutes: number) => DateTime;
98
- setSeconds: (value: DateTime, seconds: number) => DateTime;
99
- setMilliseconds: (value: DateTime, milliseconds: number) => DateTime;
93
+ setYear: (value: DateTime, year: number) => DateTime<boolean>;
94
+ setMonth: (value: DateTime, month: number) => DateTime<boolean>;
95
+ setDate: (value: DateTime, date: number) => DateTime<boolean>;
96
+ setHours: (value: DateTime, hours: number) => DateTime<boolean>;
97
+ setMinutes: (value: DateTime, minutes: number) => DateTime<boolean>;
98
+ setSeconds: (value: DateTime, seconds: number) => DateTime<boolean>;
99
+ setMilliseconds: (value: DateTime, milliseconds: number) => DateTime<boolean>;
100
100
  getDaysInMonth: (value: DateTime) => import("luxon").PossibleDaysInMonth;
101
- getNextMonth: (value: DateTime) => DateTime;
102
- getPreviousMonth: (value: DateTime) => DateTime;
103
- getMonthArray: (value: DateTime) => DateTime[];
104
- mergeDateAndTime: (dateParam: DateTime, timeParam: DateTime) => DateTime;
101
+ getNextMonth: (value: DateTime) => DateTime<boolean>;
102
+ getPreviousMonth: (value: DateTime) => DateTime<boolean>;
103
+ getMonthArray: (value: DateTime) => DateTime<boolean>[];
104
+ mergeDateAndTime: (dateParam: DateTime, timeParam: DateTime) => DateTime<boolean>;
105
105
  getWeekdays: () => string[];
106
- getWeekArray: (value: DateTime) => DateTime[][];
106
+ getWeekArray: (value: DateTime) => DateTime<boolean>[][];
107
107
  getWeekNumber: (value: DateTime) => number;
108
- getYearRange: (start: DateTime, end: DateTime) => DateTime[];
108
+ getYearRange: (start: DateTime, end: DateTime) => DateTime<boolean>[];
109
109
  getMeridiemText: (ampm: 'am' | 'pm') => string;
110
110
  }
package/CHANGELOG.md CHANGED
@@ -3,6 +3,48 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## 6.18.7
7
+
8
+ _Jan 5, 2024_
9
+
10
+ We'd like to offer a big thanks to the 4 contributors who made this release possible. Here are some highlights ✨:
11
+
12
+ - 🌍 Improve Czech (cs-CZ) locale on Data Grid (#11429) @wensiet
13
+ - 🐞 Bugfixes
14
+
15
+ ### Data Grid
16
+
17
+ #### `@mui/x-data-grid@6.18.7`
18
+
19
+ - [DataGrid] Don't evaluate `hasEval` when `disableEval` is set (#11553) @reihwald
20
+ - [l10n] Update Czech (cs-CZ) locale (#11498) @fdebef
21
+
22
+ #### `@mui/x-data-grid-pro@6.18.7` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
23
+
24
+ Same changes as in `@mui/x-data-grid@6.18.7`.
25
+
26
+ #### `@mui/x-data-grid-premium@6.18.7` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
27
+
28
+ Same changes as in `@mui/x-data-grid-pro@6.18.7`.
29
+
30
+ ### Date Pickers
31
+
32
+ #### `@mui/x-date-pickers@6.18.7`
33
+
34
+ - [pickers] Fix views management (@LukasTy) (#11572)
35
+
36
+ #### `@mui/x-date-pickers-pro@6.18.7` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
37
+
38
+ Same changes as in `@mui/x-date-pickers@6.18.7`.
39
+
40
+ ### Charts / `@mui/x-charts@6.18.7`
41
+
42
+ - [charts] Fix `null` in line chart using dataset (@alexfauquette) (#11561)
43
+
44
+ ### Docs
45
+
46
+ - [docs] Clarify Pickers usage with Luxon (#11566) @LukasTy
47
+
6
48
  ## 6.18.6
7
49
 
8
50
  _Dec 22, 2023_
@@ -37,7 +79,7 @@ Same changes as in `@mui/x-data-grid-pro@6.18.6`.
37
79
 
38
80
  Same changes as in `@mui/x-date-pickers@6.18.6`.
39
81
 
40
- ### Charts / `@mui/x-charts@6.18.6`
82
+ ### Charts / `@mui/x-charts@6.18.4`
41
83
 
42
84
  - [charts] Allow percentage values for pie chart center and radius (#11464) @alexfauquette
43
85
  - [charts] Make error message more explicit (#11457) @alexfauquette
@@ -258,9 +258,9 @@ export const DateCalendar = /*#__PURE__*/React.forwardRef(function DateCalendar(
258
258
  const handleSelectedDayChange = useEventCallback(day => {
259
259
  if (day) {
260
260
  // If there is a date already selected, then we want to keep its time
261
- return handleValueChange(mergeDateAndTime(utils, day, value != null ? value : referenceDate), 'finish');
261
+ return handleValueChange(mergeDateAndTime(utils, day, value != null ? value : referenceDate), 'finish', view);
262
262
  }
263
- return handleValueChange(day, 'finish');
263
+ return handleValueChange(day, 'finish', view);
264
264
  });
265
265
  React.useEffect(() => {
266
266
  if (value != null && utils.isValid(value)) {
@@ -449,9 +449,11 @@ process.env.NODE_ENV !== "production" ? DateCalendar.propTypes = {
449
449
  monthsPerRow: PropTypes.oneOf([3, 4]),
450
450
  /**
451
451
  * Callback fired when the value changes.
452
- * @template TDate
453
- * @param {TDate | null} value The new value.
452
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
453
+ * @template TView The view type. Will be one of date or time views.
454
+ * @param {TValue} value The new value.
454
455
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
456
+ * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
455
457
  */
456
458
  onChange: PropTypes.func,
457
459
  /**
@@ -6,7 +6,6 @@ import { PickersCalendarHeader, PickersCalendarHeaderProps, PickersCalendarHeade
6
6
  import { DayCalendarSlotsComponent, DayCalendarSlotsComponentsProps, ExportedDayCalendarProps } from './DayCalendar';
7
7
  import { DateCalendarClasses } from './dateCalendarClasses';
8
8
  import { BaseDateValidationProps, YearValidationProps, MonthValidationProps, DayValidationProps } from '../internals/models/validation';
9
- import { PickerSelectionState } from '../internals/hooks/usePicker/usePickerValue.types';
10
9
  import { ExportedUseViewsOptions } from '../internals/hooks/useViews';
11
10
  import { DateView, TimezoneProps } from '../models';
12
11
  import { DefaultizedProps } from '../internals/models/helpers';
@@ -80,13 +79,6 @@ export interface DateCalendarProps<TDate> extends ExportedDateCalendarProps<TDat
80
79
  * @default The closest valid date using the validation props, except callbacks such as `shouldDisableDate`.
81
80
  */
82
81
  referenceDate?: TDate;
83
- /**
84
- * Callback fired when the value changes.
85
- * @template TDate
86
- * @param {TDate | null} value The new value.
87
- * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
88
- */
89
- onChange?: (value: TDate | null, selectionState?: PickerSelectionState) => void;
90
82
  className?: string;
91
83
  classes?: Partial<DateCalendarClasses>;
92
84
  /**
@@ -340,8 +340,9 @@ process.env.NODE_ENV !== "production" ? DigitalClock.propTypes = {
340
340
  minutesStep: PropTypes.number,
341
341
  /**
342
342
  * Callback fired when the value changes.
343
- * @template TDate, TView
344
- * @param {TDate | null} value The new value.
343
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
344
+ * @template TView The view type. Will be one of date or time views.
345
+ * @param {TValue} value The new value.
345
346
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
346
347
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
347
348
  */
@@ -125,7 +125,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
125
125
  }, [ampm, inViews]);
126
126
  const {
127
127
  view,
128
- setValueAndGoToView,
128
+ setValueAndGoToNextView,
129
129
  focusedView
130
130
  } = useViews({
131
131
  view: inView,
@@ -137,7 +137,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
137
137
  onFocusedViewChange
138
138
  });
139
139
  const handleMeridiemValueChange = useEventCallback(newValue => {
140
- setValueAndGoToView(newValue, null, 'meridiem');
140
+ setValueAndGoToNextView(newValue, 'finish', 'meridiem');
141
141
  });
142
142
  const {
143
143
  meridiemMode,
@@ -221,11 +221,6 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
221
221
  throw new Error('not supported');
222
222
  }
223
223
  }, [ampm, valueOrReferenceDate, disableIgnoringDatePartForTimeValidation, maxTime, meridiemMode, minTime, minutesStep, shouldDisableClock, shouldDisableTime, utils, disableFuture, disablePast, now, views]);
224
- const handleSectionChange = useEventCallback((sectionView, newValue) => {
225
- const viewIndex = views.indexOf(sectionView);
226
- const nextView = views[viewIndex + 1];
227
- setValueAndGoToView(newValue, nextView, sectionView);
228
- });
229
224
  const buildViewProps = React.useCallback(viewToBuild => {
230
225
  switch (viewToBuild) {
231
226
  case 'hours':
@@ -233,7 +228,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
233
228
  return {
234
229
  onChange: hours => {
235
230
  const valueWithMeridiem = convertValueToMeridiem(hours, meridiemMode, ampm);
236
- handleSectionChange('hours', utils.setHours(valueOrReferenceDate, valueWithMeridiem));
231
+ setValueAndGoToNextView(utils.setHours(valueOrReferenceDate, valueWithMeridiem), 'finish', 'hours');
237
232
  },
238
233
  items: getHourSectionOptions({
239
234
  now,
@@ -250,7 +245,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
250
245
  {
251
246
  return {
252
247
  onChange: minutes => {
253
- handleSectionChange('minutes', utils.setMinutes(valueOrReferenceDate, minutes));
248
+ setValueAndGoToNextView(utils.setMinutes(valueOrReferenceDate, minutes), 'finish', 'minutes');
254
249
  },
255
250
  items: getTimeSectionOptions({
256
251
  value: utils.getMinutes(valueOrReferenceDate),
@@ -267,7 +262,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
267
262
  {
268
263
  return {
269
264
  onChange: seconds => {
270
- handleSectionChange('seconds', utils.setSeconds(valueOrReferenceDate, seconds));
265
+ setValueAndGoToNextView(utils.setSeconds(valueOrReferenceDate, seconds), 'finish', 'seconds');
271
266
  },
272
267
  items: getTimeSectionOptions({
273
268
  value: utils.getSeconds(valueOrReferenceDate),
@@ -302,7 +297,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
302
297
  default:
303
298
  throw new Error(`Unknown view: ${viewToBuild} found.`);
304
299
  }
305
- }, [now, value, ampm, utils, timeSteps.hours, timeSteps.minutes, timeSteps.seconds, localeText.hoursClockNumberText, localeText.minutesClockNumberText, localeText.secondsClockNumberText, meridiemMode, handleSectionChange, valueOrReferenceDate, disabled, isTimeDisabled, handleMeridiemChange]);
300
+ }, [now, value, ampm, utils, timeSteps.hours, timeSteps.minutes, timeSteps.seconds, localeText.hoursClockNumberText, localeText.minutesClockNumberText, localeText.secondsClockNumberText, meridiemMode, setValueAndGoToNextView, valueOrReferenceDate, disabled, isTimeDisabled, handleMeridiemChange]);
306
301
  const viewTimeOptions = React.useMemo(() => {
307
302
  return views.reduce((result, currentView) => {
308
303
  return _extends({}, result, {
@@ -412,8 +407,9 @@ process.env.NODE_ENV !== "production" ? MultiSectionDigitalClock.propTypes = {
412
407
  minutesStep: PropTypes.number,
413
408
  /**
414
409
  * Callback fired when the value changes.
415
- * @template TDate, TView
416
- * @param {TDate | null} value The new value.
410
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
411
+ * @template TView The view type. Will be one of date or time views.
412
+ * @param {TValue} value The new value.
417
413
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
418
414
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
419
415
  */
@@ -89,7 +89,7 @@ export const MultiSectionDigitalClockSection = /*#__PURE__*/React.forwardRef(fun
89
89
  var _slots$digitalClockSe;
90
90
  const containerRef = React.useRef(null);
91
91
  const handleRef = useForkRef(ref, containerRef);
92
- const previousSelected = React.useRef(null);
92
+ const previousActive = React.useRef(null);
93
93
  const props = useThemeProps({
94
94
  props: inProps,
95
95
  name: 'MuiMultiSectionDigitalClockSection'
@@ -116,19 +116,15 @@ export const MultiSectionDigitalClockSection = /*#__PURE__*/React.forwardRef(fun
116
116
  if (containerRef.current === null) {
117
117
  return;
118
118
  }
119
- const selectedItem = containerRef.current.querySelector('[role="option"][aria-selected="true"]');
120
- if (!selectedItem || previousSelected.current === selectedItem) {
121
- // Handle setting the ref to null if the selected item is ever reset via UI
122
- if (previousSelected.current !== selectedItem) {
123
- previousSelected.current = selectedItem;
124
- }
125
- return;
119
+ const activeItem = containerRef.current.querySelector('[role="option"][aria-selected="true"]');
120
+ if (active && autoFocus && activeItem) {
121
+ activeItem.focus();
126
122
  }
127
- previousSelected.current = selectedItem;
128
- if (active && autoFocus) {
129
- selectedItem.focus();
123
+ if (!activeItem || previousActive.current === activeItem) {
124
+ return;
130
125
  }
131
- const offsetTop = selectedItem.offsetTop;
126
+ previousActive.current = activeItem;
127
+ const offsetTop = activeItem.offsetTop;
132
128
 
133
129
  // Subtracting the 4px of extra margin intended for the first visible section item
134
130
  containerRef.current.scrollTop = offsetTop - 4;
@@ -404,8 +404,9 @@ process.env.NODE_ENV !== "production" ? TimeClock.propTypes = {
404
404
  minutesStep: PropTypes.number,
405
405
  /**
406
406
  * Callback fired when the value changes.
407
- * @template TDate, TView
408
- * @param {TDate | null} value The new value.
407
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
408
+ * @template TView The view type. Will be one of date or time views.
409
+ * @param {TValue} value The new value.
409
410
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
410
411
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
411
412
  */
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-date-pickers v6.18.6
2
+ * @mui/x-date-pickers v6.18.7
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -5,7 +5,8 @@ export type PickerOnChangeFn<TDate> = (date: TDate | null, selectionState?: Pick
5
5
  export interface UseViewsOptions<TValue, TView extends DateOrTimeViewWithMeridiem> {
6
6
  /**
7
7
  * Callback fired when the value changes.
8
- * @template TValue
8
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
9
+ * @template TView The view type. Will be one of date or time views.
9
10
  * @param {TValue} value The new value.
10
11
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
11
12
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
@@ -52,7 +53,7 @@ export interface UseViewsOptions<TValue, TView extends DateOrTimeViewWithMeridie
52
53
  */
53
54
  onFocusedViewChange?: (view: TView, hasFocus: boolean) => void;
54
55
  }
55
- export interface ExportedUseViewsOptions<TView extends DateOrTimeViewWithMeridiem> extends MakeOptional<Omit<UseViewsOptions<any, TView>, 'onChange'>, 'openTo' | 'views'> {
56
+ export interface ExportedUseViewsOptions<TView extends DateOrTimeViewWithMeridiem> extends MakeOptional<UseViewsOptions<any, TView>, 'onChange' | 'openTo' | 'views'> {
56
57
  }
57
58
  interface UseViewsResponse<TValue, TView extends DateOrTimeViewWithMeridiem> {
58
59
  view: TView;
@@ -63,8 +64,7 @@ interface UseViewsResponse<TValue, TView extends DateOrTimeViewWithMeridiem> {
63
64
  previousView: TView | null;
64
65
  defaultView: TView;
65
66
  goToNextView: () => void;
66
- setValueAndGoToNextView: (value: TValue, currentViewSelectionState?: PickerSelectionState) => void;
67
- setValueAndGoToView: (value: TValue, newView: TView | null, selectedView: TView) => void;
67
+ setValueAndGoToNextView: (value: TValue, currentViewSelectionState?: PickerSelectionState, selectedView?: TView) => void;
68
68
  }
69
69
  export declare function useViews<TValue, TView extends DateOrTimeViewWithMeridiem>({ onChange, onViewChange, openTo, view: inView, views, autoFocus, focusedView: inFocusedView, onFocusedViewChange, }: UseViewsOptions<TValue, TView>): UseViewsResponse<TValue, TView>;
70
70
  export {};
@@ -65,11 +65,12 @@ export function useViews({
65
65
  onFocusedViewChange == null || onFocusedViewChange(viewToFocus, hasFocus);
66
66
  });
67
67
  const handleChangeView = useEventCallback(newView => {
68
+ // always keep the focused view in sync
69
+ handleFocusedViewChange(newView, true);
68
70
  if (newView === view) {
69
71
  return;
70
72
  }
71
73
  setView(newView);
72
- handleFocusedViewChange(newView, true);
73
74
  if (onViewChange) {
74
75
  onViewChange(newView);
75
76
  }
@@ -78,7 +79,6 @@ export function useViews({
78
79
  if (nextView) {
79
80
  handleChangeView(nextView);
80
81
  }
81
- handleFocusedViewChange(nextView, true);
82
82
  });
83
83
  const setValueAndGoToNextView = useEventCallback((value, currentViewSelectionState, selectedView) => {
84
84
  const isSelectionFinishedOnCurrentView = currentViewSelectionState === 'finish';
@@ -87,18 +87,19 @@ export function useViews({
87
87
  // but we it's not the final view given all `views` -> overall selection state should be `partial`.
88
88
  views.indexOf(selectedView) < views.length - 1 : Boolean(nextView);
89
89
  const globalSelectionState = isSelectionFinishedOnCurrentView && hasMoreViews ? 'partial' : currentViewSelectionState;
90
- onChange(value, globalSelectionState);
91
- if (isSelectionFinishedOnCurrentView) {
90
+ onChange(value, globalSelectionState, selectedView);
91
+ // Detects if the selected view is not the active one.
92
+ // Can happen if multiple views are displayed, like in `DesktopDateTimePicker` or `MultiSectionDigitalClock`.
93
+ if (selectedView && selectedView !== view) {
94
+ const nextViewAfterSelected = views[views.indexOf(selectedView) + 1];
95
+ if (nextViewAfterSelected) {
96
+ // move to next view after the selected one
97
+ handleChangeView(nextViewAfterSelected);
98
+ }
99
+ } else if (isSelectionFinishedOnCurrentView) {
92
100
  goToNextView();
93
101
  }
94
102
  });
95
- const setValueAndGoToView = useEventCallback((value, newView, selectedView) => {
96
- onChange(value, newView ? 'partial' : 'finish', selectedView);
97
- if (newView) {
98
- handleChangeView(newView);
99
- handleFocusedViewChange(newView, true);
100
- }
101
- });
102
103
  return {
103
104
  view,
104
105
  setView: handleChangeView,
@@ -109,7 +110,6 @@ export function useViews({
109
110
  // Always return up to date default view instead of the initial one (i.e. defaultView.current)
110
111
  defaultView: views.includes(openTo) ? openTo : views[0],
111
112
  goToNextView,
112
- setValueAndGoToNextView,
113
- setValueAndGoToView
113
+ setValueAndGoToNextView
114
114
  };
115
115
  }
@@ -1,6 +1,5 @@
1
1
  import { SxProps, Theme } from '@mui/material/styles';
2
2
  import { BaseTimeValidationProps, TimeValidationProps } from '../validation';
3
- import { PickerSelectionState } from '../../hooks/usePicker/usePickerValue.types';
4
3
  import { TimeStepOptions, TimezoneProps } from '../../../models';
5
4
  import type { ExportedDigitalClockProps } from '../../../DigitalClock/DigitalClock.types';
6
5
  import type { ExportedMultiSectionDigitalClockProps } from '../../../MultiSectionDigitalClock/MultiSectionDigitalClock.types';
@@ -29,14 +28,6 @@ export interface BaseClockProps<TDate, TView extends TimeViewWithMeridiem> exten
29
28
  * Used when the component is not controlled.
30
29
  */
31
30
  defaultValue?: TDate | null;
32
- /**
33
- * Callback fired when the value changes.
34
- * @template TDate, TView
35
- * @param {TDate | null} value The new value.
36
- * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
37
- * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
38
- */
39
- onChange?: (value: TDate | null, selectionState?: PickerSelectionState, selectedView?: TView) => void;
40
31
  /**
41
32
  * If `true`, the picker views and text field are disabled.
42
33
  * @default false
@@ -259,9 +259,9 @@ export var DateCalendar = /*#__PURE__*/React.forwardRef(function DateCalendar(in
259
259
  var handleSelectedDayChange = useEventCallback(function (day) {
260
260
  if (day) {
261
261
  // If there is a date already selected, then we want to keep its time
262
- return handleValueChange(mergeDateAndTime(utils, day, value != null ? value : referenceDate), 'finish');
262
+ return handleValueChange(mergeDateAndTime(utils, day, value != null ? value : referenceDate), 'finish', view);
263
263
  }
264
- return handleValueChange(day, 'finish');
264
+ return handleValueChange(day, 'finish', view);
265
265
  });
266
266
  React.useEffect(function () {
267
267
  if (value != null && utils.isValid(value)) {
@@ -458,9 +458,11 @@ process.env.NODE_ENV !== "production" ? DateCalendar.propTypes = {
458
458
  monthsPerRow: PropTypes.oneOf([3, 4]),
459
459
  /**
460
460
  * Callback fired when the value changes.
461
- * @template TDate
462
- * @param {TDate | null} value The new value.
461
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
462
+ * @template TView The view type. Will be one of date or time views.
463
+ * @param {TValue} value The new value.
463
464
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
465
+ * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
464
466
  */
465
467
  onChange: PropTypes.func,
466
468
  /**
@@ -357,8 +357,9 @@ process.env.NODE_ENV !== "production" ? DigitalClock.propTypes = {
357
357
  minutesStep: PropTypes.number,
358
358
  /**
359
359
  * Callback fired when the value changes.
360
- * @template TDate, TView
361
- * @param {TDate | null} value The new value.
360
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
361
+ * @template TView The view type. Will be one of date or time views.
362
+ * @param {TValue} value The new value.
362
363
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
363
364
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
364
365
  */
@@ -143,10 +143,10 @@ export var MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function Mul
143
143
  onFocusedViewChange: onFocusedViewChange
144
144
  }),
145
145
  view = _useViews.view,
146
- setValueAndGoToView = _useViews.setValueAndGoToView,
146
+ setValueAndGoToNextView = _useViews.setValueAndGoToNextView,
147
147
  focusedView = _useViews.focusedView;
148
148
  var handleMeridiemValueChange = useEventCallback(function (newValue) {
149
- setValueAndGoToView(newValue, null, 'meridiem');
149
+ setValueAndGoToNextView(newValue, 'finish', 'meridiem');
150
150
  });
151
151
  var _useMeridiemMode = useMeridiemMode(valueOrReferenceDate, ampm, handleMeridiemValueChange, 'finish'),
152
152
  meridiemMode = _useMeridiemMode.meridiemMode,
@@ -229,11 +229,6 @@ export var MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function Mul
229
229
  throw new Error('not supported');
230
230
  }
231
231
  }, [ampm, valueOrReferenceDate, disableIgnoringDatePartForTimeValidation, maxTime, meridiemMode, minTime, minutesStep, shouldDisableClock, shouldDisableTime, utils, disableFuture, disablePast, now, views]);
232
- var handleSectionChange = useEventCallback(function (sectionView, newValue) {
233
- var viewIndex = views.indexOf(sectionView);
234
- var nextView = views[viewIndex + 1];
235
- setValueAndGoToView(newValue, nextView, sectionView);
236
- });
237
232
  var buildViewProps = React.useCallback(function (viewToBuild) {
238
233
  switch (viewToBuild) {
239
234
  case 'hours':
@@ -241,7 +236,7 @@ export var MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function Mul
241
236
  return {
242
237
  onChange: function onChange(hours) {
243
238
  var valueWithMeridiem = convertValueToMeridiem(hours, meridiemMode, ampm);
244
- handleSectionChange('hours', utils.setHours(valueOrReferenceDate, valueWithMeridiem));
239
+ setValueAndGoToNextView(utils.setHours(valueOrReferenceDate, valueWithMeridiem), 'finish', 'hours');
245
240
  },
246
241
  items: getHourSectionOptions({
247
242
  now: now,
@@ -260,7 +255,7 @@ export var MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function Mul
260
255
  {
261
256
  return {
262
257
  onChange: function onChange(minutes) {
263
- handleSectionChange('minutes', utils.setMinutes(valueOrReferenceDate, minutes));
258
+ setValueAndGoToNextView(utils.setMinutes(valueOrReferenceDate, minutes), 'finish', 'minutes');
264
259
  },
265
260
  items: getTimeSectionOptions({
266
261
  value: utils.getMinutes(valueOrReferenceDate),
@@ -281,7 +276,7 @@ export var MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function Mul
281
276
  {
282
277
  return {
283
278
  onChange: function onChange(seconds) {
284
- handleSectionChange('seconds', utils.setSeconds(valueOrReferenceDate, seconds));
279
+ setValueAndGoToNextView(utils.setSeconds(valueOrReferenceDate, seconds), 'finish', 'seconds');
285
280
  },
286
281
  items: getTimeSectionOptions({
287
282
  value: utils.getSeconds(valueOrReferenceDate),
@@ -324,7 +319,7 @@ export var MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function Mul
324
319
  default:
325
320
  throw new Error("Unknown view: ".concat(viewToBuild, " found."));
326
321
  }
327
- }, [now, value, ampm, utils, timeSteps.hours, timeSteps.minutes, timeSteps.seconds, localeText.hoursClockNumberText, localeText.minutesClockNumberText, localeText.secondsClockNumberText, meridiemMode, handleSectionChange, valueOrReferenceDate, disabled, isTimeDisabled, handleMeridiemChange]);
322
+ }, [now, value, ampm, utils, timeSteps.hours, timeSteps.minutes, timeSteps.seconds, localeText.hoursClockNumberText, localeText.minutesClockNumberText, localeText.secondsClockNumberText, meridiemMode, setValueAndGoToNextView, valueOrReferenceDate, disabled, isTimeDisabled, handleMeridiemChange]);
328
323
  var viewTimeOptions = React.useMemo(function () {
329
324
  return views.reduce(function (result, currentView) {
330
325
  return _extends({}, result, _defineProperty({}, currentView, buildViewProps(currentView)));
@@ -437,8 +432,9 @@ process.env.NODE_ENV !== "production" ? MultiSectionDigitalClock.propTypes = {
437
432
  minutesStep: PropTypes.number,
438
433
  /**
439
434
  * Callback fired when the value changes.
440
- * @template TDate, TView
441
- * @param {TDate | null} value The new value.
435
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
436
+ * @template TView The view type. Will be one of date or time views.
437
+ * @param {TValue} value The new value.
442
438
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
443
439
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
444
440
  */
@@ -93,7 +93,7 @@ export var MultiSectionDigitalClockSection = /*#__PURE__*/React.forwardRef(funct
93
93
  var _slots$digitalClockSe;
94
94
  var containerRef = React.useRef(null);
95
95
  var handleRef = useForkRef(ref, containerRef);
96
- var previousSelected = React.useRef(null);
96
+ var previousActive = React.useRef(null);
97
97
  var props = useThemeProps({
98
98
  props: inProps,
99
99
  name: 'MuiMultiSectionDigitalClockSection'
@@ -120,19 +120,15 @@ export var MultiSectionDigitalClockSection = /*#__PURE__*/React.forwardRef(funct
120
120
  if (containerRef.current === null) {
121
121
  return;
122
122
  }
123
- var selectedItem = containerRef.current.querySelector('[role="option"][aria-selected="true"]');
124
- if (!selectedItem || previousSelected.current === selectedItem) {
125
- // Handle setting the ref to null if the selected item is ever reset via UI
126
- if (previousSelected.current !== selectedItem) {
127
- previousSelected.current = selectedItem;
128
- }
129
- return;
123
+ var activeItem = containerRef.current.querySelector('[role="option"][aria-selected="true"]');
124
+ if (active && autoFocus && activeItem) {
125
+ activeItem.focus();
130
126
  }
131
- previousSelected.current = selectedItem;
132
- if (active && autoFocus) {
133
- selectedItem.focus();
127
+ if (!activeItem || previousActive.current === activeItem) {
128
+ return;
134
129
  }
135
- var offsetTop = selectedItem.offsetTop;
130
+ previousActive.current = activeItem;
131
+ var offsetTop = activeItem.offsetTop;
136
132
 
137
133
  // Subtracting the 4px of extra margin intended for the first visible section item
138
134
  containerRef.current.scrollTop = offsetTop - 4;
@@ -416,8 +416,9 @@ process.env.NODE_ENV !== "production" ? TimeClock.propTypes = {
416
416
  minutesStep: PropTypes.number,
417
417
  /**
418
418
  * Callback fired when the value changes.
419
- * @template TDate, TView
420
- * @param {TDate | null} value The new value.
419
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
420
+ * @template TView The view type. Will be one of date or time views.
421
+ * @param {TValue} value The new value.
421
422
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
422
423
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
423
424
  */
package/legacy/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-date-pickers v6.18.6
2
+ * @mui/x-date-pickers v6.18.7
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -75,11 +75,12 @@ export function useViews(_ref) {
75
75
  onFocusedViewChange == null || onFocusedViewChange(viewToFocus, hasFocus);
76
76
  });
77
77
  var handleChangeView = useEventCallback(function (newView) {
78
+ // always keep the focused view in sync
79
+ handleFocusedViewChange(newView, true);
78
80
  if (newView === view) {
79
81
  return;
80
82
  }
81
83
  setView(newView);
82
- handleFocusedViewChange(newView, true);
83
84
  if (onViewChange) {
84
85
  onViewChange(newView);
85
86
  }
@@ -88,7 +89,6 @@ export function useViews(_ref) {
88
89
  if (nextView) {
89
90
  handleChangeView(nextView);
90
91
  }
91
- handleFocusedViewChange(nextView, true);
92
92
  });
93
93
  var setValueAndGoToNextView = useEventCallback(function (value, currentViewSelectionState, selectedView) {
94
94
  var isSelectionFinishedOnCurrentView = currentViewSelectionState === 'finish';
@@ -97,18 +97,19 @@ export function useViews(_ref) {
97
97
  // but we it's not the final view given all `views` -> overall selection state should be `partial`.
98
98
  views.indexOf(selectedView) < views.length - 1 : Boolean(nextView);
99
99
  var globalSelectionState = isSelectionFinishedOnCurrentView && hasMoreViews ? 'partial' : currentViewSelectionState;
100
- onChange(value, globalSelectionState);
101
- if (isSelectionFinishedOnCurrentView) {
100
+ onChange(value, globalSelectionState, selectedView);
101
+ // Detects if the selected view is not the active one.
102
+ // Can happen if multiple views are displayed, like in `DesktopDateTimePicker` or `MultiSectionDigitalClock`.
103
+ if (selectedView && selectedView !== view) {
104
+ var nextViewAfterSelected = views[views.indexOf(selectedView) + 1];
105
+ if (nextViewAfterSelected) {
106
+ // move to next view after the selected one
107
+ handleChangeView(nextViewAfterSelected);
108
+ }
109
+ } else if (isSelectionFinishedOnCurrentView) {
102
110
  goToNextView();
103
111
  }
104
112
  });
105
- var setValueAndGoToView = useEventCallback(function (value, newView, selectedView) {
106
- onChange(value, newView ? 'partial' : 'finish', selectedView);
107
- if (newView) {
108
- handleChangeView(newView);
109
- handleFocusedViewChange(newView, true);
110
- }
111
- });
112
113
  return {
113
114
  view: view,
114
115
  setView: handleChangeView,
@@ -119,7 +120,6 @@ export function useViews(_ref) {
119
120
  // Always return up to date default view instead of the initial one (i.e. defaultView.current)
120
121
  defaultView: views.includes(openTo) ? openTo : views[0],
121
122
  goToNextView: goToNextView,
122
- setValueAndGoToNextView: setValueAndGoToNextView,
123
- setValueAndGoToView: setValueAndGoToView
123
+ setValueAndGoToNextView: setValueAndGoToNextView
124
124
  };
125
125
  }
@@ -256,9 +256,9 @@ export const DateCalendar = /*#__PURE__*/React.forwardRef(function DateCalendar(
256
256
  const handleSelectedDayChange = useEventCallback(day => {
257
257
  if (day) {
258
258
  // If there is a date already selected, then we want to keep its time
259
- return handleValueChange(mergeDateAndTime(utils, day, value ?? referenceDate), 'finish');
259
+ return handleValueChange(mergeDateAndTime(utils, day, value ?? referenceDate), 'finish', view);
260
260
  }
261
- return handleValueChange(day, 'finish');
261
+ return handleValueChange(day, 'finish', view);
262
262
  });
263
263
  React.useEffect(() => {
264
264
  if (value != null && utils.isValid(value)) {
@@ -447,9 +447,11 @@ process.env.NODE_ENV !== "production" ? DateCalendar.propTypes = {
447
447
  monthsPerRow: PropTypes.oneOf([3, 4]),
448
448
  /**
449
449
  * Callback fired when the value changes.
450
- * @template TDate
451
- * @param {TDate | null} value The new value.
450
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
451
+ * @template TView The view type. Will be one of date or time views.
452
+ * @param {TValue} value The new value.
452
453
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
454
+ * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
453
455
  */
454
456
  onChange: PropTypes.func,
455
457
  /**
@@ -339,8 +339,9 @@ process.env.NODE_ENV !== "production" ? DigitalClock.propTypes = {
339
339
  minutesStep: PropTypes.number,
340
340
  /**
341
341
  * Callback fired when the value changes.
342
- * @template TDate, TView
343
- * @param {TDate | null} value The new value.
342
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
343
+ * @template TView The view type. Will be one of date or time views.
344
+ * @param {TValue} value The new value.
344
345
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
345
346
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
346
347
  */
@@ -125,7 +125,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
125
125
  }, [ampm, inViews]);
126
126
  const {
127
127
  view,
128
- setValueAndGoToView,
128
+ setValueAndGoToNextView,
129
129
  focusedView
130
130
  } = useViews({
131
131
  view: inView,
@@ -137,7 +137,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
137
137
  onFocusedViewChange
138
138
  });
139
139
  const handleMeridiemValueChange = useEventCallback(newValue => {
140
- setValueAndGoToView(newValue, null, 'meridiem');
140
+ setValueAndGoToNextView(newValue, 'finish', 'meridiem');
141
141
  });
142
142
  const {
143
143
  meridiemMode,
@@ -221,11 +221,6 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
221
221
  throw new Error('not supported');
222
222
  }
223
223
  }, [ampm, valueOrReferenceDate, disableIgnoringDatePartForTimeValidation, maxTime, meridiemMode, minTime, minutesStep, shouldDisableClock, shouldDisableTime, utils, disableFuture, disablePast, now, views]);
224
- const handleSectionChange = useEventCallback((sectionView, newValue) => {
225
- const viewIndex = views.indexOf(sectionView);
226
- const nextView = views[viewIndex + 1];
227
- setValueAndGoToView(newValue, nextView, sectionView);
228
- });
229
224
  const buildViewProps = React.useCallback(viewToBuild => {
230
225
  switch (viewToBuild) {
231
226
  case 'hours':
@@ -233,7 +228,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
233
228
  return {
234
229
  onChange: hours => {
235
230
  const valueWithMeridiem = convertValueToMeridiem(hours, meridiemMode, ampm);
236
- handleSectionChange('hours', utils.setHours(valueOrReferenceDate, valueWithMeridiem));
231
+ setValueAndGoToNextView(utils.setHours(valueOrReferenceDate, valueWithMeridiem), 'finish', 'hours');
237
232
  },
238
233
  items: getHourSectionOptions({
239
234
  now,
@@ -250,7 +245,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
250
245
  {
251
246
  return {
252
247
  onChange: minutes => {
253
- handleSectionChange('minutes', utils.setMinutes(valueOrReferenceDate, minutes));
248
+ setValueAndGoToNextView(utils.setMinutes(valueOrReferenceDate, minutes), 'finish', 'minutes');
254
249
  },
255
250
  items: getTimeSectionOptions({
256
251
  value: utils.getMinutes(valueOrReferenceDate),
@@ -267,7 +262,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
267
262
  {
268
263
  return {
269
264
  onChange: seconds => {
270
- handleSectionChange('seconds', utils.setSeconds(valueOrReferenceDate, seconds));
265
+ setValueAndGoToNextView(utils.setSeconds(valueOrReferenceDate, seconds), 'finish', 'seconds');
271
266
  },
272
267
  items: getTimeSectionOptions({
273
268
  value: utils.getSeconds(valueOrReferenceDate),
@@ -302,7 +297,7 @@ export const MultiSectionDigitalClock = /*#__PURE__*/React.forwardRef(function M
302
297
  default:
303
298
  throw new Error(`Unknown view: ${viewToBuild} found.`);
304
299
  }
305
- }, [now, value, ampm, utils, timeSteps.hours, timeSteps.minutes, timeSteps.seconds, localeText.hoursClockNumberText, localeText.minutesClockNumberText, localeText.secondsClockNumberText, meridiemMode, handleSectionChange, valueOrReferenceDate, disabled, isTimeDisabled, handleMeridiemChange]);
300
+ }, [now, value, ampm, utils, timeSteps.hours, timeSteps.minutes, timeSteps.seconds, localeText.hoursClockNumberText, localeText.minutesClockNumberText, localeText.secondsClockNumberText, meridiemMode, setValueAndGoToNextView, valueOrReferenceDate, disabled, isTimeDisabled, handleMeridiemChange]);
306
301
  const viewTimeOptions = React.useMemo(() => {
307
302
  return views.reduce((result, currentView) => {
308
303
  return _extends({}, result, {
@@ -412,8 +407,9 @@ process.env.NODE_ENV !== "production" ? MultiSectionDigitalClock.propTypes = {
412
407
  minutesStep: PropTypes.number,
413
408
  /**
414
409
  * Callback fired when the value changes.
415
- * @template TDate, TView
416
- * @param {TDate | null} value The new value.
410
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
411
+ * @template TView The view type. Will be one of date or time views.
412
+ * @param {TValue} value The new value.
417
413
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
418
414
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
419
415
  */
@@ -88,7 +88,7 @@ const MultiSectionDigitalClockSectionItem = styled(MenuItem, {
88
88
  export const MultiSectionDigitalClockSection = /*#__PURE__*/React.forwardRef(function MultiSectionDigitalClockSection(inProps, ref) {
89
89
  const containerRef = React.useRef(null);
90
90
  const handleRef = useForkRef(ref, containerRef);
91
- const previousSelected = React.useRef(null);
91
+ const previousActive = React.useRef(null);
92
92
  const props = useThemeProps({
93
93
  props: inProps,
94
94
  name: 'MuiMultiSectionDigitalClockSection'
@@ -115,19 +115,15 @@ export const MultiSectionDigitalClockSection = /*#__PURE__*/React.forwardRef(fun
115
115
  if (containerRef.current === null) {
116
116
  return;
117
117
  }
118
- const selectedItem = containerRef.current.querySelector('[role="option"][aria-selected="true"]');
119
- if (!selectedItem || previousSelected.current === selectedItem) {
120
- // Handle setting the ref to null if the selected item is ever reset via UI
121
- if (previousSelected.current !== selectedItem) {
122
- previousSelected.current = selectedItem;
123
- }
124
- return;
118
+ const activeItem = containerRef.current.querySelector('[role="option"][aria-selected="true"]');
119
+ if (active && autoFocus && activeItem) {
120
+ activeItem.focus();
125
121
  }
126
- previousSelected.current = selectedItem;
127
- if (active && autoFocus) {
128
- selectedItem.focus();
122
+ if (!activeItem || previousActive.current === activeItem) {
123
+ return;
129
124
  }
130
- const offsetTop = selectedItem.offsetTop;
125
+ previousActive.current = activeItem;
126
+ const offsetTop = activeItem.offsetTop;
131
127
 
132
128
  // Subtracting the 4px of extra margin intended for the first visible section item
133
129
  containerRef.current.scrollTop = offsetTop - 4;
@@ -404,8 +404,9 @@ process.env.NODE_ENV !== "production" ? TimeClock.propTypes = {
404
404
  minutesStep: PropTypes.number,
405
405
  /**
406
406
  * Callback fired when the value changes.
407
- * @template TDate, TView
408
- * @param {TDate | null} value The new value.
407
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
408
+ * @template TView The view type. Will be one of date or time views.
409
+ * @param {TValue} value The new value.
409
410
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
410
411
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
411
412
  */
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-date-pickers v6.18.6
2
+ * @mui/x-date-pickers v6.18.7
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -64,11 +64,12 @@ export function useViews({
64
64
  onFocusedViewChange?.(viewToFocus, hasFocus);
65
65
  });
66
66
  const handleChangeView = useEventCallback(newView => {
67
+ // always keep the focused view in sync
68
+ handleFocusedViewChange(newView, true);
67
69
  if (newView === view) {
68
70
  return;
69
71
  }
70
72
  setView(newView);
71
- handleFocusedViewChange(newView, true);
72
73
  if (onViewChange) {
73
74
  onViewChange(newView);
74
75
  }
@@ -77,7 +78,6 @@ export function useViews({
77
78
  if (nextView) {
78
79
  handleChangeView(nextView);
79
80
  }
80
- handleFocusedViewChange(nextView, true);
81
81
  });
82
82
  const setValueAndGoToNextView = useEventCallback((value, currentViewSelectionState, selectedView) => {
83
83
  const isSelectionFinishedOnCurrentView = currentViewSelectionState === 'finish';
@@ -86,18 +86,19 @@ export function useViews({
86
86
  // but we it's not the final view given all `views` -> overall selection state should be `partial`.
87
87
  views.indexOf(selectedView) < views.length - 1 : Boolean(nextView);
88
88
  const globalSelectionState = isSelectionFinishedOnCurrentView && hasMoreViews ? 'partial' : currentViewSelectionState;
89
- onChange(value, globalSelectionState);
90
- if (isSelectionFinishedOnCurrentView) {
89
+ onChange(value, globalSelectionState, selectedView);
90
+ // Detects if the selected view is not the active one.
91
+ // Can happen if multiple views are displayed, like in `DesktopDateTimePicker` or `MultiSectionDigitalClock`.
92
+ if (selectedView && selectedView !== view) {
93
+ const nextViewAfterSelected = views[views.indexOf(selectedView) + 1];
94
+ if (nextViewAfterSelected) {
95
+ // move to next view after the selected one
96
+ handleChangeView(nextViewAfterSelected);
97
+ }
98
+ } else if (isSelectionFinishedOnCurrentView) {
91
99
  goToNextView();
92
100
  }
93
101
  });
94
- const setValueAndGoToView = useEventCallback((value, newView, selectedView) => {
95
- onChange(value, newView ? 'partial' : 'finish', selectedView);
96
- if (newView) {
97
- handleChangeView(newView);
98
- handleFocusedViewChange(newView, true);
99
- }
100
- });
101
102
  return {
102
103
  view,
103
104
  setView: handleChangeView,
@@ -108,7 +109,6 @@ export function useViews({
108
109
  // Always return up to date default view instead of the initial one (i.e. defaultView.current)
109
110
  defaultView: views.includes(openTo) ? openTo : views[0],
110
111
  goToNextView,
111
- setValueAndGoToNextView,
112
- setValueAndGoToView
112
+ setValueAndGoToNextView
113
113
  };
114
114
  }
@@ -264,9 +264,9 @@ const DateCalendar = exports.DateCalendar = /*#__PURE__*/React.forwardRef(functi
264
264
  const handleSelectedDayChange = (0, _utils2.unstable_useEventCallback)(day => {
265
265
  if (day) {
266
266
  // If there is a date already selected, then we want to keep its time
267
- return handleValueChange((0, _dateUtils.mergeDateAndTime)(utils, day, value ?? referenceDate), 'finish');
267
+ return handleValueChange((0, _dateUtils.mergeDateAndTime)(utils, day, value ?? referenceDate), 'finish', view);
268
268
  }
269
- return handleValueChange(day, 'finish');
269
+ return handleValueChange(day, 'finish', view);
270
270
  });
271
271
  React.useEffect(() => {
272
272
  if (value != null && utils.isValid(value)) {
@@ -455,9 +455,11 @@ process.env.NODE_ENV !== "production" ? DateCalendar.propTypes = {
455
455
  monthsPerRow: _propTypes.default.oneOf([3, 4]),
456
456
  /**
457
457
  * Callback fired when the value changes.
458
- * @template TDate
459
- * @param {TDate | null} value The new value.
458
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
459
+ * @template TView The view type. Will be one of date or time views.
460
+ * @param {TValue} value The new value.
460
461
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
462
+ * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
461
463
  */
462
464
  onChange: _propTypes.default.func,
463
465
  /**
@@ -348,8 +348,9 @@ process.env.NODE_ENV !== "production" ? DigitalClock.propTypes = {
348
348
  minutesStep: _propTypes.default.number,
349
349
  /**
350
350
  * Callback fired when the value changes.
351
- * @template TDate, TView
352
- * @param {TDate | null} value The new value.
351
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
352
+ * @template TView The view type. Will be one of date or time views.
353
+ * @param {TValue} value The new value.
353
354
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
354
355
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
355
356
  */
@@ -134,7 +134,7 @@ const MultiSectionDigitalClock = exports.MultiSectionDigitalClock = /*#__PURE__*
134
134
  }, [ampm, inViews]);
135
135
  const {
136
136
  view,
137
- setValueAndGoToView,
137
+ setValueAndGoToNextView,
138
138
  focusedView
139
139
  } = (0, _useViews.useViews)({
140
140
  view: inView,
@@ -146,7 +146,7 @@ const MultiSectionDigitalClock = exports.MultiSectionDigitalClock = /*#__PURE__*
146
146
  onFocusedViewChange
147
147
  });
148
148
  const handleMeridiemValueChange = (0, _useEventCallback.default)(newValue => {
149
- setValueAndGoToView(newValue, null, 'meridiem');
149
+ setValueAndGoToNextView(newValue, 'finish', 'meridiem');
150
150
  });
151
151
  const {
152
152
  meridiemMode,
@@ -230,11 +230,6 @@ const MultiSectionDigitalClock = exports.MultiSectionDigitalClock = /*#__PURE__*
230
230
  throw new Error('not supported');
231
231
  }
232
232
  }, [ampm, valueOrReferenceDate, disableIgnoringDatePartForTimeValidation, maxTime, meridiemMode, minTime, minutesStep, shouldDisableClock, shouldDisableTime, utils, disableFuture, disablePast, now, views]);
233
- const handleSectionChange = (0, _useEventCallback.default)((sectionView, newValue) => {
234
- const viewIndex = views.indexOf(sectionView);
235
- const nextView = views[viewIndex + 1];
236
- setValueAndGoToView(newValue, nextView, sectionView);
237
- });
238
233
  const buildViewProps = React.useCallback(viewToBuild => {
239
234
  switch (viewToBuild) {
240
235
  case 'hours':
@@ -242,7 +237,7 @@ const MultiSectionDigitalClock = exports.MultiSectionDigitalClock = /*#__PURE__*
242
237
  return {
243
238
  onChange: hours => {
244
239
  const valueWithMeridiem = (0, _timeUtils.convertValueToMeridiem)(hours, meridiemMode, ampm);
245
- handleSectionChange('hours', utils.setHours(valueOrReferenceDate, valueWithMeridiem));
240
+ setValueAndGoToNextView(utils.setHours(valueOrReferenceDate, valueWithMeridiem), 'finish', 'hours');
246
241
  },
247
242
  items: (0, _MultiSectionDigitalClock.getHourSectionOptions)({
248
243
  now,
@@ -259,7 +254,7 @@ const MultiSectionDigitalClock = exports.MultiSectionDigitalClock = /*#__PURE__*
259
254
  {
260
255
  return {
261
256
  onChange: minutes => {
262
- handleSectionChange('minutes', utils.setMinutes(valueOrReferenceDate, minutes));
257
+ setValueAndGoToNextView(utils.setMinutes(valueOrReferenceDate, minutes), 'finish', 'minutes');
263
258
  },
264
259
  items: (0, _MultiSectionDigitalClock.getTimeSectionOptions)({
265
260
  value: utils.getMinutes(valueOrReferenceDate),
@@ -276,7 +271,7 @@ const MultiSectionDigitalClock = exports.MultiSectionDigitalClock = /*#__PURE__*
276
271
  {
277
272
  return {
278
273
  onChange: seconds => {
279
- handleSectionChange('seconds', utils.setSeconds(valueOrReferenceDate, seconds));
274
+ setValueAndGoToNextView(utils.setSeconds(valueOrReferenceDate, seconds), 'finish', 'seconds');
280
275
  },
281
276
  items: (0, _MultiSectionDigitalClock.getTimeSectionOptions)({
282
277
  value: utils.getSeconds(valueOrReferenceDate),
@@ -311,7 +306,7 @@ const MultiSectionDigitalClock = exports.MultiSectionDigitalClock = /*#__PURE__*
311
306
  default:
312
307
  throw new Error(`Unknown view: ${viewToBuild} found.`);
313
308
  }
314
- }, [now, value, ampm, utils, timeSteps.hours, timeSteps.minutes, timeSteps.seconds, localeText.hoursClockNumberText, localeText.minutesClockNumberText, localeText.secondsClockNumberText, meridiemMode, handleSectionChange, valueOrReferenceDate, disabled, isTimeDisabled, handleMeridiemChange]);
309
+ }, [now, value, ampm, utils, timeSteps.hours, timeSteps.minutes, timeSteps.seconds, localeText.hoursClockNumberText, localeText.minutesClockNumberText, localeText.secondsClockNumberText, meridiemMode, setValueAndGoToNextView, valueOrReferenceDate, disabled, isTimeDisabled, handleMeridiemChange]);
315
310
  const viewTimeOptions = React.useMemo(() => {
316
311
  return views.reduce((result, currentView) => {
317
312
  return (0, _extends2.default)({}, result, {
@@ -421,8 +416,9 @@ process.env.NODE_ENV !== "production" ? MultiSectionDigitalClock.propTypes = {
421
416
  minutesStep: _propTypes.default.number,
422
417
  /**
423
418
  * Callback fired when the value changes.
424
- * @template TDate, TView
425
- * @param {TDate | null} value The new value.
419
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
420
+ * @template TView The view type. Will be one of date or time views.
421
+ * @param {TValue} value The new value.
426
422
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
427
423
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
428
424
  */
@@ -97,7 +97,7 @@ const MultiSectionDigitalClockSectionItem = (0, _styles.styled)(_MenuItem.defaul
97
97
  const MultiSectionDigitalClockSection = exports.MultiSectionDigitalClockSection = /*#__PURE__*/React.forwardRef(function MultiSectionDigitalClockSection(inProps, ref) {
98
98
  const containerRef = React.useRef(null);
99
99
  const handleRef = (0, _useForkRef.default)(ref, containerRef);
100
- const previousSelected = React.useRef(null);
100
+ const previousActive = React.useRef(null);
101
101
  const props = (0, _styles.useThemeProps)({
102
102
  props: inProps,
103
103
  name: 'MuiMultiSectionDigitalClockSection'
@@ -124,19 +124,15 @@ const MultiSectionDigitalClockSection = exports.MultiSectionDigitalClockSection
124
124
  if (containerRef.current === null) {
125
125
  return;
126
126
  }
127
- const selectedItem = containerRef.current.querySelector('[role="option"][aria-selected="true"]');
128
- if (!selectedItem || previousSelected.current === selectedItem) {
129
- // Handle setting the ref to null if the selected item is ever reset via UI
130
- if (previousSelected.current !== selectedItem) {
131
- previousSelected.current = selectedItem;
132
- }
133
- return;
127
+ const activeItem = containerRef.current.querySelector('[role="option"][aria-selected="true"]');
128
+ if (active && autoFocus && activeItem) {
129
+ activeItem.focus();
134
130
  }
135
- previousSelected.current = selectedItem;
136
- if (active && autoFocus) {
137
- selectedItem.focus();
131
+ if (!activeItem || previousActive.current === activeItem) {
132
+ return;
138
133
  }
139
- const offsetTop = selectedItem.offsetTop;
134
+ previousActive.current = activeItem;
135
+ const offsetTop = activeItem.offsetTop;
140
136
 
141
137
  // Subtracting the 4px of extra margin intended for the first visible section item
142
138
  containerRef.current.scrollTop = offsetTop - 4;
@@ -412,8 +412,9 @@ process.env.NODE_ENV !== "production" ? TimeClock.propTypes = {
412
412
  minutesStep: _propTypes.default.number,
413
413
  /**
414
414
  * Callback fired when the value changes.
415
- * @template TDate, TView
416
- * @param {TDate | null} value The new value.
415
+ * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
416
+ * @template TView The view type. Will be one of date or time views.
417
+ * @param {TValue} value The new value.
417
418
  * @param {PickerSelectionState | undefined} selectionState Indicates if the date selection is complete.
418
419
  * @param {TView | undefined} selectedView Indicates the view in which the selection has been made.
419
420
  */
package/node/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-date-pickers v6.18.6
2
+ * @mui/x-date-pickers v6.18.7
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -73,11 +73,12 @@ function useViews({
73
73
  onFocusedViewChange?.(viewToFocus, hasFocus);
74
74
  });
75
75
  const handleChangeView = (0, _useEventCallback.default)(newView => {
76
+ // always keep the focused view in sync
77
+ handleFocusedViewChange(newView, true);
76
78
  if (newView === view) {
77
79
  return;
78
80
  }
79
81
  setView(newView);
80
- handleFocusedViewChange(newView, true);
81
82
  if (onViewChange) {
82
83
  onViewChange(newView);
83
84
  }
@@ -86,7 +87,6 @@ function useViews({
86
87
  if (nextView) {
87
88
  handleChangeView(nextView);
88
89
  }
89
- handleFocusedViewChange(nextView, true);
90
90
  });
91
91
  const setValueAndGoToNextView = (0, _useEventCallback.default)((value, currentViewSelectionState, selectedView) => {
92
92
  const isSelectionFinishedOnCurrentView = currentViewSelectionState === 'finish';
@@ -95,18 +95,19 @@ function useViews({
95
95
  // but we it's not the final view given all `views` -> overall selection state should be `partial`.
96
96
  views.indexOf(selectedView) < views.length - 1 : Boolean(nextView);
97
97
  const globalSelectionState = isSelectionFinishedOnCurrentView && hasMoreViews ? 'partial' : currentViewSelectionState;
98
- onChange(value, globalSelectionState);
99
- if (isSelectionFinishedOnCurrentView) {
98
+ onChange(value, globalSelectionState, selectedView);
99
+ // Detects if the selected view is not the active one.
100
+ // Can happen if multiple views are displayed, like in `DesktopDateTimePicker` or `MultiSectionDigitalClock`.
101
+ if (selectedView && selectedView !== view) {
102
+ const nextViewAfterSelected = views[views.indexOf(selectedView) + 1];
103
+ if (nextViewAfterSelected) {
104
+ // move to next view after the selected one
105
+ handleChangeView(nextViewAfterSelected);
106
+ }
107
+ } else if (isSelectionFinishedOnCurrentView) {
100
108
  goToNextView();
101
109
  }
102
110
  });
103
- const setValueAndGoToView = (0, _useEventCallback.default)((value, newView, selectedView) => {
104
- onChange(value, newView ? 'partial' : 'finish', selectedView);
105
- if (newView) {
106
- handleChangeView(newView);
107
- handleFocusedViewChange(newView, true);
108
- }
109
- });
110
111
  return {
111
112
  view,
112
113
  setView: handleChangeView,
@@ -117,7 +118,6 @@ function useViews({
117
118
  // Always return up to date default view instead of the initial one (i.e. defaultView.current)
118
119
  defaultView: views.includes(openTo) ? openTo : views[0],
119
120
  goToNextView,
120
- setValueAndGoToNextView,
121
- setValueAndGoToView
121
+ setValueAndGoToNextView
122
122
  };
123
123
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/x-date-pickers",
3
- "version": "6.18.6",
3
+ "version": "6.18.7",
4
4
  "description": "The community edition of the date picker components (MUI X).",
5
5
  "author": "MUI Team",
6
6
  "main": "./node/index.js",