@mui/x-date-pickers 6.0.1 → 6.0.3
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/AdapterDateFns/index.js +2 -0
- package/AdapterDateFnsJalali/index.js +1 -0
- package/AdapterDayjs/index.js +6 -0
- package/AdapterLuxon/index.js +1 -0
- package/AdapterMoment/index.js +6 -0
- package/AdapterMomentHijri/index.d.ts +1 -1
- package/AdapterMomentHijri/index.js +5 -0
- package/AdapterMomentJalaali/index.js +5 -0
- package/CHANGELOG.md +116 -10
- package/DateField/DateField.js +4 -0
- package/DateField/DateField.types.d.ts +2 -2
- package/DateField/useDateField.js +5 -3
- package/DateTimeField/DateTimeField.js +4 -0
- package/DateTimeField/DateTimeField.types.d.ts +2 -2
- package/DateTimeField/useDateTimeField.js +5 -3
- package/PickersDay/PickersDay.js +4 -4
- package/TimeField/TimeField.js +4 -0
- package/TimeField/TimeField.types.d.ts +2 -2
- package/TimeField/useTimeField.js +5 -3
- package/index.d.ts +1 -6
- package/index.js +4 -2
- package/internals/components/PickersArrowSwitcher/PickersArrowSwitcher.js +8 -2
- package/internals/components/PickersModalDialog.d.ts +2 -2
- package/internals/components/PickersPopper.d.ts +1 -1
- package/internals/hooks/useDesktopPicker/useDesktopPicker.types.d.ts +5 -4
- package/internals/hooks/useField/index.d.ts +2 -2
- package/internals/hooks/useField/index.js +1 -1
- package/internals/hooks/useField/useField.d.ts +1 -1
- package/internals/hooks/useField/useField.js +62 -27
- package/internals/hooks/useField/useField.types.d.ts +37 -20
- package/internals/hooks/useField/useField.utils.d.ts +3 -3
- package/internals/hooks/useField/useField.utils.js +63 -35
- package/internals/hooks/useField/useFieldCharacterEditing.js +4 -9
- package/internals/hooks/useField/useFieldState.d.ts +1 -2
- package/internals/hooks/useField/useFieldState.js +44 -43
- package/internals/hooks/useMobilePicker/useMobilePicker.types.d.ts +5 -4
- package/internals/hooks/usePicker/usePicker.d.ts +2 -1
- package/internals/hooks/usePicker/usePicker.types.d.ts +4 -3
- package/internals/hooks/usePicker/usePickerValue.d.ts +8 -8
- package/internals/hooks/usePicker/usePickerValue.js +7 -11
- package/internals/hooks/useStaticPicker/useStaticPicker.types.d.ts +2 -1
- package/internals/index.d.ts +2 -2
- package/internals/index.js +2 -2
- package/internals/models/fields.d.ts +3 -3
- package/internals/utils/date-utils.d.ts +1 -0
- package/internals/utils/date-utils.js +6 -0
- package/internals/utils/valueManagers.js +15 -12
- package/legacy/AdapterDateFns/index.js +2 -0
- package/legacy/AdapterDateFnsJalali/index.js +1 -0
- package/legacy/AdapterDayjs/index.js +6 -0
- package/legacy/AdapterLuxon/index.js +1 -0
- package/legacy/AdapterMoment/index.js +6 -0
- package/legacy/AdapterMomentHijri/index.js +5 -0
- package/legacy/AdapterMomentJalaali/index.js +5 -0
- package/legacy/DateField/DateField.js +4 -0
- package/legacy/DateField/useDateField.js +4 -2
- package/legacy/DateTimeField/DateTimeField.js +4 -0
- package/legacy/DateTimeField/useDateTimeField.js +4 -2
- package/legacy/PickersDay/PickersDay.js +4 -4
- package/legacy/TimeField/TimeField.js +4 -0
- package/legacy/TimeField/useTimeField.js +4 -2
- package/legacy/index.js +4 -2
- package/legacy/internals/components/PickersArrowSwitcher/PickersArrowSwitcher.js +8 -2
- package/legacy/internals/hooks/useField/index.js +1 -1
- package/legacy/internals/hooks/useField/useField.js +86 -40
- package/legacy/internals/hooks/useField/useField.utils.js +64 -36
- package/legacy/internals/hooks/useField/useFieldCharacterEditing.js +4 -9
- package/legacy/internals/hooks/useField/useFieldState.js +46 -47
- package/legacy/internals/hooks/usePicker/usePickerValue.js +9 -13
- package/legacy/internals/index.js +2 -2
- package/legacy/internals/utils/date-utils.js +6 -0
- package/legacy/internals/utils/valueManagers.js +7 -8
- package/legacy/locales/deDE.js +8 -5
- package/legacy/locales/faIR.js +33 -16
- package/legacy/locales/frFR.js +30 -15
- package/legacy/locales/heIL.js +71 -0
- package/legacy/locales/index.js +1 -0
- package/legacy/locales/nlNL.js +12 -10
- package/legacy/locales/plPL.js +12 -10
- package/legacy/models/index.js +1 -0
- package/legacy/tests/describeValue/testPickerOpenCloseLifeCycle.js +19 -1
- package/locales/deDE.js +4 -5
- package/locales/faIR.js +13 -16
- package/locales/frFR.js +12 -15
- package/locales/heIL.d.ts +51 -0
- package/locales/heIL.js +57 -0
- package/locales/index.d.ts +1 -0
- package/locales/index.js +1 -0
- package/locales/nlNL.js +8 -10
- package/locales/plPL.js +8 -10
- package/models/index.d.ts +6 -0
- package/models/index.js +1 -0
- package/models/package.json +6 -0
- package/modern/AdapterDateFns/index.js +2 -0
- package/modern/AdapterDateFnsJalali/index.js +1 -0
- package/modern/AdapterDayjs/index.js +6 -0
- package/modern/AdapterLuxon/index.js +1 -0
- package/modern/AdapterMoment/index.js +6 -0
- package/modern/AdapterMomentHijri/index.js +5 -0
- package/modern/AdapterMomentJalaali/index.js +5 -0
- package/modern/DateField/DateField.js +4 -0
- package/modern/DateField/useDateField.js +5 -3
- package/modern/DateTimeField/DateTimeField.js +4 -0
- package/modern/DateTimeField/useDateTimeField.js +5 -3
- package/modern/PickersDay/PickersDay.js +4 -4
- package/modern/TimeField/TimeField.js +4 -0
- package/modern/TimeField/useTimeField.js +5 -3
- package/modern/index.js +4 -2
- package/modern/internals/components/PickersArrowSwitcher/PickersArrowSwitcher.js +8 -2
- package/modern/internals/hooks/useField/index.js +1 -1
- package/modern/internals/hooks/useField/useField.js +61 -27
- package/modern/internals/hooks/useField/useField.utils.js +63 -35
- package/modern/internals/hooks/useField/useFieldCharacterEditing.js +4 -9
- package/modern/internals/hooks/useField/useFieldState.js +44 -43
- package/modern/internals/hooks/usePicker/usePickerValue.js +7 -11
- package/modern/internals/index.js +2 -2
- package/modern/internals/utils/date-utils.js +6 -0
- package/modern/internals/utils/valueManagers.js +15 -12
- package/modern/locales/deDE.js +4 -5
- package/modern/locales/faIR.js +13 -16
- package/modern/locales/frFR.js +12 -15
- package/modern/locales/heIL.js +57 -0
- package/modern/locales/index.js +1 -0
- package/modern/locales/nlNL.js +8 -10
- package/modern/locales/plPL.js +8 -10
- package/modern/models/index.js +1 -0
- package/modern/tests/describeValue/testPickerOpenCloseLifeCycle.js +19 -1
- package/node/AdapterDateFns/index.js +2 -0
- package/node/AdapterDateFnsJalali/index.js +1 -0
- package/node/AdapterDayjs/index.js +6 -0
- package/node/AdapterLuxon/index.js +1 -0
- package/node/AdapterMoment/index.js +6 -0
- package/node/AdapterMomentHijri/index.js +5 -0
- package/node/AdapterMomentJalaali/index.js +5 -0
- package/node/DateField/DateField.js +4 -0
- package/node/DateField/useDateField.js +5 -3
- package/node/DateTimeField/DateTimeField.js +4 -0
- package/node/DateTimeField/useDateTimeField.js +5 -3
- package/node/PickersDay/PickersDay.js +4 -4
- package/node/TimeField/TimeField.js +4 -0
- package/node/TimeField/useTimeField.js +5 -3
- package/node/index.js +14 -2
- package/node/internals/components/PickersArrowSwitcher/PickersArrowSwitcher.js +8 -2
- package/node/internals/hooks/useField/index.js +0 -6
- package/node/internals/hooks/useField/useField.js +60 -26
- package/node/internals/hooks/useField/useField.utils.js +66 -38
- package/node/internals/hooks/useField/useFieldCharacterEditing.js +3 -8
- package/node/internals/hooks/useField/useFieldState.js +44 -43
- package/node/internals/hooks/usePicker/usePickerValue.js +7 -11
- package/node/internals/index.js +6 -6
- package/node/internals/utils/date-utils.js +9 -2
- package/node/internals/utils/valueManagers.js +13 -10
- package/node/locales/deDE.js +4 -5
- package/node/locales/faIR.js +13 -16
- package/node/locales/frFR.js +12 -15
- package/node/locales/heIL.js +64 -0
- package/node/locales/index.js +11 -0
- package/node/locales/nlNL.js +8 -10
- package/node/locales/plPL.js +8 -10
- package/node/models/index.js +5 -0
- package/node/tests/describeValue/testPickerOpenCloseLifeCycle.js +18 -0
- package/package.json +3 -3
- package/tests/describeValue/testPickerOpenCloseLifeCycle.js +19 -1
|
@@ -14,7 +14,7 @@ export interface PickersPopperSlotsComponent {
|
|
|
14
14
|
*/
|
|
15
15
|
DesktopPaper?: React.JSXElementConstructor<MuiPaperProps>;
|
|
16
16
|
/**
|
|
17
|
-
* Custom component for the desktop popper [Transition](https://mui.com/material-ui/transitions).
|
|
17
|
+
* Custom component for the desktop popper [Transition](https://mui.com/material-ui/transitions/).
|
|
18
18
|
* @default Grow from @mui/material
|
|
19
19
|
*/
|
|
20
20
|
DesktopTransition?: React.JSXElementConstructor<MuiTransitionProps>;
|
|
@@ -12,11 +12,12 @@ import { ExportedPickersLayoutSlotsComponent, ExportedPickersLayoutSlotsComponen
|
|
|
12
12
|
import { UsePickerValueNonStaticProps } from '../usePicker/usePickerValue';
|
|
13
13
|
import { UsePickerViewsNonStaticProps, UsePickerViewsProps } from '../usePicker/usePickerViews';
|
|
14
14
|
import { UncapitalizeObjectKeys } from '../../utils/slots-migration';
|
|
15
|
+
import { FieldSection } from '../useField';
|
|
15
16
|
export interface UseDesktopPickerSlotsComponent<TDate, TView extends DateOrTimeView> extends Pick<PickersPopperSlotsComponent, 'DesktopPaper' | 'DesktopTransition' | 'DesktopTrapFocus' | 'Popper'>, ExportedPickersLayoutSlotsComponent<TDate | null, TDate, TView> {
|
|
16
17
|
/**
|
|
17
18
|
* Component used to enter the date with the keyboard.
|
|
18
19
|
*/
|
|
19
|
-
Field: React.ElementType<BaseSingleInputFieldProps<TDate | null, any>>;
|
|
20
|
+
Field: React.ElementType<BaseSingleInputFieldProps<TDate | null, FieldSection, any>>;
|
|
20
21
|
/**
|
|
21
22
|
* Form control with an input to render the value inside the default field.
|
|
22
23
|
* Receives the same props as `@mui/material/TextField`.
|
|
@@ -41,13 +42,13 @@ export interface UseDesktopPickerSlotsComponent<TDate, TView extends DateOrTimeV
|
|
|
41
42
|
export interface UseDesktopPickerSlotsComponentsProps<TDate, TView extends DateOrTimeView> extends ExportedUseDesktopPickerSlotsComponentsProps<TDate, TView>, Pick<PickersLayoutSlotsComponentsProps<TDate | null, TDate, TView>, 'toolbar'> {
|
|
42
43
|
}
|
|
43
44
|
export interface ExportedUseDesktopPickerSlotsComponentsProps<TDate, TView extends DateOrTimeView> extends PickersPopperSlotsComponentsProps, ExportedPickersLayoutSlotsComponentsProps<TDate | null, TDate, TView> {
|
|
44
|
-
field?: SlotComponentProps<React.ElementType<BaseSingleInputFieldProps<TDate | null, unknown>>, {}, UsePickerProps<TDate | null, any, any, any, any>>;
|
|
45
|
+
field?: SlotComponentProps<React.ElementType<BaseSingleInputFieldProps<TDate | null, FieldSection, unknown>>, {}, UsePickerProps<TDate | null, any, FieldSection, any, any, any>>;
|
|
45
46
|
textField?: SlotComponentProps<typeof TextField, {}, Record<string, any>>;
|
|
46
47
|
inputAdornment?: Partial<InputAdornmentProps>;
|
|
47
48
|
openPickerButton?: SlotComponentProps<typeof IconButton, {}, UseDesktopPickerProps<TDate, any, any, any>>;
|
|
48
49
|
openPickerIcon?: Record<string, any>;
|
|
49
50
|
}
|
|
50
|
-
export interface DesktopOnlyPickerProps<TDate> extends BaseNonStaticPickerProps, BaseSingleInputNonStaticPickerProps, UsePickerValueNonStaticProps<TDate | null>, UsePickerViewsNonStaticProps {
|
|
51
|
+
export interface DesktopOnlyPickerProps<TDate> extends BaseNonStaticPickerProps, BaseSingleInputNonStaticPickerProps, UsePickerValueNonStaticProps<TDate | null, FieldSection>, UsePickerViewsNonStaticProps {
|
|
51
52
|
/**
|
|
52
53
|
* If `true`, the `input` element is focused during the first mount.
|
|
53
54
|
*/
|
|
@@ -65,7 +66,7 @@ export interface UseDesktopPickerProps<TDate, TView extends DateOrTimeView, TErr
|
|
|
65
66
|
*/
|
|
66
67
|
slotProps?: UseDesktopPickerSlotsComponentsProps<TDate, TView>;
|
|
67
68
|
}
|
|
68
|
-
export interface UseDesktopPickerParams<TDate, TView extends DateOrTimeView, TExternalProps extends UseDesktopPickerProps<TDate, TView, any, TExternalProps>> extends Pick<UsePickerParams<TDate | null, TDate, TView, TExternalProps, {}>, 'valueManager' | 'validator'> {
|
|
69
|
+
export interface UseDesktopPickerParams<TDate, TView extends DateOrTimeView, TExternalProps extends UseDesktopPickerProps<TDate, TView, any, TExternalProps>> extends Pick<UsePickerParams<TDate | null, TDate, TView, FieldSection, TExternalProps, {}>, 'valueManager' | 'validator'> {
|
|
69
70
|
props: TExternalProps;
|
|
70
71
|
getOpenDialogAriaText: (date: TDate | null, utils: MuiPickersAdapter<TDate>) => string;
|
|
71
72
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { useField } from './useField';
|
|
2
|
-
export type { FieldValueManager, FieldSection, UseFieldInternalProps, UseFieldForwardedProps, UseFieldParams, UseFieldResponse, FieldSelectedSections, FieldChangeHandler, FieldChangeHandlerContext, } from './useField.types';
|
|
3
|
-
export { splitFormatIntoSections, addPositionPropertiesToSections, createDateStrForInputFromSections,
|
|
2
|
+
export type { FieldValueManager, FieldSection, UseFieldInternalProps, UseFieldForwardedProps, UseFieldParams, UseFieldResponse, FieldSelectedSections, FieldChangeHandler, FieldChangeHandlerContext, FieldRef, } from './useField.types';
|
|
3
|
+
export { splitFormatIntoSections, addPositionPropertiesToSections, createDateStrForInputFromSections, } from './useField.utils';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { useField } from './useField';
|
|
2
|
-
export { splitFormatIntoSections, addPositionPropertiesToSections, createDateStrForInputFromSections
|
|
2
|
+
export { splitFormatIntoSections, addPositionPropertiesToSections, createDateStrForInputFromSections } from './useField.utils';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { FieldSection, UseFieldParams, UseFieldResponse, UseFieldForwardedProps, UseFieldInternalProps } from './useField.types';
|
|
2
|
-
export declare const useField: <TValue, TDate, TSection extends FieldSection, TForwardedProps extends UseFieldForwardedProps, TInternalProps extends UseFieldInternalProps<any, any>>(params: UseFieldParams<TValue, TDate, TSection, TForwardedProps, TInternalProps>) => UseFieldResponse<TForwardedProps>;
|
|
2
|
+
export declare const useField: <TValue, TDate, TSection extends FieldSection, TForwardedProps extends UseFieldForwardedProps, TInternalProps extends UseFieldInternalProps<any, any, any>>(params: UseFieldParams<TValue, TDate, TSection, TForwardedProps, TInternalProps>) => UseFieldResponse<TForwardedProps>;
|
|
@@ -5,16 +5,15 @@ import * as React from 'react';
|
|
|
5
5
|
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
|
|
6
6
|
import useEventCallback from '@mui/utils/useEventCallback';
|
|
7
7
|
import useForkRef from '@mui/utils/useForkRef';
|
|
8
|
+
import { useTheme } from '@mui/material/styles';
|
|
8
9
|
import { useValidation } from '../validation/useValidation';
|
|
9
10
|
import { useUtils } from '../useUtils';
|
|
10
|
-
import { adjustSectionValue, isAndroid, cleanString } from './useField.utils';
|
|
11
|
+
import { adjustSectionValue, isAndroid, cleanString, getSectionOrder } from './useField.utils';
|
|
11
12
|
import { useFieldState } from './useFieldState';
|
|
12
13
|
import { useFieldCharacterEditing } from './useFieldCharacterEditing';
|
|
14
|
+
import { getActiveElement } from '../../utils/utils';
|
|
13
15
|
export const useField = params => {
|
|
14
16
|
const utils = useUtils();
|
|
15
|
-
if (!utils.formatTokenMap) {
|
|
16
|
-
throw new Error('This adapter is not compatible with the field components');
|
|
17
|
-
}
|
|
18
17
|
const {
|
|
19
18
|
state,
|
|
20
19
|
selectedSectionIndexes,
|
|
@@ -24,7 +23,6 @@ export const useField = params => {
|
|
|
24
23
|
updateSectionValue,
|
|
25
24
|
updateValueFromValueStr,
|
|
26
25
|
setTempAndroidValueStr,
|
|
27
|
-
sectionOrder,
|
|
28
26
|
sectionsValueBoundaries
|
|
29
27
|
} = useFieldState(params);
|
|
30
28
|
const {
|
|
@@ -40,7 +38,8 @@ export const useField = params => {
|
|
|
40
38
|
inputRef: inputRefProp,
|
|
41
39
|
internalProps,
|
|
42
40
|
internalProps: {
|
|
43
|
-
readOnly = false
|
|
41
|
+
readOnly = false,
|
|
42
|
+
unstableFieldRef
|
|
44
43
|
},
|
|
45
44
|
forwardedProps: {
|
|
46
45
|
onClick,
|
|
@@ -59,8 +58,14 @@ export const useField = params => {
|
|
|
59
58
|
const inputRef = React.useRef(null);
|
|
60
59
|
const handleRef = useForkRef(inputRefProp, inputRef);
|
|
61
60
|
const focusTimeoutRef = React.useRef(undefined);
|
|
61
|
+
const theme = useTheme();
|
|
62
|
+
const sectionOrder = React.useMemo(() => getSectionOrder(state.sections, theme.direction === 'rtl'), [theme.direction, state.sections]);
|
|
62
63
|
const syncSelectionFromDOM = () => {
|
|
63
64
|
var _selectionStart;
|
|
65
|
+
if (readOnly) {
|
|
66
|
+
setSelectedSections(null);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
64
69
|
const browserStartIndex = (_selectionStart = inputRef.current.selectionStart) != null ? _selectionStart : 0;
|
|
65
70
|
const nextSectionIndex = browserStartIndex <= state.sections[0].startInInput ? 1 // Special case if browser index is in invisible characters at the beginning.
|
|
66
71
|
: state.sections.findIndex(section => section.startInInput - section.startSeparator.length > browserStartIndex);
|
|
@@ -87,7 +92,7 @@ export const useField = params => {
|
|
|
87
92
|
if (!input || input !== inputRef.current) {
|
|
88
93
|
return;
|
|
89
94
|
}
|
|
90
|
-
if (selectedSectionIndexes != null) {
|
|
95
|
+
if (selectedSectionIndexes != null || readOnly) {
|
|
91
96
|
return;
|
|
92
97
|
}
|
|
93
98
|
if (
|
|
@@ -142,27 +147,32 @@ export const useField = params => {
|
|
|
142
147
|
updateValueFromValueStr(cleanValueStr);
|
|
143
148
|
return;
|
|
144
149
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
let keyPressed;
|
|
151
|
+
if (selectedSectionIndexes.startIndex === 0 && selectedSectionIndexes.endIndex === state.sections.length - 1) {
|
|
152
|
+
keyPressed = cleanValueStr;
|
|
153
|
+
} else {
|
|
154
|
+
const prevValueStr = cleanString(fieldValueManager.getValueStrFromSections(state.sections));
|
|
155
|
+
let startOfDiffIndex = -1;
|
|
156
|
+
let endOfDiffIndex = -1;
|
|
157
|
+
for (let i = 0; i < prevValueStr.length; i += 1) {
|
|
158
|
+
if (startOfDiffIndex === -1 && prevValueStr[i] !== cleanValueStr[i]) {
|
|
159
|
+
startOfDiffIndex = i;
|
|
160
|
+
}
|
|
161
|
+
if (endOfDiffIndex === -1 && prevValueStr[prevValueStr.length - i - 1] !== cleanValueStr[cleanValueStr.length - i - 1]) {
|
|
162
|
+
endOfDiffIndex = i;
|
|
163
|
+
}
|
|
151
164
|
}
|
|
152
|
-
|
|
153
|
-
|
|
165
|
+
const activeSection = state.sections[selectedSectionIndexes.startIndex];
|
|
166
|
+
const hasDiffOutsideOfActiveSection = startOfDiffIndex < activeSection.start || prevValueStr.length - endOfDiffIndex - 1 > activeSection.end;
|
|
167
|
+
if (hasDiffOutsideOfActiveSection) {
|
|
168
|
+
// TODO: Support if the new date is valid
|
|
169
|
+
return;
|
|
154
170
|
}
|
|
155
|
-
}
|
|
156
|
-
const activeSection = state.sections[selectedSectionIndexes.startIndex];
|
|
157
|
-
const hasDiffOutsideOfActiveSection = startOfDiffIndex < activeSection.start || prevValueStr.length - endOfDiffIndex - 1 > activeSection.end;
|
|
158
|
-
if (hasDiffOutsideOfActiveSection) {
|
|
159
|
-
// TODO: Support if the new date is valid
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
171
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
172
|
+
// The active section being selected, the browser has replaced its value with the key pressed by the user.
|
|
173
|
+
const activeSectionEndRelativeToNewValue = cleanValueStr.length - prevValueStr.length + activeSection.end - cleanString(activeSection.endSeparator || '').length;
|
|
174
|
+
keyPressed = cleanValueStr.slice(activeSection.start, activeSectionEndRelativeToNewValue);
|
|
175
|
+
}
|
|
166
176
|
if (isAndroid() && keyPressed.length === 0) {
|
|
167
177
|
setTempAndroidValueStr(valueStr);
|
|
168
178
|
return;
|
|
@@ -258,6 +268,12 @@ export const useField = params => {
|
|
|
258
268
|
});
|
|
259
269
|
useEnhancedEffect(() => {
|
|
260
270
|
if (selectedSectionIndexes == null) {
|
|
271
|
+
if (inputRef.current.scrollLeft) {
|
|
272
|
+
// Ensure that input content is not marked as selected.
|
|
273
|
+
// setting selection range to 0 causes issues in Safari.
|
|
274
|
+
// https://bugs.webkit.org/show_bug.cgi?id=224425
|
|
275
|
+
inputRef.current.scrollLeft = 0;
|
|
276
|
+
}
|
|
261
277
|
return;
|
|
262
278
|
}
|
|
263
279
|
const firstSelectedSection = state.sections[selectedSectionIndexes.startIndex];
|
|
@@ -269,7 +285,11 @@ export const useField = params => {
|
|
|
269
285
|
selectionEnd += lastSelectedSection.endSeparator.length;
|
|
270
286
|
}
|
|
271
287
|
if (selectionStart !== inputRef.current.selectionStart || selectionEnd !== inputRef.current.selectionEnd) {
|
|
288
|
+
// Fix scroll jumping on iOS browser: https://github.com/mui/mui-x/issues/8321
|
|
289
|
+
const currentScrollTop = inputRef.current.scrollTop;
|
|
272
290
|
inputRef.current.setSelectionRange(selectionStart, selectionEnd);
|
|
291
|
+
// Even reading this variable seems to do the trick, but also setting it just to make use of it
|
|
292
|
+
inputRef.current.scrollTop = currentScrollTop;
|
|
273
293
|
}
|
|
274
294
|
});
|
|
275
295
|
const validationError = useValidation(_extends({}, internalProps, {
|
|
@@ -315,8 +335,23 @@ export const useField = params => {
|
|
|
315
335
|
}
|
|
316
336
|
return 'tel';
|
|
317
337
|
}, [selectedSectionIndexes, state.sections]);
|
|
318
|
-
const inputHasFocus = inputRef.current && inputRef.current === document
|
|
319
|
-
const shouldShowPlaceholder = !inputHasFocus &&
|
|
338
|
+
const inputHasFocus = inputRef.current && inputRef.current === getActiveElement(document);
|
|
339
|
+
const shouldShowPlaceholder = !inputHasFocus && valueManager.areValuesEqual(utils, state.value, valueManager.emptyValue);
|
|
340
|
+
React.useImperativeHandle(unstableFieldRef, () => ({
|
|
341
|
+
getSections: () => state.sections,
|
|
342
|
+
getActiveSectionIndex: () => {
|
|
343
|
+
var _selectionStart2, _selectionEnd;
|
|
344
|
+
const browserStartIndex = (_selectionStart2 = inputRef.current.selectionStart) != null ? _selectionStart2 : 0;
|
|
345
|
+
const browserEndIndex = (_selectionEnd = inputRef.current.selectionEnd) != null ? _selectionEnd : 0;
|
|
346
|
+
if (browserStartIndex === 0 && browserEndIndex === 0) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
const nextSectionIndex = browserStartIndex <= state.sections[0].startInInput ? 1 // Special case if browser index is in invisible characters at the beginning.
|
|
350
|
+
: state.sections.findIndex(section => section.startInInput - section.startSeparator.length > browserStartIndex);
|
|
351
|
+
return nextSectionIndex === -1 ? state.sections.length - 1 : nextSectionIndex - 1;
|
|
352
|
+
},
|
|
353
|
+
setSelectedSections: activeSectionIndex => setSelectedSections(activeSectionIndex)
|
|
354
|
+
}));
|
|
320
355
|
return _extends({
|
|
321
356
|
placeholder: state.placeholder,
|
|
322
357
|
autoComplete: 'off'
|
|
@@ -3,7 +3,7 @@ import { FieldSectionType, MuiPickersAdapter } from '../../models';
|
|
|
3
3
|
import type { PickerValueManager } from '../usePicker';
|
|
4
4
|
import { InferError, Validator } from '../validation/useValidation';
|
|
5
5
|
import { PickersLocaleText } from '../../../locales/utils/pickersLocaleTextApi';
|
|
6
|
-
export interface UseFieldParams<TValue, TDate, TSection extends FieldSection, TForwardedProps extends UseFieldForwardedProps, TInternalProps extends UseFieldInternalProps<any, any>> {
|
|
6
|
+
export interface UseFieldParams<TValue, TDate, TSection extends FieldSection, TForwardedProps extends UseFieldForwardedProps, TInternalProps extends UseFieldInternalProps<any, any, any>> {
|
|
7
7
|
inputRef?: React.Ref<HTMLInputElement>;
|
|
8
8
|
forwardedProps: TForwardedProps;
|
|
9
9
|
internalProps: TInternalProps;
|
|
@@ -12,7 +12,7 @@ export interface UseFieldParams<TValue, TDate, TSection extends FieldSection, TF
|
|
|
12
12
|
validator: Validator<TValue, TDate, InferError<TInternalProps>, UseFieldValidationProps<TValue, TInternalProps>>;
|
|
13
13
|
valueType: FieldValueType;
|
|
14
14
|
}
|
|
15
|
-
export interface UseFieldInternalProps<TValue, TError> {
|
|
15
|
+
export interface UseFieldInternalProps<TValue, TSection extends FieldSection, TError> {
|
|
16
16
|
/**
|
|
17
17
|
* The selected value.
|
|
18
18
|
* Used when the component is controlled.
|
|
@@ -63,6 +63,28 @@ export interface UseFieldInternalProps<TValue, TError> {
|
|
|
63
63
|
* @param {FieldSelectedSections} newValue The new selected sections.
|
|
64
64
|
*/
|
|
65
65
|
onSelectedSectionsChange?: (newValue: FieldSelectedSections) => void;
|
|
66
|
+
/**
|
|
67
|
+
* The ref object used to imperatively interact with the field.
|
|
68
|
+
*/
|
|
69
|
+
unstableFieldRef?: React.Ref<FieldRef<TSection>>;
|
|
70
|
+
}
|
|
71
|
+
export interface FieldRef<TSection extends FieldSection> {
|
|
72
|
+
/**
|
|
73
|
+
* Returns the sections of the current value.
|
|
74
|
+
* @returns {TSection[]} The sections of the current value.
|
|
75
|
+
*/
|
|
76
|
+
getSections: () => TSection[];
|
|
77
|
+
/**
|
|
78
|
+
* Returns the index of the active section (the first focused section).
|
|
79
|
+
* If no section is active, returns `null`.
|
|
80
|
+
* @returns {number | null} The index of the active section.
|
|
81
|
+
*/
|
|
82
|
+
getActiveSectionIndex: () => number | null;
|
|
83
|
+
/**
|
|
84
|
+
* Updates the selected sections.
|
|
85
|
+
* @param {FieldSelectedSections} selectedSections The sections to select.
|
|
86
|
+
*/
|
|
87
|
+
setSelectedSections: (selectedSections: FieldSelectedSections) => void;
|
|
66
88
|
}
|
|
67
89
|
export interface UseFieldForwardedProps {
|
|
68
90
|
onKeyDown?: React.KeyboardEventHandler;
|
|
@@ -152,14 +174,19 @@ export interface FieldSection {
|
|
|
152
174
|
endSeparator: string;
|
|
153
175
|
}
|
|
154
176
|
export type FieldSectionWithoutPosition<TSection extends FieldSection = FieldSection> = Omit<TSection, 'start' | 'end' | 'startInInput' | 'endInInput'>;
|
|
155
|
-
export type
|
|
156
|
-
currentDate: TDate | null;
|
|
157
|
-
format: string;
|
|
158
|
-
contentType: 'digit' | 'letter';
|
|
159
|
-
}) => {
|
|
177
|
+
export type FieldSectionValueBoundaries<TDate, SectionType extends FieldSectionType> = {
|
|
160
178
|
minimum: number;
|
|
161
179
|
maximum: number;
|
|
162
|
-
}
|
|
180
|
+
} & (SectionType extends 'day' ? {
|
|
181
|
+
longestMonth: TDate;
|
|
182
|
+
} : {});
|
|
183
|
+
export type FieldSectionsValueBoundaries<TDate> = {
|
|
184
|
+
[SectionType in FieldSectionType]: (params: {
|
|
185
|
+
currentDate: TDate | null;
|
|
186
|
+
format: string;
|
|
187
|
+
contentType: 'digit' | 'letter';
|
|
188
|
+
}) => FieldSectionValueBoundaries<TDate, SectionType>;
|
|
189
|
+
};
|
|
163
190
|
export type FieldChangeHandler<TValue, TError> = (value: TValue, context: FieldChangeHandlerContext<TError>) => void;
|
|
164
191
|
export interface FieldChangeHandlerContext<TError> {
|
|
165
192
|
validationError: TError;
|
|
@@ -205,12 +232,12 @@ export interface FieldValueManager<TValue, TDate, TSection extends FieldSection,
|
|
|
205
232
|
* @template TValue, TDate, TSection
|
|
206
233
|
* @param {MuiPickersAdapter<TDate>} utils The utils to manipulate the date.
|
|
207
234
|
* @param {PickersLocaleText<TDate>} localeText The localization object to generate the placeholders.
|
|
208
|
-
* @param {TSection[] | null}
|
|
235
|
+
* @param {TSection[] | null} sections The sections to use as a fallback if a date is null or invalid.
|
|
209
236
|
* @param {TValue} value The current value to generate sections from.
|
|
210
237
|
* @param {string} format The date format.
|
|
211
238
|
* @returns {TSection[]} The new section list.
|
|
212
239
|
*/
|
|
213
|
-
getSectionsFromValue: (utils: MuiPickersAdapter<TDate>, localeText: PickersLocaleText<TDate>,
|
|
240
|
+
getSectionsFromValue: (utils: MuiPickersAdapter<TDate>, localeText: PickersLocaleText<TDate>, sections: TSection[] | null, value: TValue, format: string) => TSection[];
|
|
214
241
|
/**
|
|
215
242
|
* Creates the string value to render in the input based on the current section list.
|
|
216
243
|
* @template TSection
|
|
@@ -264,16 +291,6 @@ export interface FieldValueManager<TValue, TDate, TSection extends FieldSection,
|
|
|
264
291
|
* @returns {boolean} `true` if the current error is not empty.
|
|
265
292
|
*/
|
|
266
293
|
hasError: (error: TError) => boolean;
|
|
267
|
-
/**
|
|
268
|
-
* Return a description of sections display order. This description is useful in RTL mode.
|
|
269
|
-
* @template TDate
|
|
270
|
-
* @param {MuiPickersAdapter<TDate>} utils The utils to manipulate the date.
|
|
271
|
-
* @param {PickersLocaleText<TDate>} localeText The translation object.
|
|
272
|
-
* @param {string} format The format from which sections are computed.
|
|
273
|
-
* @param {boolean} isRTL Is the field in right-to-left orientation.
|
|
274
|
-
* @returns {SectionOrdering} The description of sections order from left to right.
|
|
275
|
-
*/
|
|
276
|
-
getSectionOrder: (utils: MuiPickersAdapter<TDate>, localeText: PickersLocaleText<TDate>, format: string, isRTL: boolean) => SectionOrdering;
|
|
277
294
|
}
|
|
278
295
|
export interface UseFieldState<TValue, TSection extends FieldSection> {
|
|
279
296
|
value: TValue;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { FieldSection, AvailableAdjustKeyCode, FieldSectionsValueBoundaries, SectionOrdering, FieldValueType, FieldSectionWithoutPosition } from './useField.types';
|
|
1
|
+
import { FieldSection, AvailableAdjustKeyCode, FieldSectionsValueBoundaries, SectionOrdering, FieldValueType, FieldSectionWithoutPosition, FieldSectionValueBoundaries } from './useField.types';
|
|
2
2
|
import { MuiPickersAdapter, FieldSectionType } from '../../models';
|
|
3
3
|
import { PickersLocaleText } from '../../../locales/utils/pickersLocaleTextApi';
|
|
4
4
|
export declare const getDateSectionConfigFromFormatToken: <TDate>(utils: MuiPickersAdapter<TDate>, formatToken: string) => Pick<FieldSection, 'type' | 'contentType'>;
|
|
5
5
|
export declare const getDaysInWeekStr: <TDate>(utils: MuiPickersAdapter<TDate>, format: string) => string[];
|
|
6
|
-
export declare const cleanLeadingZerosInNumericSectionValue: <TDate>(utils: MuiPickersAdapter<TDate>, format: string, value: string) => string;
|
|
7
6
|
export declare const getLetterEditingOptions: <TDate>(utils: MuiPickersAdapter<TDate>, sectionType: FieldSectionType, format: string) => string[];
|
|
7
|
+
export declare const cleanDigitSectionValue: <TDate>(utils: MuiPickersAdapter<TDate>, value: number, sectionType: FieldSectionType, format: string, hasLeadingZeros: boolean, sectionBoundaries: FieldSectionValueBoundaries<TDate, any>) => string;
|
|
8
8
|
export declare const adjustSectionValue: <TDate, TSection extends FieldSection>(utils: MuiPickersAdapter<TDate>, section: TSection, keyCode: AvailableAdjustKeyCode, sectionsValueBoundaries: FieldSectionsValueBoundaries<TDate>, activeDate: TDate | null) => string;
|
|
9
9
|
export declare const cleanString: (dirtyString: string) => string;
|
|
10
10
|
export declare const addPositionPropertiesToSections: <TSection extends FieldSection>(sections: FieldSectionWithoutPosition<TSection>[]) => TSection[];
|
|
11
11
|
export declare const changeSectionValueFormat: <TDate>(utils: MuiPickersAdapter<TDate>, valueStr: string, currentFormat: string, newFormat: string) => string;
|
|
12
|
-
export declare const
|
|
12
|
+
export declare const doesSectionHaveLeadingZeros: <TDate>(utils: MuiPickersAdapter<TDate>, contentType: 'digit' | 'letter', sectionType: FieldSectionType, format: string) => boolean;
|
|
13
13
|
export declare const splitFormatIntoSections: <TDate>(utils: MuiPickersAdapter<TDate>, localeText: PickersLocaleText<TDate>, format: string, date: TDate | null) => FieldSectionWithoutPosition<FieldSection>[];
|
|
14
14
|
/**
|
|
15
15
|
* Some date libraries like `dayjs` don't support parsing from date with escaped characters.
|
|
@@ -41,19 +41,6 @@ export const getDaysInWeekStr = (utils, format) => {
|
|
|
41
41
|
}
|
|
42
42
|
return elements.map(weekDay => utils.formatByString(weekDay, format));
|
|
43
43
|
};
|
|
44
|
-
export const cleanLeadingZerosInNumericSectionValue = (utils, format, value) => {
|
|
45
|
-
const size = utils.formatByString(utils.date(), format).length;
|
|
46
|
-
let cleanValue = value;
|
|
47
|
-
|
|
48
|
-
// We remove the leading zeros
|
|
49
|
-
cleanValue = Number(cleanValue).toString();
|
|
50
|
-
|
|
51
|
-
// We add enough leading zeros to fill the section
|
|
52
|
-
while (cleanValue.length < size) {
|
|
53
|
-
cleanValue = `0${cleanValue}`;
|
|
54
|
-
}
|
|
55
|
-
return cleanValue;
|
|
56
|
-
};
|
|
57
44
|
export const getLetterEditingOptions = (utils, sectionType, format) => {
|
|
58
45
|
switch (sectionType) {
|
|
59
46
|
case 'month':
|
|
@@ -75,42 +62,70 @@ export const getLetterEditingOptions = (utils, sectionType, format) => {
|
|
|
75
62
|
}
|
|
76
63
|
}
|
|
77
64
|
};
|
|
65
|
+
export const cleanDigitSectionValue = (utils, value, sectionType, format, hasLeadingZeros, sectionBoundaries) => {
|
|
66
|
+
const hasLetter = () => {
|
|
67
|
+
const startOfYear = utils.startOfYear(utils.date());
|
|
68
|
+
const startOfYearStr = utils.formatByString(startOfYear, format);
|
|
69
|
+
return Number.isNaN(Number(startOfYearStr));
|
|
70
|
+
};
|
|
71
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
72
|
+
if (sectionType !== 'day' && hasLetter()) {
|
|
73
|
+
throw new Error([`MUI: The token "${format}" is a digit format with letter in it.'
|
|
74
|
+
This type of format is only supported for 'day' sections`].join('\n'));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (sectionType === 'day' && hasLetter()) {
|
|
78
|
+
const date = utils.setDate(sectionBoundaries.longestMonth, value);
|
|
79
|
+
return utils.formatByString(date, format);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// queryValue without leading `0` (`01` => `1`)
|
|
83
|
+
const valueStr = value.toString();
|
|
84
|
+
if (hasLeadingZeros) {
|
|
85
|
+
const size = utils.formatByString(utils.date(), format).length;
|
|
86
|
+
let cleanValueStr = valueStr;
|
|
87
|
+
|
|
88
|
+
// Remove the leading zeros
|
|
89
|
+
cleanValueStr = Number(cleanValueStr).toString();
|
|
90
|
+
|
|
91
|
+
// Add enough leading zeros to fill the section
|
|
92
|
+
while (cleanValueStr.length < size) {
|
|
93
|
+
cleanValueStr = `0${cleanValueStr}`;
|
|
94
|
+
}
|
|
95
|
+
return cleanValueStr;
|
|
96
|
+
}
|
|
97
|
+
return valueStr;
|
|
98
|
+
};
|
|
78
99
|
export const adjustSectionValue = (utils, section, keyCode, sectionsValueBoundaries, activeDate) => {
|
|
79
100
|
const delta = getDeltaFromKeyCode(keyCode);
|
|
80
101
|
const isStart = keyCode === 'Home';
|
|
81
102
|
const isEnd = keyCode === 'End';
|
|
82
103
|
const shouldSetAbsolute = section.value === '' || isStart || isEnd;
|
|
83
|
-
const cleanDigitSectionValue = value => {
|
|
84
|
-
const valueStr = value.toString();
|
|
85
|
-
if (section.hasLeadingZeros) {
|
|
86
|
-
return cleanLeadingZerosInNumericSectionValue(utils, section.format, valueStr);
|
|
87
|
-
}
|
|
88
|
-
return valueStr;
|
|
89
|
-
};
|
|
90
104
|
const adjustDigitSection = () => {
|
|
91
105
|
const sectionBoundaries = sectionsValueBoundaries[section.type]({
|
|
92
106
|
currentDate: activeDate,
|
|
93
107
|
format: section.format,
|
|
94
108
|
contentType: section.contentType
|
|
95
109
|
});
|
|
110
|
+
const getCleanValue = value => cleanDigitSectionValue(utils, value, section.type, section.format, section.hasLeadingZeros, sectionBoundaries);
|
|
96
111
|
if (shouldSetAbsolute) {
|
|
97
112
|
if (section.type === 'year' && !isEnd && !isStart) {
|
|
98
113
|
return utils.formatByString(utils.date(), section.format);
|
|
99
114
|
}
|
|
100
115
|
if (delta > 0 || isStart) {
|
|
101
|
-
return
|
|
116
|
+
return getCleanValue(sectionBoundaries.minimum);
|
|
102
117
|
}
|
|
103
|
-
return
|
|
118
|
+
return getCleanValue(sectionBoundaries.maximum);
|
|
104
119
|
}
|
|
105
|
-
const currentSectionValue =
|
|
120
|
+
const currentSectionValue = parseInt(section.value, 10);
|
|
106
121
|
const newSectionValueNumber = currentSectionValue + delta;
|
|
107
122
|
if (newSectionValueNumber > sectionBoundaries.maximum) {
|
|
108
|
-
return
|
|
123
|
+
return getCleanValue(sectionBoundaries.minimum);
|
|
109
124
|
}
|
|
110
125
|
if (newSectionValueNumber < sectionBoundaries.minimum) {
|
|
111
|
-
return
|
|
126
|
+
return getCleanValue(sectionBoundaries.maximum);
|
|
112
127
|
}
|
|
113
|
-
return
|
|
128
|
+
return getCleanValue(newSectionValueNumber);
|
|
114
129
|
};
|
|
115
130
|
const adjustLetterSection = () => {
|
|
116
131
|
const options = getLetterEditingOptions(utils, section.type, section.format);
|
|
@@ -233,7 +248,7 @@ export const changeSectionValueFormat = (utils, valueStr, currentFormat, newForm
|
|
|
233
248
|
return utils.formatByString(utils.parse(valueStr, currentFormat), newFormat);
|
|
234
249
|
};
|
|
235
250
|
const isFourDigitYearFormat = (utils, format) => utils.formatByString(utils.date(), format).length === 4;
|
|
236
|
-
export const
|
|
251
|
+
export const doesSectionHaveLeadingZeros = (utils, contentType, sectionType, format) => {
|
|
237
252
|
if (contentType !== 'digit') {
|
|
238
253
|
return false;
|
|
239
254
|
}
|
|
@@ -307,13 +322,13 @@ export const splitFormatIntoSections = (utils, localeText, format, date) => {
|
|
|
307
322
|
return expandedToken;
|
|
308
323
|
}
|
|
309
324
|
const sectionConfig = getDateSectionConfigFromFormatToken(utils, token);
|
|
310
|
-
const sectionValue = date == null ? '' : utils.formatByString(date, token);
|
|
311
|
-
const
|
|
325
|
+
const sectionValue = date == null || !utils.isValid(date) ? '' : utils.formatByString(date, token);
|
|
326
|
+
const hasLeadingZeros = doesSectionHaveLeadingZeros(utils, sectionConfig.contentType, sectionConfig.type, token);
|
|
312
327
|
sections.push(_extends({}, sectionConfig, {
|
|
313
328
|
format: token,
|
|
314
329
|
value: sectionValue,
|
|
315
330
|
placeholder: getSectionPlaceholder(utils, localeText, sectionConfig, token),
|
|
316
|
-
hasLeadingZeros
|
|
331
|
+
hasLeadingZeros,
|
|
317
332
|
startSeparator: sections.length === 0 ? startSeparator : '',
|
|
318
333
|
endSeparator: '',
|
|
319
334
|
modified: false
|
|
@@ -406,10 +421,22 @@ export const createDateStrForInputFromSections = sections => {
|
|
|
406
421
|
export const getSectionsBoundaries = utils => {
|
|
407
422
|
const today = utils.date();
|
|
408
423
|
const endOfYear = utils.endOfYear(today);
|
|
409
|
-
const
|
|
424
|
+
const {
|
|
425
|
+
maxDaysInMonth,
|
|
426
|
+
longestMonth
|
|
427
|
+
} = utils.getMonthArray(today).reduce((acc, month) => {
|
|
410
428
|
const daysInMonth = utils.getDaysInMonth(month);
|
|
411
|
-
|
|
412
|
-
|
|
429
|
+
if (daysInMonth > acc.maxDaysInMonth) {
|
|
430
|
+
return {
|
|
431
|
+
maxDaysInMonth: daysInMonth,
|
|
432
|
+
longestMonth: month
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
return acc;
|
|
436
|
+
}, {
|
|
437
|
+
maxDaysInMonth: 0,
|
|
438
|
+
longestMonth: null
|
|
439
|
+
});
|
|
413
440
|
return {
|
|
414
441
|
year: ({
|
|
415
442
|
format
|
|
@@ -426,7 +453,8 @@ export const getSectionsBoundaries = utils => {
|
|
|
426
453
|
currentDate
|
|
427
454
|
}) => ({
|
|
428
455
|
minimum: 1,
|
|
429
|
-
maximum: currentDate != null && utils.isValid(currentDate) ? utils.getDaysInMonth(currentDate) : maxDaysInMonth
|
|
456
|
+
maximum: currentDate != null && utils.isValid(currentDate) ? utils.getDaysInMonth(currentDate) : maxDaysInMonth,
|
|
457
|
+
longestMonth: longestMonth
|
|
430
458
|
}),
|
|
431
459
|
weekDay: ({
|
|
432
460
|
format,
|
|
@@ -567,7 +595,7 @@ export const clampDaySection = (utils, sections, sectionsValueBoundaries) => {
|
|
|
567
595
|
contentType: section.contentType
|
|
568
596
|
});
|
|
569
597
|
return _extends({}, section, {
|
|
570
|
-
value:
|
|
598
|
+
value: cleanDigitSectionValue(utils, dayBoundaries.minimum, section.type, section.format, section.hasLeadingZeros, dayBoundaries)
|
|
571
599
|
});
|
|
572
600
|
});
|
|
573
601
|
const startOfMonth = getDateFromDateSections(utils, sectionsForStartOfMonth);
|
|
@@ -2,7 +2,7 @@ import _extends from "@babel/runtime/helpers/esm/extends";
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import useEventCallback from '@mui/utils/useEventCallback';
|
|
4
4
|
import { useUtils } from '../useUtils';
|
|
5
|
-
import { changeSectionValueFormat,
|
|
5
|
+
import { changeSectionValueFormat, cleanDigitSectionValue, doesSectionHaveLeadingZeros, getDateSectionConfigFromFormatToken, getDaysInWeekStr, getLetterEditingOptions } from './useField.utils';
|
|
6
6
|
const QUERY_LIFE_DURATION_MS = 5000;
|
|
7
7
|
const isQueryResponseWithoutValue = response => response.saveQuery != null;
|
|
8
8
|
|
|
@@ -138,7 +138,7 @@ export const useFieldCharacterEditing = ({
|
|
|
138
138
|
return applyQuery(params, getFirstSectionValueMatchingWithQuery);
|
|
139
139
|
};
|
|
140
140
|
const applyNumericEditing = params => {
|
|
141
|
-
const getNewSectionValue = (queryValue, sectionType, format,
|
|
141
|
+
const getNewSectionValue = (queryValue, sectionType, format, hasLeadingZeros, contentType) => {
|
|
142
142
|
const queryValueNumber = Number(`${queryValue}`);
|
|
143
143
|
const sectionBoundaries = sectionsValueBoundaries[sectionType]({
|
|
144
144
|
currentDate: null,
|
|
@@ -160,12 +160,7 @@ export const useFieldCharacterEditing = ({
|
|
|
160
160
|
};
|
|
161
161
|
}
|
|
162
162
|
const shouldGoToNextSection = Number(`${queryValue}0`) > sectionBoundaries.maximum || queryValue.length === sectionBoundaries.maximum.toString().length;
|
|
163
|
-
|
|
164
|
-
// queryValue without leading `0` (`01` => `1`)
|
|
165
|
-
let newSectionValue = queryValueNumber.toString();
|
|
166
|
-
if (hasTrailingZeroes) {
|
|
167
|
-
newSectionValue = cleanLeadingZerosInNumericSectionValue(utils, format, newSectionValue);
|
|
168
|
-
}
|
|
163
|
+
const newSectionValue = cleanDigitSectionValue(utils, queryValueNumber, sectionType, format, hasLeadingZeros, sectionBoundaries);
|
|
169
164
|
return {
|
|
170
165
|
sectionValue: newSectionValue,
|
|
171
166
|
shouldGoToNextSection
|
|
@@ -179,7 +174,7 @@ export const useFieldCharacterEditing = ({
|
|
|
179
174
|
// When editing a letter-format month and the user presses a digit,
|
|
180
175
|
// We can support the numeric editing by using the digit-format month and re-formatting the result.
|
|
181
176
|
if (activeSection.type === 'month') {
|
|
182
|
-
const response = getNewSectionValue(queryValue, activeSection.type, 'MM',
|
|
177
|
+
const response = getNewSectionValue(queryValue, activeSection.type, 'MM', doesSectionHaveLeadingZeros(utils, 'digit', 'month', 'MM'), 'digit');
|
|
183
178
|
if (isQueryResponseWithoutValue(response)) {
|
|
184
179
|
return response;
|
|
185
180
|
}
|
|
@@ -13,7 +13,7 @@ export interface UpdateSectionValueParams<TSection extends FieldSection> {
|
|
|
13
13
|
*/
|
|
14
14
|
shouldGoToNextSection: boolean;
|
|
15
15
|
}
|
|
16
|
-
export declare const useFieldState: <TValue, TDate, TSection extends FieldSection, TForwardedProps extends UseFieldForwardedProps, TInternalProps extends UseFieldInternalProps<any, any>>(params: UseFieldParams<TValue, TDate, TSection, TForwardedProps, TInternalProps>) => {
|
|
16
|
+
export declare const useFieldState: <TValue, TDate, TSection extends FieldSection, TForwardedProps extends UseFieldForwardedProps, TInternalProps extends UseFieldInternalProps<any, any, any>>(params: UseFieldParams<TValue, TDate, TSection, TForwardedProps, TInternalProps>) => {
|
|
17
17
|
state: UseFieldState<TValue, TSection>;
|
|
18
18
|
selectedSectionIndexes: FieldSelectedSectionsIndexes | null;
|
|
19
19
|
setSelectedSections: (newSelectedSections: FieldSelectedSections) => void;
|
|
@@ -22,6 +22,5 @@ export declare const useFieldState: <TValue, TDate, TSection extends FieldSectio
|
|
|
22
22
|
updateSectionValue: ({ activeSection, newSectionValue, shouldGoToNextSection, }: UpdateSectionValueParams<TSection>) => void;
|
|
23
23
|
updateValueFromValueStr: (valueStr: string) => void;
|
|
24
24
|
setTempAndroidValueStr: (tempValueStrAndroid: string | null) => void;
|
|
25
|
-
sectionOrder: import("./useField.types").SectionOrdering;
|
|
26
25
|
sectionsValueBoundaries: import("./useField.types").FieldSectionsValueBoundaries<TDate>;
|
|
27
26
|
};
|