@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.
- package/AdapterLuxon/AdapterLuxon.d.ts +32 -32
- package/CHANGELOG.md +43 -1
- package/DateCalendar/DateCalendar.js +6 -4
- package/DateCalendar/DateCalendar.types.d.ts +0 -8
- package/DigitalClock/DigitalClock.js +3 -2
- package/MultiSectionDigitalClock/MultiSectionDigitalClock.js +9 -13
- package/MultiSectionDigitalClock/MultiSectionDigitalClockSection.js +8 -12
- package/TimeClock/TimeClock.js +3 -2
- package/index.js +1 -1
- package/internals/hooks/useViews.d.ts +4 -4
- package/internals/hooks/useViews.js +13 -13
- package/internals/models/props/clock.d.ts +0 -9
- package/legacy/DateCalendar/DateCalendar.js +6 -4
- package/legacy/DigitalClock/DigitalClock.js +3 -2
- package/legacy/MultiSectionDigitalClock/MultiSectionDigitalClock.js +9 -13
- package/legacy/MultiSectionDigitalClock/MultiSectionDigitalClockSection.js +8 -12
- package/legacy/TimeClock/TimeClock.js +3 -2
- package/legacy/index.js +1 -1
- package/legacy/internals/hooks/useViews.js +13 -13
- package/modern/DateCalendar/DateCalendar.js +6 -4
- package/modern/DigitalClock/DigitalClock.js +3 -2
- package/modern/MultiSectionDigitalClock/MultiSectionDigitalClock.js +9 -13
- package/modern/MultiSectionDigitalClock/MultiSectionDigitalClockSection.js +8 -12
- package/modern/TimeClock/TimeClock.js +3 -2
- package/modern/index.js +1 -1
- package/modern/internals/hooks/useViews.js +13 -13
- package/node/DateCalendar/DateCalendar.js +6 -4
- package/node/DigitalClock/DigitalClock.js +3 -2
- package/node/MultiSectionDigitalClock/MultiSectionDigitalClock.js +9 -13
- package/node/MultiSectionDigitalClock/MultiSectionDigitalClockSection.js +8 -12
- package/node/TimeClock/TimeClock.js +3 -2
- package/node/index.js +1 -1
- package/node/internals/hooks/useViews.js +13 -13
- 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` [](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` [](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` [](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.
|
|
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
|
|
453
|
-
* @
|
|
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
|
|
344
|
-
* @
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
416
|
-
* @
|
|
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
|
|
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
|
|
120
|
-
if (
|
|
121
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
selectedItem.focus();
|
|
123
|
+
if (!activeItem || previousActive.current === activeItem) {
|
|
124
|
+
return;
|
|
130
125
|
}
|
|
131
|
-
|
|
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;
|
package/TimeClock/TimeClock.js
CHANGED
|
@@ -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
|
|
408
|
-
* @
|
|
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
|
@@ -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<
|
|
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
|
|
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
|
|
462
|
-
* @
|
|
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
|
|
361
|
-
* @
|
|
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
|
-
|
|
146
|
+
setValueAndGoToNextView = _useViews.setValueAndGoToNextView,
|
|
147
147
|
focusedView = _useViews.focusedView;
|
|
148
148
|
var handleMeridiemValueChange = useEventCallback(function (newValue) {
|
|
149
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
441
|
-
* @
|
|
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
|
|
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
|
|
124
|
-
if (
|
|
125
|
-
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
selectedItem.focus();
|
|
127
|
+
if (!activeItem || previousActive.current === activeItem) {
|
|
128
|
+
return;
|
|
134
129
|
}
|
|
135
|
-
|
|
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
|
|
420
|
-
* @
|
|
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
|
@@ -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
|
|
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
|
|
451
|
-
* @
|
|
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
|
|
343
|
-
* @
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
416
|
-
* @
|
|
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
|
|
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
|
|
119
|
-
if (
|
|
120
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
selectedItem.focus();
|
|
122
|
+
if (!activeItem || previousActive.current === activeItem) {
|
|
123
|
+
return;
|
|
129
124
|
}
|
|
130
|
-
|
|
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
|
|
408
|
-
* @
|
|
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
|
@@ -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
|
|
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
|
|
459
|
-
* @
|
|
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
|
|
352
|
-
* @
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
425
|
-
* @
|
|
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
|
|
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
|
|
128
|
-
if (
|
|
129
|
-
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
selectedItem.focus();
|
|
131
|
+
if (!activeItem || previousActive.current === activeItem) {
|
|
132
|
+
return;
|
|
138
133
|
}
|
|
139
|
-
|
|
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
|
|
416
|
-
* @
|
|
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
|
@@ -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
|
|
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
|
}
|