@mui/x-date-pickers 8.0.0-beta.0 → 8.0.0-beta.2
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 +171 -0
- package/DateCalendar/DateCalendar.js +4 -8
- package/DateCalendar/DayCalendar.d.ts +3 -7
- package/DateCalendar/DayCalendar.js +18 -10
- 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/DatePicker/shared.js +3 -9
- package/DateTimeField/useDateTimeField.d.ts +1 -1
- package/DateTimeField/useDateTimeField.js +2 -16
- package/DateTimePicker/DateTimePicker.js +1 -0
- package/DateTimePicker/shared.js +3 -13
- 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/MonthCalendar/MonthCalendar.js +4 -9
- 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/PickersSectionList/PickersSectionList.d.ts +1 -1
- package/PickersSectionList/PickersSectionList.types.d.ts +2 -6
- package/TimeField/useTimeField.d.ts +1 -1
- package/TimeField/useTimeField.js +2 -16
- package/TimePicker/TimePicker.js +1 -0
- package/TimePicker/shared.js +3 -3
- package/YearCalendar/YearCalendar.js +4 -10
- package/esm/DateCalendar/DateCalendar.js +6 -10
- package/esm/DateCalendar/DayCalendar.d.ts +3 -7
- package/esm/DateCalendar/DayCalendar.js +18 -10
- 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/DatePicker/shared.js +3 -9
- package/esm/DateTimeField/useDateTimeField.d.ts +1 -1
- package/esm/DateTimeField/useDateTimeField.js +3 -17
- package/esm/DateTimePicker/DateTimePicker.js +1 -0
- package/esm/DateTimePicker/shared.js +4 -14
- 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/MonthCalendar/MonthCalendar.js +6 -11
- 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/PickersSectionList/PickersSectionList.d.ts +1 -1
- package/esm/PickersSectionList/PickersSectionList.types.d.ts +2 -6
- package/esm/TimeField/useTimeField.d.ts +1 -1
- package/esm/TimeField/useTimeField.js +3 -17
- package/esm/TimePicker/TimePicker.js +1 -0
- package/esm/TimePicker/shared.js +3 -3
- package/esm/YearCalendar/YearCalendar.js +5 -11
- 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/syncSelectionToDOM.d.ts +9 -0
- package/esm/internals/hooks/useField/syncSelectionToDOM.js +50 -0
- 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 +55 -68
- package/esm/internals/hooks/useField/useField.utils.d.ts +3 -8
- package/esm/internals/hooks/useField/useField.utils.js +7 -149
- package/esm/internals/hooks/useField/useFieldCharacterEditing.d.ts +19 -26
- package/esm/internals/hooks/useField/useFieldCharacterEditing.js +42 -60
- package/esm/internals/hooks/useField/useFieldHiddenInputProps.d.ts +20 -0
- package/esm/internals/hooks/useField/useFieldHiddenInputProps.js +31 -0
- package/esm/internals/hooks/useField/useFieldInternalPropsWithDefaults.js +8 -10
- package/esm/internals/hooks/useField/useFieldRootHandleKeyDown.d.ts +16 -0
- package/esm/internals/hooks/useField/useFieldRootHandleKeyDown.js +205 -0
- package/esm/internals/hooks/useField/useFieldRootProps.d.ts +32 -0
- package/esm/internals/hooks/useField/useFieldRootProps.js +150 -0
- package/esm/internals/hooks/useField/useFieldSectionContainerProps.d.ts +15 -0
- package/esm/internals/hooks/useField/useFieldSectionContainerProps.js +29 -0
- package/esm/internals/hooks/useField/useFieldSectionContentProps.d.ts +23 -0
- package/esm/internals/hooks/useField/useFieldSectionContentProps.js +226 -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 +200 -367
- package/esm/internals/hooks/usePicker/usePicker.types.d.ts +1 -0
- package/esm/internals/index.d.ts +6 -5
- package/esm/internals/index.js +4 -3
- package/esm/locales/deDE.js +2 -3
- package/esm/managers/useDateManager.d.ts +4 -13
- package/esm/managers/useDateManager.js +21 -31
- package/esm/managers/useDateTimeManager.d.ts +4 -13
- package/esm/managers/useDateTimeManager.js +26 -36
- package/esm/managers/useTimeManager.d.ts +4 -13
- package/esm/managers/useTimeManager.js +17 -27
- package/esm/models/fields.d.ts +2 -2
- package/esm/models/manager.d.ts +6 -10
- package/esm/validation/validateDate.js +3 -4
- 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/syncSelectionToDOM.d.ts +9 -0
- package/internals/hooks/useField/syncSelectionToDOM.js +56 -0
- 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 +55 -68
- package/internals/hooks/useField/useField.utils.d.ts +3 -8
- package/internals/hooks/useField/useField.utils.js +9 -154
- package/internals/hooks/useField/useFieldCharacterEditing.d.ts +19 -26
- package/internals/hooks/useField/useFieldCharacterEditing.js +41 -59
- package/internals/hooks/useField/useFieldHiddenInputProps.d.ts +20 -0
- package/internals/hooks/useField/useFieldHiddenInputProps.js +39 -0
- package/internals/hooks/useField/useFieldInternalPropsWithDefaults.js +8 -10
- package/internals/hooks/useField/useFieldRootHandleKeyDown.d.ts +16 -0
- package/internals/hooks/useField/useFieldRootHandleKeyDown.js +211 -0
- package/internals/hooks/useField/useFieldRootProps.d.ts +32 -0
- package/internals/hooks/useField/useFieldRootProps.js +156 -0
- package/internals/hooks/useField/useFieldSectionContainerProps.d.ts +15 -0
- package/internals/hooks/useField/useFieldSectionContainerProps.js +37 -0
- package/internals/hooks/useField/useFieldSectionContentProps.d.ts +23 -0
- package/internals/hooks/useField/useFieldSectionContentProps.js +234 -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 +200 -367
- package/internals/hooks/usePicker/usePicker.types.d.ts +1 -0
- package/internals/index.d.ts +6 -5
- package/internals/index.js +25 -18
- package/locales/deDE.js +2 -3
- package/managers/useDateManager.d.ts +4 -13
- package/managers/useDateManager.js +21 -31
- package/managers/useDateTimeManager.d.ts +4 -13
- package/managers/useDateTimeManager.js +26 -36
- package/managers/useTimeManager.d.ts +4 -13
- package/managers/useTimeManager.js +18 -28
- package/models/fields.d.ts +2 -2
- package/models/manager.d.ts +6 -10
- package/modern/DateCalendar/DateCalendar.js +6 -10
- package/modern/DateCalendar/DayCalendar.d.ts +3 -7
- package/modern/DateCalendar/DayCalendar.js +18 -10
- 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/DatePicker/shared.js +3 -9
- package/modern/DateTimeField/useDateTimeField.d.ts +1 -1
- package/modern/DateTimeField/useDateTimeField.js +3 -17
- package/modern/DateTimePicker/DateTimePicker.js +1 -0
- package/modern/DateTimePicker/shared.js +4 -14
- 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/MonthCalendar/MonthCalendar.js +6 -11
- 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/PickersSectionList/PickersSectionList.d.ts +1 -1
- package/modern/PickersSectionList/PickersSectionList.types.d.ts +2 -6
- package/modern/TimeField/useTimeField.d.ts +1 -1
- package/modern/TimeField/useTimeField.js +3 -17
- package/modern/TimePicker/TimePicker.js +1 -0
- package/modern/TimePicker/shared.js +3 -3
- package/modern/YearCalendar/YearCalendar.js +5 -11
- 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/syncSelectionToDOM.d.ts +9 -0
- package/modern/internals/hooks/useField/syncSelectionToDOM.js +50 -0
- 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 +55 -68
- package/modern/internals/hooks/useField/useField.utils.d.ts +3 -8
- package/modern/internals/hooks/useField/useField.utils.js +7 -149
- package/modern/internals/hooks/useField/useFieldCharacterEditing.d.ts +19 -26
- package/modern/internals/hooks/useField/useFieldCharacterEditing.js +42 -60
- package/modern/internals/hooks/useField/useFieldHiddenInputProps.d.ts +20 -0
- package/modern/internals/hooks/useField/useFieldHiddenInputProps.js +31 -0
- package/modern/internals/hooks/useField/useFieldInternalPropsWithDefaults.js +8 -10
- package/modern/internals/hooks/useField/useFieldRootHandleKeyDown.d.ts +16 -0
- package/modern/internals/hooks/useField/useFieldRootHandleKeyDown.js +205 -0
- package/modern/internals/hooks/useField/useFieldRootProps.d.ts +32 -0
- package/modern/internals/hooks/useField/useFieldRootProps.js +150 -0
- package/modern/internals/hooks/useField/useFieldSectionContainerProps.d.ts +15 -0
- package/modern/internals/hooks/useField/useFieldSectionContainerProps.js +29 -0
- package/modern/internals/hooks/useField/useFieldSectionContentProps.d.ts +23 -0
- package/modern/internals/hooks/useField/useFieldSectionContentProps.js +226 -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 +200 -367
- package/modern/internals/hooks/usePicker/usePicker.types.d.ts +1 -0
- package/modern/internals/index.d.ts +6 -5
- package/modern/internals/index.js +4 -3
- package/modern/locales/deDE.js +2 -3
- package/modern/managers/useDateManager.d.ts +4 -13
- package/modern/managers/useDateManager.js +21 -31
- package/modern/managers/useDateTimeManager.d.ts +4 -13
- package/modern/managers/useDateTimeManager.js +26 -36
- package/modern/managers/useTimeManager.d.ts +4 -13
- package/modern/managers/useTimeManager.js +17 -27
- package/modern/models/fields.d.ts +2 -2
- package/modern/models/manager.d.ts +6 -10
- package/modern/validation/validateDate.js +3 -4
- package/package.json +2 -2
- package/tsconfig.build.tsbuildinfo +1 -1
- package/validation/validateDate.js +3 -4
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import useEventCallback from '@mui/utils/useEventCallback';
|
|
2
|
+
import useTimeout from '@mui/utils/useTimeout';
|
|
3
|
+
import { useFieldRootHandleKeyDown } from "./useFieldRootHandleKeyDown.js";
|
|
4
|
+
import { getActiveElement } from "../../utils/utils.js";
|
|
5
|
+
import { syncSelectionToDOM } from "./syncSelectionToDOM.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generate the props to pass to the root element of the field.
|
|
9
|
+
* It is not used by the non-accessible DOM structure (with an <input /> element for editing).
|
|
10
|
+
* It should be used in the MUI accessible DOM structure and the Base UI implementation.
|
|
11
|
+
* @param {UseFieldRootPropsParameters} parameters The parameters of the hook.
|
|
12
|
+
* @returns {UseFieldRootPropsReturnValue} The props to forward to the root element of the field.
|
|
13
|
+
*/
|
|
14
|
+
export function useFieldRootProps(parameters) {
|
|
15
|
+
const {
|
|
16
|
+
manager,
|
|
17
|
+
focused,
|
|
18
|
+
setFocused,
|
|
19
|
+
domGetters,
|
|
20
|
+
stateResponse,
|
|
21
|
+
applyCharacterEditing,
|
|
22
|
+
internalPropsWithDefaults,
|
|
23
|
+
stateResponse: {
|
|
24
|
+
// States and derived states
|
|
25
|
+
parsedSelectedSections,
|
|
26
|
+
sectionOrder,
|
|
27
|
+
state,
|
|
28
|
+
// Methods to update the states
|
|
29
|
+
clearValue,
|
|
30
|
+
setCharacterQuery,
|
|
31
|
+
setSelectedSections,
|
|
32
|
+
updateValueFromValueStr
|
|
33
|
+
},
|
|
34
|
+
internalPropsWithDefaults: {
|
|
35
|
+
readOnly = false
|
|
36
|
+
}
|
|
37
|
+
} = parameters;
|
|
38
|
+
|
|
39
|
+
// TODO: Inline onContainerKeyDown once the old DOM structure is removed
|
|
40
|
+
const handleKeyDown = useFieldRootHandleKeyDown({
|
|
41
|
+
manager,
|
|
42
|
+
internalPropsWithDefaults,
|
|
43
|
+
stateResponse
|
|
44
|
+
});
|
|
45
|
+
const containerClickTimeout = useTimeout();
|
|
46
|
+
const handleClick = useEventCallback(event => {
|
|
47
|
+
if (!domGetters.isReady()) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
setFocused(true);
|
|
51
|
+
if (parsedSelectedSections === 'all') {
|
|
52
|
+
containerClickTimeout.start(0, () => {
|
|
53
|
+
const cursorPosition = document.getSelection().getRangeAt(0).startOffset;
|
|
54
|
+
if (cursorPosition === 0) {
|
|
55
|
+
setSelectedSections(sectionOrder.startIndex);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
let sectionIndex = 0;
|
|
59
|
+
let cursorOnStartOfSection = 0;
|
|
60
|
+
while (cursorOnStartOfSection < cursorPosition && sectionIndex < state.sections.length) {
|
|
61
|
+
const section = state.sections[sectionIndex];
|
|
62
|
+
sectionIndex += 1;
|
|
63
|
+
cursorOnStartOfSection += `${section.startSeparator}${section.value || section.placeholder}${section.endSeparator}`.length;
|
|
64
|
+
}
|
|
65
|
+
setSelectedSections(sectionIndex - 1);
|
|
66
|
+
});
|
|
67
|
+
} else if (!focused) {
|
|
68
|
+
setFocused(true);
|
|
69
|
+
setSelectedSections(sectionOrder.startIndex);
|
|
70
|
+
} else {
|
|
71
|
+
const hasClickedOnASection = domGetters.getRoot().contains(event.target);
|
|
72
|
+
if (!hasClickedOnASection) {
|
|
73
|
+
setSelectedSections(sectionOrder.startIndex);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
const handleInput = useEventCallback(event => {
|
|
78
|
+
if (!domGetters.isReady() || parsedSelectedSections !== 'all') {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const target = event.target;
|
|
82
|
+
const keyPressed = target.textContent ?? '';
|
|
83
|
+
domGetters.getRoot().innerHTML = state.sections.map(section => `${section.startSeparator}${section.value || section.placeholder}${section.endSeparator}`).join('');
|
|
84
|
+
syncSelectionToDOM({
|
|
85
|
+
focused,
|
|
86
|
+
domGetters,
|
|
87
|
+
stateResponse
|
|
88
|
+
});
|
|
89
|
+
if (keyPressed.length === 0 || keyPressed.charCodeAt(0) === 10) {
|
|
90
|
+
clearValue();
|
|
91
|
+
setSelectedSections('all');
|
|
92
|
+
} else if (keyPressed.length > 1) {
|
|
93
|
+
updateValueFromValueStr(keyPressed);
|
|
94
|
+
} else {
|
|
95
|
+
if (parsedSelectedSections === 'all') {
|
|
96
|
+
setSelectedSections(0);
|
|
97
|
+
}
|
|
98
|
+
applyCharacterEditing({
|
|
99
|
+
keyPressed,
|
|
100
|
+
sectionIndex: 0
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
const handlePaste = useEventCallback(event => {
|
|
105
|
+
if (readOnly || parsedSelectedSections !== 'all') {
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const pastedValue = event.clipboardData.getData('text');
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
setCharacterQuery(null);
|
|
112
|
+
updateValueFromValueStr(pastedValue);
|
|
113
|
+
});
|
|
114
|
+
const handleFocus = useEventCallback(() => {
|
|
115
|
+
if (focused || !domGetters.isReady()) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const activeElement = getActiveElement(document);
|
|
119
|
+
setFocused(true);
|
|
120
|
+
const isFocusInsideASection = domGetters.getSectionIndexFromDOMElement(activeElement) != null;
|
|
121
|
+
if (!isFocusInsideASection) {
|
|
122
|
+
setSelectedSections(sectionOrder.startIndex);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
const handleBlur = useEventCallback(() => {
|
|
126
|
+
setTimeout(() => {
|
|
127
|
+
if (!domGetters.isReady()) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const activeElement = getActiveElement(document);
|
|
131
|
+
const shouldBlur = !domGetters.getRoot().contains(activeElement);
|
|
132
|
+
if (shouldBlur) {
|
|
133
|
+
setFocused(false);
|
|
134
|
+
setSelectedSections(null);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
return {
|
|
139
|
+
// Event handlers
|
|
140
|
+
onKeyDown: handleKeyDown,
|
|
141
|
+
onBlur: handleBlur,
|
|
142
|
+
onFocus: handleFocus,
|
|
143
|
+
onClick: handleClick,
|
|
144
|
+
onPaste: handlePaste,
|
|
145
|
+
onInput: handleInput,
|
|
146
|
+
// Other
|
|
147
|
+
contentEditable: parsedSelectedSections === 'all',
|
|
148
|
+
tabIndex: parsedSelectedSections === 0 ? -1 : 0 // TODO: Try to set to undefined when there is a section selected.
|
|
149
|
+
};
|
|
150
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { UseFieldStateReturnValue } from "./useFieldState.js";
|
|
3
|
+
/**
|
|
4
|
+
* Generate the props to pass to the container element of each section of the field.
|
|
5
|
+
* It is not used by the non-accessible DOM structure (with an <input /> element for editing).
|
|
6
|
+
* It should be used in the MUI accessible DOM structure and the Base UI implementation.
|
|
7
|
+
* @param {UseFieldRootPropsParameters} parameters The parameters of the hook.
|
|
8
|
+
* @returns {UseFieldRootPropsReturnValue} The props to forward to the container element of each section of the field.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useFieldSectionContainerProps(parameters: UseFieldSectionContainerPropsParameters): UseFieldSectionContainerPropsReturnValue;
|
|
11
|
+
interface UseFieldSectionContainerPropsParameters {
|
|
12
|
+
stateResponse: UseFieldStateReturnValue<any>;
|
|
13
|
+
}
|
|
14
|
+
type UseFieldSectionContainerPropsReturnValue = (sectionIndex: number) => React.HTMLAttributes<HTMLSpanElement>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import useEventCallback from '@mui/utils/useEventCallback';
|
|
3
|
+
/**
|
|
4
|
+
* Generate the props to pass to the container element of each section of the field.
|
|
5
|
+
* It is not used by the non-accessible DOM structure (with an <input /> element for editing).
|
|
6
|
+
* It should be used in the MUI accessible DOM structure and the Base UI implementation.
|
|
7
|
+
* @param {UseFieldRootPropsParameters} parameters The parameters of the hook.
|
|
8
|
+
* @returns {UseFieldRootPropsReturnValue} The props to forward to the container element of each section of the field.
|
|
9
|
+
*/
|
|
10
|
+
export function useFieldSectionContainerProps(parameters) {
|
|
11
|
+
const {
|
|
12
|
+
stateResponse: {
|
|
13
|
+
// Methods to update the states
|
|
14
|
+
setSelectedSections
|
|
15
|
+
}
|
|
16
|
+
} = parameters;
|
|
17
|
+
const createHandleClick = useEventCallback(sectionIndex => event => {
|
|
18
|
+
// The click event on the clear button would propagate to the input, trigger this handler and result in a wrong section selection.
|
|
19
|
+
// We avoid this by checking if the call to this function is actually intended, or a side effect.
|
|
20
|
+
if (event.isDefaultPrevented()) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
setSelectedSections(sectionIndex);
|
|
24
|
+
});
|
|
25
|
+
return React.useCallback(sectionIndex => ({
|
|
26
|
+
'data-sectionindex': sectionIndex,
|
|
27
|
+
onClick: createHandleClick(sectionIndex)
|
|
28
|
+
}), [createHandleClick]);
|
|
29
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { UseFieldStateReturnValue } from "./useFieldState.js";
|
|
3
|
+
import { FieldSection, PickerManager } from "../../../models/index.js";
|
|
4
|
+
import { UseFieldDOMGetters, UseFieldInternalProps } from "./useField.types.js";
|
|
5
|
+
import { UseFieldCharacterEditingReturnValue } from "./useFieldCharacterEditing.js";
|
|
6
|
+
/**
|
|
7
|
+
* Generate the props to pass to the content element of each section of the field.
|
|
8
|
+
* It is not used by the non-accessible DOM structure (with an <input /> element for editing).
|
|
9
|
+
* It should be used in the MUI accessible DOM structure and the Base UI implementation.
|
|
10
|
+
* @param {UseFieldRootPropsParameters} parameters The parameters of the hook.
|
|
11
|
+
* @returns {UseFieldRootPropsReturnValue} The props to forward to the content element of each section of the field.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useFieldSectionContentProps(parameters: UseFieldSectionContentPropsParameters): UseFieldSectionContentPropsReturnValue;
|
|
14
|
+
interface UseFieldSectionContentPropsParameters {
|
|
15
|
+
manager: PickerManager<any, any, any, any, any>;
|
|
16
|
+
stateResponse: UseFieldStateReturnValue<any>;
|
|
17
|
+
applyCharacterEditing: UseFieldCharacterEditingReturnValue;
|
|
18
|
+
internalPropsWithDefaults: UseFieldInternalProps<any, any, any>;
|
|
19
|
+
domGetters: UseFieldDOMGetters;
|
|
20
|
+
focused: boolean;
|
|
21
|
+
}
|
|
22
|
+
type UseFieldSectionContentPropsReturnValue = (section: FieldSection, sectionIndex: number) => React.HTMLAttributes<HTMLSpanElement>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import useEventCallback from '@mui/utils/useEventCallback';
|
|
3
|
+
import useId from '@mui/utils/useId';
|
|
4
|
+
import { useUtils } from "../useUtils.js";
|
|
5
|
+
import { usePickerTranslations } from "../../../hooks/index.js";
|
|
6
|
+
import { syncSelectionToDOM } from "./syncSelectionToDOM.js";
|
|
7
|
+
/**
|
|
8
|
+
* Generate the props to pass to the content element of each section of the field.
|
|
9
|
+
* It is not used by the non-accessible DOM structure (with an <input /> element for editing).
|
|
10
|
+
* It should be used in the MUI accessible DOM structure and the Base UI implementation.
|
|
11
|
+
* @param {UseFieldRootPropsParameters} parameters The parameters of the hook.
|
|
12
|
+
* @returns {UseFieldRootPropsReturnValue} The props to forward to the content element of each section of the field.
|
|
13
|
+
*/
|
|
14
|
+
export function useFieldSectionContentProps(parameters) {
|
|
15
|
+
const utils = useUtils();
|
|
16
|
+
const translations = usePickerTranslations();
|
|
17
|
+
const id = useId();
|
|
18
|
+
const {
|
|
19
|
+
focused,
|
|
20
|
+
domGetters,
|
|
21
|
+
stateResponse,
|
|
22
|
+
applyCharacterEditing,
|
|
23
|
+
manager: {
|
|
24
|
+
internal_fieldValueManager: fieldValueManager
|
|
25
|
+
},
|
|
26
|
+
stateResponse: {
|
|
27
|
+
// States and derived states
|
|
28
|
+
parsedSelectedSections,
|
|
29
|
+
sectionsValueBoundaries,
|
|
30
|
+
state,
|
|
31
|
+
value,
|
|
32
|
+
// Methods to update the states
|
|
33
|
+
clearActiveSection,
|
|
34
|
+
setCharacterQuery,
|
|
35
|
+
setSelectedSections,
|
|
36
|
+
updateSectionValue,
|
|
37
|
+
updateValueFromValueStr
|
|
38
|
+
},
|
|
39
|
+
internalPropsWithDefaults: {
|
|
40
|
+
disabled = false,
|
|
41
|
+
readOnly = false
|
|
42
|
+
}
|
|
43
|
+
} = parameters;
|
|
44
|
+
const isContainerEditable = parsedSelectedSections === 'all';
|
|
45
|
+
const isEditable = !isContainerEditable && !disabled && !readOnly;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* If a section content has been updated with a value we don't want to keep,
|
|
49
|
+
* Then we need to imperatively revert it (we can't let React do it because the value did not change in his internal representation).
|
|
50
|
+
*/
|
|
51
|
+
const revertDOMSectionChange = useEventCallback(sectionIndex => {
|
|
52
|
+
if (!domGetters.isReady()) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const section = state.sections[sectionIndex];
|
|
56
|
+
domGetters.getSectionContent(sectionIndex).innerHTML = section.value || section.placeholder;
|
|
57
|
+
syncSelectionToDOM({
|
|
58
|
+
focused,
|
|
59
|
+
domGetters,
|
|
60
|
+
stateResponse
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
const handleInput = useEventCallback(event => {
|
|
64
|
+
if (!domGetters.isReady()) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const target = event.target;
|
|
68
|
+
const keyPressed = target.textContent ?? '';
|
|
69
|
+
const sectionIndex = domGetters.getSectionIndexFromDOMElement(target);
|
|
70
|
+
const section = state.sections[sectionIndex];
|
|
71
|
+
if (readOnly) {
|
|
72
|
+
revertDOMSectionChange(sectionIndex);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (keyPressed.length === 0) {
|
|
76
|
+
if (section.value === '') {
|
|
77
|
+
revertDOMSectionChange(sectionIndex);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const inputType = event.nativeEvent.inputType;
|
|
81
|
+
if (inputType === 'insertParagraph' || inputType === 'insertLineBreak') {
|
|
82
|
+
revertDOMSectionChange(sectionIndex);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
revertDOMSectionChange(sectionIndex);
|
|
86
|
+
clearActiveSection();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
applyCharacterEditing({
|
|
90
|
+
keyPressed,
|
|
91
|
+
sectionIndex
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// The DOM value needs to remain the one React is expecting.
|
|
95
|
+
revertDOMSectionChange(sectionIndex);
|
|
96
|
+
});
|
|
97
|
+
const handleMouseUp = useEventCallback(event => {
|
|
98
|
+
// Without this, the browser will remove the selected when clicking inside an already-selected section.
|
|
99
|
+
event.preventDefault();
|
|
100
|
+
});
|
|
101
|
+
const handlePaste = useEventCallback(event => {
|
|
102
|
+
// prevent default to avoid the input `onInput` handler being called
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
if (readOnly || disabled || typeof parsedSelectedSections !== 'number') {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const activeSection = state.sections[parsedSelectedSections];
|
|
108
|
+
const pastedValue = event.clipboardData.getData('text');
|
|
109
|
+
const lettersOnly = /^[a-zA-Z]+$/.test(pastedValue);
|
|
110
|
+
const digitsOnly = /^[0-9]+$/.test(pastedValue);
|
|
111
|
+
const digitsAndLetterOnly = /^(([a-zA-Z]+)|)([0-9]+)(([a-zA-Z]+)|)$/.test(pastedValue);
|
|
112
|
+
const isValidPastedValue = activeSection.contentType === 'letter' && lettersOnly || activeSection.contentType === 'digit' && digitsOnly || activeSection.contentType === 'digit-with-letter' && digitsAndLetterOnly;
|
|
113
|
+
if (isValidPastedValue) {
|
|
114
|
+
setCharacterQuery(null);
|
|
115
|
+
updateSectionValue({
|
|
116
|
+
section: activeSection,
|
|
117
|
+
newSectionValue: pastedValue,
|
|
118
|
+
shouldGoToNextSection: true
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// If the pasted value corresponds to a single section, but not the expected type, we skip the modification
|
|
122
|
+
else if (!lettersOnly && !digitsOnly) {
|
|
123
|
+
setCharacterQuery(null);
|
|
124
|
+
updateValueFromValueStr(pastedValue);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
const handleDragOver = useEventCallback(event => {
|
|
128
|
+
event.preventDefault();
|
|
129
|
+
event.dataTransfer.dropEffect = 'none';
|
|
130
|
+
});
|
|
131
|
+
const createFocusHandler = useEventCallback(sectionIndex => () => {
|
|
132
|
+
setSelectedSections(sectionIndex);
|
|
133
|
+
});
|
|
134
|
+
return React.useCallback((section, sectionIndex) => {
|
|
135
|
+
const sectionBoundaries = sectionsValueBoundaries[section.type]({
|
|
136
|
+
currentDate: fieldValueManager.getDateFromSection(value, section),
|
|
137
|
+
contentType: section.contentType,
|
|
138
|
+
format: section.format
|
|
139
|
+
});
|
|
140
|
+
return {
|
|
141
|
+
// Event handlers
|
|
142
|
+
onInput: handleInput,
|
|
143
|
+
onPaste: handlePaste,
|
|
144
|
+
onMouseUp: handleMouseUp,
|
|
145
|
+
onDragOver: handleDragOver,
|
|
146
|
+
onFocus: createFocusHandler(sectionIndex),
|
|
147
|
+
// Aria attributes
|
|
148
|
+
'aria-labelledby': `${id}-${section.type}`,
|
|
149
|
+
'aria-readonly': readOnly,
|
|
150
|
+
'aria-valuenow': getSectionValueNow(section, utils),
|
|
151
|
+
'aria-valuemin': sectionBoundaries.minimum,
|
|
152
|
+
'aria-valuemax': sectionBoundaries.maximum,
|
|
153
|
+
'aria-valuetext': section.value ? getSectionValueText(section, utils) : translations.empty,
|
|
154
|
+
'aria-label': translations[section.type],
|
|
155
|
+
'aria-disabled': disabled,
|
|
156
|
+
// Other
|
|
157
|
+
tabIndex: isContainerEditable || sectionIndex > 0 ? -1 : 0,
|
|
158
|
+
contentEditable: !isContainerEditable && !disabled && !readOnly,
|
|
159
|
+
role: 'spinbutton',
|
|
160
|
+
id: `${id}-${section.type}`,
|
|
161
|
+
spellCheck: isEditable ? false : undefined,
|
|
162
|
+
autoCapitalize: isEditable ? 'off' : undefined,
|
|
163
|
+
autoCorrect: isEditable ? 'off' : undefined,
|
|
164
|
+
[parseInt(React.version, 10) >= 17 ? 'enterKeyHint' : 'enterkeyhint']: isEditable ? 'next' : undefined,
|
|
165
|
+
children: section.value || section.placeholder,
|
|
166
|
+
inputMode: section.contentType === 'letter' ? 'text' : 'numeric'
|
|
167
|
+
};
|
|
168
|
+
}, [sectionsValueBoundaries, id, isContainerEditable, disabled, readOnly, isEditable, translations, utils, handleInput, handlePaste, handleMouseUp, handleDragOver, createFocusHandler, fieldValueManager, value]);
|
|
169
|
+
}
|
|
170
|
+
function getSectionValueText(section, utils) {
|
|
171
|
+
if (!section.value) {
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
switch (section.type) {
|
|
175
|
+
case 'month':
|
|
176
|
+
{
|
|
177
|
+
if (section.contentType === 'digit') {
|
|
178
|
+
return utils.format(utils.setMonth(utils.date(), Number(section.value) - 1), 'month');
|
|
179
|
+
}
|
|
180
|
+
const parsedDate = utils.parse(section.value, section.format);
|
|
181
|
+
return parsedDate ? utils.format(parsedDate, 'month') : undefined;
|
|
182
|
+
}
|
|
183
|
+
case 'day':
|
|
184
|
+
return section.contentType === 'digit' ? utils.format(utils.setDate(utils.startOfYear(utils.date()), Number(section.value)), 'dayOfMonthFull') : section.value;
|
|
185
|
+
case 'weekDay':
|
|
186
|
+
// TODO: improve by providing the label of the week day
|
|
187
|
+
return undefined;
|
|
188
|
+
default:
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function getSectionValueNow(section, utils) {
|
|
193
|
+
if (!section.value) {
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
switch (section.type) {
|
|
197
|
+
case 'weekDay':
|
|
198
|
+
{
|
|
199
|
+
if (section.contentType === 'letter') {
|
|
200
|
+
// TODO: improve by resolving the week day number from a letter week day
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
return Number(section.value);
|
|
204
|
+
}
|
|
205
|
+
case 'meridiem':
|
|
206
|
+
{
|
|
207
|
+
const parsedDate = utils.parse(`01:00 ${section.value}`, `${utils.formats.hours12h}:${utils.formats.minutes} ${section.format}`);
|
|
208
|
+
if (parsedDate) {
|
|
209
|
+
return utils.getHours(parsedDate) >= 12 ? 1 : 0;
|
|
210
|
+
}
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
case 'day':
|
|
214
|
+
return section.contentType === 'digit-with-letter' ? parseInt(section.value, 10) : Number(section.value);
|
|
215
|
+
case 'month':
|
|
216
|
+
{
|
|
217
|
+
if (section.contentType === 'digit') {
|
|
218
|
+
return Number(section.value);
|
|
219
|
+
}
|
|
220
|
+
const parsedDate = utils.parse(section.value, section.format);
|
|
221
|
+
return parsedDate ? utils.getMonth(parsedDate) + 1 : undefined;
|
|
222
|
+
}
|
|
223
|
+
default:
|
|
224
|
+
return section.contentType !== 'letter' ? Number(section.value) : undefined;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import { UseFieldInternalProps,
|
|
2
|
-
import { FieldSelectedSections, PickersTimezone, InferFieldSection } from "../../../models/index.js";
|
|
1
|
+
import { UseFieldInternalProps, UseFieldState, FieldParsedSelectedSections, FieldSectionsValueBoundaries, SectionOrdering, UseFieldForwardedProps, CharacterEditingQuery } from "./useField.types.js";
|
|
2
|
+
import { FieldSelectedSections, PickersTimezone, InferFieldSection, PickerManager } from "../../../models/index.js";
|
|
3
3
|
import { PickerValidValue } from "../../models/index.js";
|
|
4
|
-
export
|
|
4
|
+
export declare const useFieldState: <TValue extends PickerValidValue, TEnableAccessibleFieldDOMStructure extends boolean, TError, TValidationProps extends {}, TForwardedProps extends UseFieldForwardedProps<TEnableAccessibleFieldDOMStructure>>(parameters: UseFieldStateParameters<TValue, TEnableAccessibleFieldDOMStructure, TError, TValidationProps, TForwardedProps>) => UseFieldStateReturnValue<TValue>;
|
|
5
|
+
interface UseFieldStateParameters<TValue extends PickerValidValue, TEnableAccessibleFieldDOMStructure extends boolean, TError, TValidationProps extends {}, TForwardedProps extends UseFieldForwardedProps<TEnableAccessibleFieldDOMStructure>> {
|
|
6
|
+
manager: PickerManager<TValue, TEnableAccessibleFieldDOMStructure, TError, TValidationProps, any>;
|
|
7
|
+
internalPropsWithDefaults: UseFieldInternalProps<TValue, TEnableAccessibleFieldDOMStructure, TError> & TValidationProps;
|
|
8
|
+
forwardedProps: TForwardedProps;
|
|
9
|
+
}
|
|
10
|
+
export interface UpdateSectionValueParameters<TValue extends PickerValidValue> {
|
|
5
11
|
/**
|
|
6
12
|
* The section on which we want to apply the new value.
|
|
7
13
|
*/
|
|
@@ -15,20 +21,24 @@ export interface UpdateSectionValueParams<TValue extends PickerValidValue> {
|
|
|
15
21
|
*/
|
|
16
22
|
shouldGoToNextSection: boolean;
|
|
17
23
|
}
|
|
18
|
-
export interface
|
|
19
|
-
state: UseFieldState<TValue>;
|
|
20
|
-
value: TValue;
|
|
24
|
+
export interface UseFieldStateReturnValue<TValue extends PickerValidValue> {
|
|
21
25
|
activeSectionIndex: number | null;
|
|
26
|
+
areAllSectionsEmpty: boolean;
|
|
27
|
+
error: boolean;
|
|
28
|
+
localizedDigits: string[];
|
|
22
29
|
parsedSelectedSections: FieldParsedSelectedSections;
|
|
23
|
-
|
|
30
|
+
sectionOrder: SectionOrdering;
|
|
31
|
+
sectionsValueBoundaries: FieldSectionsValueBoundaries;
|
|
32
|
+
state: UseFieldState<TValue>;
|
|
33
|
+
timezone: PickersTimezone;
|
|
34
|
+
value: TValue;
|
|
24
35
|
clearValue: () => void;
|
|
25
36
|
clearActiveSection: () => void;
|
|
26
|
-
|
|
27
|
-
|
|
37
|
+
setCharacterQuery: (characterQuery: CharacterEditingQuery | null) => void;
|
|
38
|
+
setSelectedSections: (sections: FieldSelectedSections) => void;
|
|
28
39
|
setTempAndroidValueStr: (tempAndroidValueStr: string | null) => void;
|
|
29
|
-
|
|
40
|
+
updateSectionValue: (parameters: UpdateSectionValueParameters<TValue>) => void;
|
|
41
|
+
updateValueFromValueStr: (valueStr: string) => void;
|
|
30
42
|
getSectionsFromValue: (value: TValue, fallbackSections?: InferFieldSection<TValue>[] | null) => InferFieldSection<TValue>[];
|
|
31
|
-
localizedDigits: string[];
|
|
32
|
-
timezone: PickersTimezone;
|
|
33
43
|
}
|
|
34
|
-
export
|
|
44
|
+
export {};
|