@mui/x-date-pickers 8.0.0-beta.0 → 8.0.0-beta.1
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/CHANGELOG.md +77 -0
- package/DateCalendar/DayCalendar.d.ts +3 -7
- package/DateCalendar/DayCalendar.js +16 -8
- package/DateCalendar/index.d.ts +0 -1
- package/DateField/useDateField.d.ts +1 -1
- package/DateField/useDateField.js +2 -16
- package/DatePicker/DatePicker.js +1 -0
- package/DateTimeField/useDateTimeField.d.ts +1 -1
- package/DateTimeField/useDateTimeField.js +2 -16
- package/DateTimePicker/DateTimePicker.js +1 -0
- package/DesktopDatePicker/DesktopDatePicker.js +1 -0
- package/DesktopDateTimePicker/DesktopDateTimePicker.js +1 -0
- package/DesktopTimePicker/DesktopTimePicker.js +1 -0
- package/MobileDatePicker/MobileDatePicker.js +1 -0
- package/MobileDateTimePicker/MobileDateTimePicker.js +1 -0
- package/MobileTimePicker/MobileTimePicker.js +1 -0
- package/PickersDay/PickersDay.d.ts +1 -72
- package/PickersDay/PickersDay.js +30 -28
- package/PickersDay/PickersDay.types.d.ts +114 -0
- package/PickersDay/PickersDay.types.js +5 -0
- package/PickersDay/index.d.ts +1 -1
- package/PickersDay/usePickerDayOwnerState.d.ts +14 -0
- package/PickersDay/usePickerDayOwnerState.js +40 -0
- package/TimeField/useTimeField.d.ts +1 -1
- package/TimeField/useTimeField.js +2 -16
- package/TimePicker/TimePicker.js +1 -0
- package/esm/DateCalendar/DayCalendar.d.ts +3 -7
- package/esm/DateCalendar/DayCalendar.js +16 -8
- package/esm/DateCalendar/index.d.ts +0 -1
- package/esm/DateField/useDateField.d.ts +1 -1
- package/esm/DateField/useDateField.js +3 -17
- package/esm/DatePicker/DatePicker.js +1 -0
- package/esm/DateTimeField/useDateTimeField.d.ts +1 -1
- package/esm/DateTimeField/useDateTimeField.js +3 -17
- package/esm/DateTimePicker/DateTimePicker.js +1 -0
- package/esm/DesktopDatePicker/DesktopDatePicker.js +1 -0
- package/esm/DesktopDateTimePicker/DesktopDateTimePicker.js +1 -0
- package/esm/DesktopTimePicker/DesktopTimePicker.js +1 -0
- package/esm/MobileDatePicker/MobileDatePicker.js +1 -0
- package/esm/MobileDateTimePicker/MobileDateTimePicker.js +1 -0
- package/esm/MobileTimePicker/MobileTimePicker.js +1 -0
- package/esm/PickersDay/PickersDay.d.ts +1 -72
- package/esm/PickersDay/PickersDay.js +30 -28
- package/esm/PickersDay/PickersDay.types.d.ts +114 -0
- package/esm/PickersDay/PickersDay.types.js +1 -0
- package/esm/PickersDay/index.d.ts +1 -1
- package/esm/PickersDay/usePickerDayOwnerState.d.ts +14 -0
- package/esm/PickersDay/usePickerDayOwnerState.js +32 -0
- package/esm/TimeField/useTimeField.d.ts +1 -1
- package/esm/TimeField/useTimeField.js +3 -17
- package/esm/TimePicker/TimePicker.js +1 -0
- package/esm/hooks/useSplitFieldProps.d.ts +1 -1
- package/esm/index.js +1 -1
- package/esm/internals/components/PickerFieldUI.d.ts +5 -5
- package/esm/internals/hooks/useField/buildSectionsFromFormat.d.ts +2 -2
- package/esm/internals/hooks/useField/buildSectionsFromFormat.js +9 -9
- package/esm/internals/hooks/useField/index.d.ts +1 -1
- package/esm/internals/hooks/useField/useField.d.ts +2 -4
- package/esm/internals/hooks/useField/useField.js +5 -229
- package/esm/internals/hooks/useField/useField.types.d.ts +48 -68
- package/esm/internals/hooks/useField/useField.utils.d.ts +2 -5
- package/esm/internals/hooks/useField/useField.utils.js +7 -92
- package/esm/internals/hooks/useField/useFieldCharacterEditing.d.ts +19 -26
- package/esm/internals/hooks/useField/useFieldCharacterEditing.js +42 -60
- package/esm/internals/hooks/useField/useFieldRootHandleKeyDown.d.ts +16 -0
- package/esm/internals/hooks/useField/useFieldRootHandleKeyDown.js +204 -0
- package/esm/internals/hooks/useField/useFieldState.d.ts +23 -13
- package/esm/internals/hooks/useField/useFieldState.js +103 -30
- package/esm/internals/hooks/useField/useFieldV6TextField.d.ts +3 -3
- package/esm/internals/hooks/useField/useFieldV6TextField.js +202 -135
- package/esm/internals/hooks/useField/useFieldV7TextField.d.ts +3 -2
- package/esm/internals/hooks/useField/useFieldV7TextField.js +217 -153
- package/esm/internals/hooks/usePicker/usePicker.types.d.ts +1 -0
- package/esm/internals/index.d.ts +2 -1
- package/esm/internals/index.js +1 -0
- package/esm/managers/useDateManager.js +3 -3
- package/esm/managers/useDateTimeManager.js +3 -3
- package/esm/managers/useTimeManager.js +3 -3
- package/esm/models/fields.d.ts +2 -2
- package/esm/models/manager.d.ts +3 -2
- package/hooks/useSplitFieldProps.d.ts +1 -1
- package/index.js +1 -1
- package/internals/components/PickerFieldUI.d.ts +5 -5
- package/internals/hooks/useField/buildSectionsFromFormat.d.ts +2 -2
- package/internals/hooks/useField/buildSectionsFromFormat.js +9 -9
- package/internals/hooks/useField/index.d.ts +1 -1
- package/internals/hooks/useField/useField.d.ts +2 -4
- package/internals/hooks/useField/useField.js +5 -231
- package/internals/hooks/useField/useField.types.d.ts +48 -68
- package/internals/hooks/useField/useField.utils.d.ts +2 -5
- package/internals/hooks/useField/useField.utils.js +8 -94
- package/internals/hooks/useField/useFieldCharacterEditing.d.ts +19 -26
- package/internals/hooks/useField/useFieldCharacterEditing.js +41 -59
- package/internals/hooks/useField/useFieldRootHandleKeyDown.d.ts +16 -0
- package/internals/hooks/useField/useFieldRootHandleKeyDown.js +210 -0
- package/internals/hooks/useField/useFieldState.d.ts +23 -13
- package/internals/hooks/useField/useFieldState.js +102 -29
- package/internals/hooks/useField/useFieldV6TextField.d.ts +3 -3
- package/internals/hooks/useField/useFieldV6TextField.js +202 -135
- package/internals/hooks/useField/useFieldV7TextField.d.ts +3 -2
- package/internals/hooks/useField/useFieldV7TextField.js +218 -154
- package/internals/hooks/usePicker/usePicker.types.d.ts +1 -0
- package/internals/index.d.ts +2 -1
- package/internals/index.js +7 -0
- package/managers/useDateManager.js +3 -3
- package/managers/useDateTimeManager.js +3 -3
- package/managers/useTimeManager.js +3 -3
- package/models/fields.d.ts +2 -2
- package/models/manager.d.ts +3 -2
- package/modern/DateCalendar/DayCalendar.d.ts +3 -7
- package/modern/DateCalendar/DayCalendar.js +16 -8
- package/modern/DateCalendar/index.d.ts +0 -1
- package/modern/DateField/useDateField.d.ts +1 -1
- package/modern/DateField/useDateField.js +3 -17
- package/modern/DatePicker/DatePicker.js +1 -0
- package/modern/DateTimeField/useDateTimeField.d.ts +1 -1
- package/modern/DateTimeField/useDateTimeField.js +3 -17
- package/modern/DateTimePicker/DateTimePicker.js +1 -0
- package/modern/DesktopDatePicker/DesktopDatePicker.js +1 -0
- package/modern/DesktopDateTimePicker/DesktopDateTimePicker.js +1 -0
- package/modern/DesktopTimePicker/DesktopTimePicker.js +1 -0
- package/modern/MobileDatePicker/MobileDatePicker.js +1 -0
- package/modern/MobileDateTimePicker/MobileDateTimePicker.js +1 -0
- package/modern/MobileTimePicker/MobileTimePicker.js +1 -0
- package/modern/PickersDay/PickersDay.d.ts +1 -72
- package/modern/PickersDay/PickersDay.js +30 -28
- package/modern/PickersDay/PickersDay.types.d.ts +114 -0
- package/modern/PickersDay/PickersDay.types.js +1 -0
- package/modern/PickersDay/index.d.ts +1 -1
- package/modern/PickersDay/usePickerDayOwnerState.d.ts +14 -0
- package/modern/PickersDay/usePickerDayOwnerState.js +32 -0
- package/modern/TimeField/useTimeField.d.ts +1 -1
- package/modern/TimeField/useTimeField.js +3 -17
- package/modern/TimePicker/TimePicker.js +1 -0
- package/modern/hooks/useSplitFieldProps.d.ts +1 -1
- package/modern/index.js +1 -1
- package/modern/internals/components/PickerFieldUI.d.ts +5 -5
- package/modern/internals/hooks/useField/buildSectionsFromFormat.d.ts +2 -2
- package/modern/internals/hooks/useField/buildSectionsFromFormat.js +9 -9
- package/modern/internals/hooks/useField/index.d.ts +1 -1
- package/modern/internals/hooks/useField/useField.d.ts +2 -4
- package/modern/internals/hooks/useField/useField.js +5 -229
- package/modern/internals/hooks/useField/useField.types.d.ts +48 -68
- package/modern/internals/hooks/useField/useField.utils.d.ts +2 -5
- package/modern/internals/hooks/useField/useField.utils.js +7 -92
- package/modern/internals/hooks/useField/useFieldCharacterEditing.d.ts +19 -26
- package/modern/internals/hooks/useField/useFieldCharacterEditing.js +42 -60
- package/modern/internals/hooks/useField/useFieldRootHandleKeyDown.d.ts +16 -0
- package/modern/internals/hooks/useField/useFieldRootHandleKeyDown.js +204 -0
- package/modern/internals/hooks/useField/useFieldState.d.ts +23 -13
- package/modern/internals/hooks/useField/useFieldState.js +103 -30
- package/modern/internals/hooks/useField/useFieldV6TextField.d.ts +3 -3
- package/modern/internals/hooks/useField/useFieldV6TextField.js +202 -135
- package/modern/internals/hooks/useField/useFieldV7TextField.d.ts +3 -2
- package/modern/internals/hooks/useField/useFieldV7TextField.js +217 -153
- package/modern/internals/hooks/usePicker/usePicker.types.d.ts +1 -0
- package/modern/internals/index.d.ts +2 -1
- package/modern/internals/index.js +1 -0
- package/modern/managers/useDateManager.js +3 -3
- package/modern/managers/useDateTimeManager.js +3 -3
- package/modern/managers/useTimeManager.js +3 -3
- package/modern/models/fields.d.ts +2 -2
- package/modern/models/manager.d.ts +3 -2
- package/package.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1,120 +1,139 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
1
2
|
import * as React from 'react';
|
|
2
3
|
import useForkRef from '@mui/utils/useForkRef';
|
|
3
4
|
import useEventCallback from '@mui/utils/useEventCallback';
|
|
4
5
|
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
|
|
6
|
+
import useTimeout from '@mui/utils/useTimeout';
|
|
5
7
|
import useId from '@mui/utils/useId';
|
|
6
8
|
import { getSectionValueNow, getSectionValueText, parseSelectedSections } from "./useField.utils.js";
|
|
7
9
|
import { getActiveElement } from "../../utils/utils.js";
|
|
10
|
+
import { useSplitFieldProps } from "../../../hooks/index.js";
|
|
8
11
|
import { usePickerTranslations } from "../../../hooks/usePickerTranslations.js";
|
|
9
12
|
import { useUtils } from "../useUtils.js";
|
|
10
|
-
|
|
13
|
+
import { useFieldCharacterEditing } from "./useFieldCharacterEditing.js";
|
|
14
|
+
import { useFieldRootHandleKeyDown } from "./useFieldRootHandleKeyDown.js";
|
|
15
|
+
import { useFieldState } from "./useFieldState.js";
|
|
16
|
+
import { useFieldInternalPropsWithDefaults } from "./useFieldInternalPropsWithDefaults.js";
|
|
17
|
+
export const useFieldV7TextField = parameters => {
|
|
18
|
+
const translations = usePickerTranslations();
|
|
19
|
+
const utils = useUtils();
|
|
20
|
+
const id = useId();
|
|
11
21
|
const {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
props,
|
|
23
|
+
manager,
|
|
24
|
+
skipContextFieldRefAssignment,
|
|
25
|
+
manager: {
|
|
26
|
+
valueType,
|
|
27
|
+
internal_fieldValueManager: fieldValueManager,
|
|
28
|
+
internal_useOpenPickerButtonAriaLabel: useOpenPickerButtonAriaLabel
|
|
29
|
+
}
|
|
30
|
+
} = parameters;
|
|
31
|
+
const {
|
|
32
|
+
internalProps,
|
|
33
|
+
forwardedProps
|
|
34
|
+
} = useSplitFieldProps(props, valueType);
|
|
35
|
+
const internalPropsWithDefaults = useFieldInternalPropsWithDefaults({
|
|
36
|
+
manager,
|
|
37
|
+
internalProps,
|
|
38
|
+
skipContextFieldRefAssignment
|
|
39
|
+
});
|
|
40
|
+
const {
|
|
41
|
+
sectionListRef: sectionListRefProp,
|
|
42
|
+
onBlur,
|
|
43
|
+
onClick,
|
|
44
|
+
onFocus,
|
|
45
|
+
onInput,
|
|
46
|
+
onPaste,
|
|
47
|
+
onKeyDown,
|
|
48
|
+
onClear,
|
|
49
|
+
clearable
|
|
50
|
+
} = forwardedProps;
|
|
51
|
+
const {
|
|
52
|
+
disabled = false,
|
|
53
|
+
readOnly = false,
|
|
54
|
+
autoFocus = false,
|
|
55
|
+
focused: focusedProp,
|
|
56
|
+
unstableFieldRef
|
|
57
|
+
} = internalPropsWithDefaults;
|
|
58
|
+
const sectionListRef = React.useRef(null);
|
|
59
|
+
const handleSectionListRef = useForkRef(sectionListRefProp, sectionListRef);
|
|
60
|
+
const stateResponse = useFieldState({
|
|
61
|
+
manager,
|
|
62
|
+
internalPropsWithDefaults,
|
|
63
|
+
forwardedProps
|
|
64
|
+
});
|
|
65
|
+
const {
|
|
66
|
+
// States and derived states
|
|
67
|
+
areAllSectionsEmpty,
|
|
68
|
+
error,
|
|
30
69
|
parsedSelectedSections,
|
|
70
|
+
sectionOrder,
|
|
71
|
+
sectionsValueBoundaries,
|
|
31
72
|
state,
|
|
32
|
-
|
|
73
|
+
value,
|
|
74
|
+
// Methods to update the states
|
|
33
75
|
clearValue,
|
|
76
|
+
clearActiveSection,
|
|
77
|
+
setCharacterQuery,
|
|
78
|
+
setSelectedSections,
|
|
34
79
|
updateSectionValue,
|
|
35
|
-
updateValueFromValueStr
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
const
|
|
41
|
-
const handleSectionListRef = useForkRef(inSectionListRef, sectionListRef);
|
|
42
|
-
const translations = usePickerTranslations();
|
|
43
|
-
const utils = useUtils();
|
|
44
|
-
const id = useId();
|
|
80
|
+
updateValueFromValueStr
|
|
81
|
+
} = stateResponse;
|
|
82
|
+
const applyCharacterEditing = useFieldCharacterEditing({
|
|
83
|
+
stateResponse
|
|
84
|
+
});
|
|
85
|
+
const openPickerAriaLabel = useOpenPickerButtonAriaLabel(value);
|
|
45
86
|
const [focused, setFocused] = React.useState(false);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
87
|
+
function syncSelectionToDOM() {
|
|
88
|
+
if (!sectionListRef.current) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const selection = document.getSelection();
|
|
92
|
+
if (!selection) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (parsedSelectedSections == null) {
|
|
96
|
+
// If the selection contains an element inside the field, we reset it.
|
|
97
|
+
if (selection.rangeCount > 0 && sectionListRef.current.getRoot().contains(selection.getRangeAt(0).startContainer)) {
|
|
98
|
+
selection.removeAllRanges();
|
|
54
99
|
}
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
if (selection.rangeCount > 0 && sectionListRef.current.getRoot().contains(selection.getRangeAt(0).startContainer)) {
|
|
58
|
-
selection.removeAllRanges();
|
|
59
|
-
}
|
|
60
|
-
if (focused) {
|
|
61
|
-
sectionListRef.current.getRoot().blur();
|
|
62
|
-
}
|
|
63
|
-
return;
|
|
100
|
+
if (focused) {
|
|
101
|
+
sectionListRef.current.getRoot().blur();
|
|
64
102
|
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
65
105
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
106
|
+
// On multi input range pickers we want to update selection range only for the active input
|
|
107
|
+
if (!sectionListRef.current.getRoot().contains(getActiveElement(document))) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const range = new window.Range();
|
|
111
|
+
let target;
|
|
112
|
+
if (parsedSelectedSections === 'all') {
|
|
113
|
+
target = sectionListRef.current.getRoot();
|
|
114
|
+
} else {
|
|
115
|
+
const section = state.sections[parsedSelectedSections];
|
|
116
|
+
if (section.type === 'empty') {
|
|
117
|
+
target = sectionListRef.current.getSectionContainer(parsedSelectedSections);
|
|
74
118
|
} else {
|
|
75
|
-
|
|
76
|
-
if (section.type === 'empty') {
|
|
77
|
-
target = sectionListRef.current.getSectionContainer(parsedSelectedSections);
|
|
78
|
-
} else {
|
|
79
|
-
target = sectionListRef.current.getSectionContent(parsedSelectedSections);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
range.selectNodeContents(target);
|
|
83
|
-
target.focus();
|
|
84
|
-
selection.removeAllRanges();
|
|
85
|
-
selection.addRange(range);
|
|
86
|
-
},
|
|
87
|
-
getActiveSectionIndexFromDOM: () => {
|
|
88
|
-
const activeElement = getActiveElement(document);
|
|
89
|
-
if (!activeElement || !sectionListRef.current || !sectionListRef.current.getRoot().contains(activeElement)) {
|
|
90
|
-
return null;
|
|
119
|
+
target = sectionListRef.current.getSectionContent(parsedSelectedSections);
|
|
91
120
|
}
|
|
92
|
-
return sectionListRef.current.getSectionIndexFromDOMElement(activeElement);
|
|
93
|
-
},
|
|
94
|
-
focusField: (newSelectedSections = 0) => {
|
|
95
|
-
if (!sectionListRef.current ||
|
|
96
|
-
// if the field is already focused, we don't need to focus it again
|
|
97
|
-
interactions.getActiveSectionIndexFromDOM() != null) {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
const newParsedSelectedSections = parseSelectedSections(newSelectedSections, state.sections);
|
|
101
|
-
setFocused(true);
|
|
102
|
-
sectionListRef.current.getSectionContent(newParsedSelectedSections).focus();
|
|
103
|
-
},
|
|
104
|
-
setSelectedSections: newSelectedSections => {
|
|
105
|
-
if (!sectionListRef.current) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
const newParsedSelectedSections = parseSelectedSections(newSelectedSections, state.sections);
|
|
109
|
-
const newActiveSectionIndex = newParsedSelectedSections === 'all' ? 0 : newParsedSelectedSections;
|
|
110
|
-
setFocused(newActiveSectionIndex !== null);
|
|
111
|
-
setSelectedSections(newSelectedSections);
|
|
112
|
-
},
|
|
113
|
-
isFieldFocused: () => {
|
|
114
|
-
const activeElement = getActiveElement(document);
|
|
115
|
-
return !!sectionListRef.current && sectionListRef.current.getRoot().contains(activeElement);
|
|
116
121
|
}
|
|
117
|
-
|
|
122
|
+
range.selectNodeContents(target);
|
|
123
|
+
target.focus();
|
|
124
|
+
selection.removeAllRanges();
|
|
125
|
+
selection.addRange(range);
|
|
126
|
+
}
|
|
127
|
+
function focusField(newSelectedSections = 0) {
|
|
128
|
+
if (!sectionListRef.current ||
|
|
129
|
+
// if the field is already focused, we don't need to focus it again
|
|
130
|
+
getActiveSectionIndex(sectionListRef) != null) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const newParsedSelectedSections = parseSelectedSections(newSelectedSections, state.sections);
|
|
134
|
+
setFocused(true);
|
|
135
|
+
sectionListRef.current.getSectionContent(newParsedSelectedSections).focus();
|
|
136
|
+
}
|
|
118
137
|
|
|
119
138
|
/**
|
|
120
139
|
* If a section content has been updated with a value we don't want to keep,
|
|
@@ -126,8 +145,9 @@ export const useFieldV7TextField = params => {
|
|
|
126
145
|
}
|
|
127
146
|
const section = state.sections[sectionIndex];
|
|
128
147
|
sectionListRef.current.getSectionContent(sectionIndex).innerHTML = section.value || section.placeholder;
|
|
129
|
-
|
|
148
|
+
syncSelectionToDOM();
|
|
130
149
|
});
|
|
150
|
+
const containerClickTimeout = useTimeout();
|
|
131
151
|
const handleContainerClick = useEventCallback((event, ...args) => {
|
|
132
152
|
// The click event on the clear button would propagate to the input, trigger this handler and result in a wrong section selection.
|
|
133
153
|
// We avoid this by checking if the call of `handleContainerClick` is actually intended, or a side effect.
|
|
@@ -137,7 +157,7 @@ export const useFieldV7TextField = params => {
|
|
|
137
157
|
setFocused(true);
|
|
138
158
|
onClick?.(event, ...args);
|
|
139
159
|
if (parsedSelectedSections === 'all') {
|
|
140
|
-
|
|
160
|
+
containerClickTimeout.start(0, () => {
|
|
141
161
|
const cursorPosition = document.getSelection().getRangeAt(0).startOffset;
|
|
142
162
|
if (cursorPosition === 0) {
|
|
143
163
|
setSelectedSections(sectionOrder.startIndex);
|
|
@@ -170,9 +190,8 @@ export const useFieldV7TextField = params => {
|
|
|
170
190
|
const target = event.target;
|
|
171
191
|
const keyPressed = target.textContent ?? '';
|
|
172
192
|
sectionListRef.current.getRoot().innerHTML = state.sections.map(section => `${section.startSeparator}${section.value || section.placeholder}${section.endSeparator}`).join('');
|
|
173
|
-
|
|
193
|
+
syncSelectionToDOM();
|
|
174
194
|
if (keyPressed.length === 0 || keyPressed.charCodeAt(0) === 10) {
|
|
175
|
-
resetCharacterQuery();
|
|
176
195
|
clearValue();
|
|
177
196
|
setSelectedSections('all');
|
|
178
197
|
} else if (keyPressed.length > 1) {
|
|
@@ -195,7 +214,7 @@ export const useFieldV7TextField = params => {
|
|
|
195
214
|
}
|
|
196
215
|
const pastedValue = event.clipboardData.getData('text');
|
|
197
216
|
event.preventDefault();
|
|
198
|
-
|
|
217
|
+
setCharacterQuery(null);
|
|
199
218
|
updateValueFromValueStr(pastedValue);
|
|
200
219
|
});
|
|
201
220
|
const handleContainerFocus = useEventCallback(event => {
|
|
@@ -252,7 +271,7 @@ export const useFieldV7TextField = params => {
|
|
|
252
271
|
const digitsAndLetterOnly = /^(([a-zA-Z]+)|)([0-9]+)(([a-zA-Z]+)|)$/.test(pastedValue);
|
|
253
272
|
const isValidPastedValue = activeSection.contentType === 'letter' && lettersOnly || activeSection.contentType === 'digit' && digitsOnly || activeSection.contentType === 'digit-with-letter' && digitsAndLetterOnly;
|
|
254
273
|
if (isValidPastedValue) {
|
|
255
|
-
|
|
274
|
+
setCharacterQuery(null);
|
|
256
275
|
updateSectionValue({
|
|
257
276
|
section: activeSection,
|
|
258
277
|
newSectionValue: pastedValue,
|
|
@@ -261,7 +280,7 @@ export const useFieldV7TextField = params => {
|
|
|
261
280
|
}
|
|
262
281
|
// If the pasted value corresponds to a single section, but not the expected type, we skip the modification
|
|
263
282
|
else if (!lettersOnly && !digitsOnly) {
|
|
264
|
-
|
|
283
|
+
setCharacterQuery(null);
|
|
265
284
|
updateValueFromValueStr(pastedValue);
|
|
266
285
|
}
|
|
267
286
|
});
|
|
@@ -291,7 +310,6 @@ export const useFieldV7TextField = params => {
|
|
|
291
310
|
revertDOMSectionChange(sectionIndex);
|
|
292
311
|
return;
|
|
293
312
|
}
|
|
294
|
-
resetCharacterQuery();
|
|
295
313
|
revertDOMSectionChange(sectionIndex);
|
|
296
314
|
clearActiveSection();
|
|
297
315
|
return;
|
|
@@ -304,33 +322,35 @@ export const useFieldV7TextField = params => {
|
|
|
304
322
|
// The DOM value needs to remain the one React is expecting.
|
|
305
323
|
revertDOMSectionChange(sectionIndex);
|
|
306
324
|
});
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
if (
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
domElement.focus();
|
|
317
|
-
}
|
|
325
|
+
const handleClear = useEventCallback((event, ...args) => {
|
|
326
|
+
event.preventDefault();
|
|
327
|
+
onClear?.(event, ...args);
|
|
328
|
+
clearValue();
|
|
329
|
+
if (!isFieldFocused(sectionListRef)) {
|
|
330
|
+
// setSelectedSections is called internally
|
|
331
|
+
focusField(0);
|
|
332
|
+
} else {
|
|
333
|
+
setSelectedSections(sectionOrder.startIndex);
|
|
318
334
|
}
|
|
319
|
-
}
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}, [sectionsValueBoundaries, state.sections]);
|
|
335
|
+
});
|
|
336
|
+
const handleContainerKeyDown = useFieldRootHandleKeyDown({
|
|
337
|
+
manager,
|
|
338
|
+
internalPropsWithDefaults,
|
|
339
|
+
stateResponse
|
|
340
|
+
});
|
|
341
|
+
const wrappedHandleContainerKeyDown = useEventCallback(event => {
|
|
342
|
+
onKeyDown?.(event);
|
|
343
|
+
handleContainerKeyDown(event);
|
|
344
|
+
});
|
|
330
345
|
const isContainerEditable = parsedSelectedSections === 'all';
|
|
331
346
|
const elements = React.useMemo(() => {
|
|
332
347
|
return state.sections.map((section, index) => {
|
|
333
348
|
const isEditable = !isContainerEditable && !disabled && !readOnly;
|
|
349
|
+
const sectionBoundaries = sectionsValueBoundaries[section.type]({
|
|
350
|
+
currentDate: fieldValueManager.getDateFromSection(value, section),
|
|
351
|
+
contentType: section.contentType,
|
|
352
|
+
format: section.format
|
|
353
|
+
});
|
|
334
354
|
return {
|
|
335
355
|
container: {
|
|
336
356
|
'data-sectionindex': index,
|
|
@@ -344,8 +364,8 @@ export const useFieldV7TextField = params => {
|
|
|
344
364
|
'aria-labelledby': `${id}-${section.type}`,
|
|
345
365
|
'aria-readonly': readOnly,
|
|
346
366
|
'aria-valuenow': getSectionValueNow(section, utils),
|
|
347
|
-
'aria-valuemin': sectionBoundaries
|
|
348
|
-
'aria-valuemax': sectionBoundaries
|
|
367
|
+
'aria-valuemin': sectionBoundaries.minimum,
|
|
368
|
+
'aria-valuemax': sectionBoundaries.maximum,
|
|
349
369
|
'aria-valuetext': section.value ? getSectionValueText(section, utils) : translations.empty,
|
|
350
370
|
'aria-label': translations[section.type],
|
|
351
371
|
'aria-disabled': disabled,
|
|
@@ -369,7 +389,7 @@ export const useFieldV7TextField = params => {
|
|
|
369
389
|
}
|
|
370
390
|
};
|
|
371
391
|
});
|
|
372
|
-
}, [
|
|
392
|
+
}, [disabled, fieldValueManager, getInputContainerClickHandler, getInputContentFocusHandler, handleInputContentDragOver, handleInputContentInput, handleInputContentMouseUp, handleInputContentPaste, id, isContainerEditable, readOnly, sectionsValueBoundaries, state.sections, translations, utils, value]);
|
|
373
393
|
const handleValueStrChange = useEventCallback(event => {
|
|
374
394
|
updateValueFromValueStr(event.target.value);
|
|
375
395
|
});
|
|
@@ -383,28 +403,72 @@ export const useFieldV7TextField = params => {
|
|
|
383
403
|
}
|
|
384
404
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
385
405
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
sectionListRef
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
onInput: handleContainerInput,
|
|
398
|
-
onPaste: handleContainerPaste,
|
|
399
|
-
// Additional
|
|
400
|
-
enableAccessibleFieldDOMStructure: true,
|
|
401
|
-
elements,
|
|
402
|
-
// TODO v7: Try to set to undefined when there is a section selected.
|
|
403
|
-
tabIndex: parsedSelectedSections === 0 ? -1 : 0,
|
|
404
|
-
contentEditable: isContainerEditable,
|
|
405
|
-
value: valueStr,
|
|
406
|
-
onChange: handleValueStrChange,
|
|
407
|
-
areAllSectionsEmpty
|
|
406
|
+
useEnhancedEffect(() => {
|
|
407
|
+
if (!focused || !sectionListRef.current) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
if (parsedSelectedSections === 'all') {
|
|
411
|
+
sectionListRef.current.getRoot().focus();
|
|
412
|
+
} else if (typeof parsedSelectedSections === 'number') {
|
|
413
|
+
const domElement = sectionListRef.current.getSectionContent(parsedSelectedSections);
|
|
414
|
+
if (domElement) {
|
|
415
|
+
domElement.focus();
|
|
416
|
+
}
|
|
408
417
|
}
|
|
409
|
-
};
|
|
410
|
-
|
|
418
|
+
}, [parsedSelectedSections, focused]);
|
|
419
|
+
useEnhancedEffect(() => {
|
|
420
|
+
syncSelectionToDOM();
|
|
421
|
+
});
|
|
422
|
+
React.useImperativeHandle(unstableFieldRef, () => ({
|
|
423
|
+
getSections: () => state.sections,
|
|
424
|
+
getActiveSectionIndex: () => getActiveSectionIndex(sectionListRef),
|
|
425
|
+
setSelectedSections: newSelectedSections => {
|
|
426
|
+
if (!sectionListRef.current) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const newParsedSelectedSections = parseSelectedSections(newSelectedSections, state.sections);
|
|
430
|
+
const newActiveSectionIndex = newParsedSelectedSections === 'all' ? 0 : newParsedSelectedSections;
|
|
431
|
+
setFocused(newActiveSectionIndex !== null);
|
|
432
|
+
setSelectedSections(newSelectedSections);
|
|
433
|
+
},
|
|
434
|
+
focusField,
|
|
435
|
+
isFieldFocused: () => isFieldFocused(sectionListRef)
|
|
436
|
+
}));
|
|
437
|
+
return _extends({}, forwardedProps, {
|
|
438
|
+
error,
|
|
439
|
+
clearable: Boolean(clearable && !areAllSectionsEmpty && !readOnly && !disabled),
|
|
440
|
+
focused: focusedProp ?? focused,
|
|
441
|
+
sectionListRef: handleSectionListRef,
|
|
442
|
+
onBlur: handleContainerBlur,
|
|
443
|
+
onClick: handleContainerClick,
|
|
444
|
+
onFocus: handleContainerFocus,
|
|
445
|
+
onInput: handleContainerInput,
|
|
446
|
+
onPaste: handleContainerPaste,
|
|
447
|
+
onKeyDown: wrappedHandleContainerKeyDown,
|
|
448
|
+
onClear: handleClear,
|
|
449
|
+
// Additional
|
|
450
|
+
enableAccessibleFieldDOMStructure: true,
|
|
451
|
+
elements,
|
|
452
|
+
// TODO v7: Try to set to undefined when there is a section selected.
|
|
453
|
+
tabIndex: parsedSelectedSections === 0 ? -1 : 0,
|
|
454
|
+
contentEditable: isContainerEditable,
|
|
455
|
+
value: valueStr,
|
|
456
|
+
onChange: handleValueStrChange,
|
|
457
|
+
areAllSectionsEmpty,
|
|
458
|
+
disabled,
|
|
459
|
+
readOnly,
|
|
460
|
+
autoFocus,
|
|
461
|
+
openPickerAriaLabel
|
|
462
|
+
});
|
|
463
|
+
};
|
|
464
|
+
function getActiveSectionIndex(sectionListRef) {
|
|
465
|
+
const activeElement = getActiveElement(document);
|
|
466
|
+
if (!activeElement || !sectionListRef.current || !sectionListRef.current.getRoot().contains(activeElement)) {
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
return sectionListRef.current.getSectionIndexFromDOMElement(activeElement);
|
|
470
|
+
}
|
|
471
|
+
function isFieldFocused(sectionListRef) {
|
|
472
|
+
const activeElement = getActiveElement(document);
|
|
473
|
+
return !!sectionListRef.current && sectionListRef.current.getRoot().contains(activeElement);
|
|
474
|
+
}
|
|
@@ -89,6 +89,7 @@ export interface UsePickerNonStaticProps extends Omit<PickerFieldPrivateContextV
|
|
|
89
89
|
format?: string;
|
|
90
90
|
/**
|
|
91
91
|
* If `true`, the button to open the Picker will not be rendered (it will only render the field).
|
|
92
|
+
* @deprecated Use the [field component](https://next.mui.com/x/react-date-pickers/fields/) instead.
|
|
92
93
|
* @default false
|
|
93
94
|
*/
|
|
94
95
|
disableOpenPicker?: boolean;
|
|
@@ -26,7 +26,7 @@ export { DAY_MARGIN, DIALOG_WIDTH, VIEW_HEIGHT, MULTI_SECTION_CLOCK_SECTION_WIDT
|
|
|
26
26
|
export { useControlledValue } from "./hooks/useControlledValue.js";
|
|
27
27
|
export type { DesktopOnlyPickerProps } from './hooks/useDesktopPicker';
|
|
28
28
|
export { useField, useFieldInternalPropsWithDefaults, createDateStrForV7HiddenInputFromSections, createDateStrForV6InputFromSections } from "./hooks/useField/index.js";
|
|
29
|
-
export type { UseFieldInternalProps,
|
|
29
|
+
export type { UseFieldInternalProps, UseFieldParameters, UseFieldReturnValue, FieldValueManager, FieldChangeHandler, FieldChangeHandlerContext } from './hooks/useField';
|
|
30
30
|
export { useFieldOwnerState } from "./hooks/useFieldOwnerState.js";
|
|
31
31
|
export type { MobileOnlyPickerProps } from './hooks/useMobilePicker';
|
|
32
32
|
export { useNullableFieldPrivateContext } from "./hooks/useNullableFieldPrivateContext.js";
|
|
@@ -65,6 +65,7 @@ export type { DayCalendarProps, DayCalendarSlots, DayCalendarSlotProps, Exported
|
|
|
65
65
|
export type { ExportedDateCalendarProps } from '../DateCalendar/DateCalendar.types';
|
|
66
66
|
export { useCalendarState } from "../DateCalendar/useCalendarState.js";
|
|
67
67
|
export { DateTimePickerToolbarOverrideContext } from "../DateTimePicker/DateTimePickerToolbar.js";
|
|
68
|
+
export { usePickerDayOwnerState } from "../PickersDay/usePickerDayOwnerState.js";
|
|
68
69
|
export { getDateFieldInternalPropsDefaults } from "../managers/useDateManager.js";
|
|
69
70
|
export { getTimeFieldInternalPropsDefaults } from "../managers/useTimeManager.js";
|
|
70
71
|
export { getDateTimeFieldInternalPropsDefaults } from "../managers/useDateTimeManager.js";
|
|
@@ -33,6 +33,7 @@ export { applyDefaultViewProps } from "./utils/views.js";
|
|
|
33
33
|
export { DayCalendar } from "../DateCalendar/DayCalendar.js";
|
|
34
34
|
export { useCalendarState } from "../DateCalendar/useCalendarState.js";
|
|
35
35
|
export { DateTimePickerToolbarOverrideContext } from "../DateTimePicker/DateTimePickerToolbar.js";
|
|
36
|
+
export { usePickerDayOwnerState } from "../PickersDay/usePickerDayOwnerState.js";
|
|
36
37
|
export { getDateFieldInternalPropsDefaults } from "../managers/useDateManager.js";
|
|
37
38
|
export { getTimeFieldInternalPropsDefaults } from "../managers/useTimeManager.js";
|
|
38
39
|
export { getDateTimeFieldInternalPropsDefaults } from "../managers/useDateTimeManager.js";
|
|
@@ -29,13 +29,13 @@ export function useDateManager(parameters = {}) {
|
|
|
29
29
|
internal_useOpenPickerButtonAriaLabel: useOpenPickerButtonAriaLabel
|
|
30
30
|
}), [enableAccessibleFieldDOMStructure]);
|
|
31
31
|
}
|
|
32
|
-
function useOpenPickerButtonAriaLabel() {
|
|
32
|
+
function useOpenPickerButtonAriaLabel(value) {
|
|
33
33
|
const utils = useUtils();
|
|
34
34
|
const translations = usePickerTranslations();
|
|
35
|
-
return React.
|
|
35
|
+
return React.useMemo(() => {
|
|
36
36
|
const formattedValue = utils.isValid(value) ? utils.format(value, 'fullDate') : null;
|
|
37
37
|
return translations.openDatePickerDialogue(formattedValue);
|
|
38
|
-
}, [translations, utils]);
|
|
38
|
+
}, [value, translations, utils]);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/**
|
|
@@ -29,13 +29,13 @@ export function useDateTimeManager(parameters = {}) {
|
|
|
29
29
|
internal_useOpenPickerButtonAriaLabel: useOpenPickerButtonAriaLabel
|
|
30
30
|
}), [enableAccessibleFieldDOMStructure]);
|
|
31
31
|
}
|
|
32
|
-
function useOpenPickerButtonAriaLabel() {
|
|
32
|
+
function useOpenPickerButtonAriaLabel(value) {
|
|
33
33
|
const utils = useUtils();
|
|
34
34
|
const translations = usePickerTranslations();
|
|
35
|
-
return React.
|
|
35
|
+
return React.useMemo(() => {
|
|
36
36
|
const formattedValue = utils.isValid(value) ? utils.format(value, 'fullDate') : null;
|
|
37
37
|
return translations.openDatePickerDialogue(formattedValue);
|
|
38
|
-
}, [translations, utils]);
|
|
38
|
+
}, [value, translations, utils]);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/**
|
|
@@ -28,14 +28,14 @@ export function useTimeManager(parameters = {}) {
|
|
|
28
28
|
}), [ampm, enableAccessibleFieldDOMStructure]);
|
|
29
29
|
}
|
|
30
30
|
function createUseOpenPickerButtonAriaLabel(ampm) {
|
|
31
|
-
return function useOpenPickerButtonAriaLabel() {
|
|
31
|
+
return function useOpenPickerButtonAriaLabel(value) {
|
|
32
32
|
const utils = useUtils();
|
|
33
33
|
const translations = usePickerTranslations();
|
|
34
|
-
return React.
|
|
34
|
+
return React.useMemo(() => {
|
|
35
35
|
const formatKey = ampm ?? utils.is12HourCycleInCurrentLocale() ? 'fullTime12h' : 'fullTime24h';
|
|
36
36
|
const formattedValue = utils.isValid(value) ? utils.format(value, formatKey) : null;
|
|
37
37
|
return translations.openTimePickerDialogue(formattedValue);
|
|
38
|
-
}, [translations, utils]);
|
|
38
|
+
}, [value, translations, utils]);
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { TextFieldProps } from '@mui/material/TextField';
|
|
3
3
|
import type { ExportedPickersSectionListProps } from '../PickersSectionList';
|
|
4
|
-
import type { UseFieldInternalProps,
|
|
4
|
+
import type { UseFieldInternalProps, UseFieldReturnValue } from '../internals/hooks/useField';
|
|
5
5
|
import type { PickersTextFieldProps } from '../PickersTextField';
|
|
6
6
|
import { BaseSingleInputFieldProps, FieldRangeSection, PickerRangeValue, PickerValidValue } from "../internals/models/index.js";
|
|
7
7
|
import { PickerOwnerState } from "./pickers.js";
|
|
@@ -131,7 +131,7 @@ export type PickerFieldSlotProps<TValue extends PickerValidValue, TEnableAccessi
|
|
|
131
131
|
* Props the text field receives when used inside a single input Picker.
|
|
132
132
|
* Only contains what the MUI components are passing to the text field, not what users can pass using the `props.slotProps.field` and `props.slotProps.textField`.
|
|
133
133
|
*/
|
|
134
|
-
export type BaseSingleInputPickersTextFieldProps<TEnableAccessibleFieldDOMStructure extends boolean> = Omit<
|
|
134
|
+
export type BaseSingleInputPickersTextFieldProps<TEnableAccessibleFieldDOMStructure extends boolean> = Omit<UseFieldReturnValue<TEnableAccessibleFieldDOMStructure, BaseSingleInputFieldProps>, 'slots' | 'slotProps' | 'clearable' | 'onClear' | 'openPickerButtonPosition' | 'clearButtonPosition' | 'openPickerAriaLabel'>;
|
|
135
135
|
/**
|
|
136
136
|
* Props the built-in text field component can receive.
|
|
137
137
|
*/
|
|
@@ -72,9 +72,10 @@ export interface PickerManager<TValue extends PickerValidValue, TEnableAccessibl
|
|
|
72
72
|
internal_applyDefaultsToFieldInternalProps: (parameters: ApplyDefaultsToFieldInternalPropsParameters<TFieldInternalProps>) => UseFieldInternalProps<TValue, TEnableAccessibleFieldDOMStructure, TError> & TValidationProps;
|
|
73
73
|
/**
|
|
74
74
|
* Returns a hook that creates the aria-label to apply on the button that opens the Picker.
|
|
75
|
-
* @
|
|
75
|
+
* @param {TValue} value The value of the Picker.
|
|
76
|
+
* @returns {string} The aria-label to apply on the button that opens the Picker.
|
|
76
77
|
*/
|
|
77
|
-
internal_useOpenPickerButtonAriaLabel: (
|
|
78
|
+
internal_useOpenPickerButtonAriaLabel: (value: TValue) => string;
|
|
78
79
|
}
|
|
79
80
|
interface ApplyDefaultsToFieldInternalPropsParameters<TFieldInternalProps extends {}> extends UseLocalizationContextReturnValue {
|
|
80
81
|
internalProps: TFieldInternalProps;
|