@mui/x-date-pickers 6.0.3 → 6.0.4
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/AdapterDateFnsJalali/index.js +68 -0
- package/AdapterLuxon/index.js +12 -3
- package/CHANGELOG.md +61 -0
- package/DateCalendar/DateCalendar.types.d.ts +1 -1
- package/DateCalendar/PickersCalendarHeader.d.ts +1 -1
- package/DateCalendar/index.d.ts +0 -1
- package/DateField/DateField.types.d.ts +2 -2
- package/DatePicker/DatePickerToolbar.d.ts +1 -1
- package/DatePicker/shared.d.ts +2 -2
- package/DateTimeField/DateTimeField.types.d.ts +2 -2
- package/DateTimePicker/DateTimePickerTabs.d.ts +1 -1
- package/DateTimePicker/DateTimePickerToolbar.d.ts +1 -1
- package/DateTimePicker/shared.d.ts +1 -2
- package/DesktopDatePicker/DesktopDatePicker.types.d.ts +1 -1
- package/DesktopDateTimePicker/DesktopDateTimePicker.types.d.ts +1 -1
- package/DesktopTimePicker/DesktopTimePicker.types.d.ts +1 -1
- package/MobileDatePicker/MobileDatePicker.types.d.ts +1 -1
- package/MobileDateTimePicker/MobileDateTimePicker.types.d.ts +1 -1
- package/MobileTimePicker/MobileTimePicker.types.d.ts +1 -1
- package/PickersLayout/PickersLayout.d.ts +1 -1
- package/PickersLayout/PickersLayout.types.d.ts +1 -1
- package/PickersLayout/index.d.ts +1 -1
- package/PickersLayout/usePickerLayout.d.ts +1 -1
- package/README.md +1 -1
- package/StaticDatePicker/StaticDatePicker.types.d.ts +2 -1
- package/StaticDateTimePicker/StaticDateTimePicker.types.d.ts +2 -1
- package/StaticTimePicker/StaticTimePicker.types.d.ts +2 -1
- package/TimeClock/Clock.d.ts +1 -1
- package/TimeClock/ClockPointer.d.ts +1 -1
- package/TimeClock/TimeClock.types.d.ts +1 -1
- package/TimeClock/index.d.ts +0 -1
- package/TimeField/TimeField.types.d.ts +2 -2
- package/TimePicker/TimePickerToolbar.d.ts +1 -1
- package/TimePicker/shared.d.ts +1 -2
- package/dateViewRenderers/dateViewRenderers.d.ts +1 -1
- package/index.js +1 -1
- package/internals/components/PickersToolbar.d.ts +1 -1
- package/internals/demo/DemoContainer.js +15 -7
- package/internals/hooks/useDesktopPicker/useDesktopPicker.d.ts +1 -1
- package/internals/hooks/useDesktopPicker/useDesktopPicker.types.d.ts +4 -5
- package/internals/hooks/useField/index.d.ts +1 -1
- package/internals/hooks/useField/useField.d.ts +2 -1
- package/internals/hooks/useField/useField.js +9 -7
- package/internals/hooks/useField/useField.types.d.ts +24 -104
- package/internals/hooks/useField/useField.utils.d.ts +7 -5
- package/internals/hooks/useField/useField.utils.js +68 -50
- package/internals/hooks/useField/useFieldCharacterEditing.d.ts +2 -1
- package/internals/hooks/useField/useFieldState.d.ts +3 -1
- package/internals/hooks/useField/useFieldState.js +88 -62
- package/internals/hooks/useIsLandscape.d.ts +1 -1
- package/internals/hooks/useMobilePicker/useMobilePicker.d.ts +1 -1
- package/internals/hooks/useMobilePicker/useMobilePicker.types.d.ts +4 -5
- package/internals/hooks/usePicker/usePicker.d.ts +1 -2
- package/internals/hooks/usePicker/usePicker.types.d.ts +1 -2
- package/internals/hooks/usePicker/usePickerLayoutProps.d.ts +1 -1
- package/internals/hooks/usePicker/usePickerValue.d.ts +2 -1
- package/internals/hooks/usePicker/usePickerViews.d.ts +1 -1
- package/internals/hooks/useStaticPicker/useStaticPicker.d.ts +1 -1
- package/internals/hooks/useStaticPicker/useStaticPicker.types.d.ts +1 -2
- package/internals/hooks/useViews.d.ts +1 -1
- package/internals/hooks/useViews.js +8 -0
- package/internals/hooks/validation/models.d.ts +1 -1
- package/internals/hooks/validation/useDateTimeValidation.d.ts +3 -3
- package/internals/hooks/validation/useDateValidation.d.ts +2 -2
- package/internals/hooks/validation/useTimeValidation.d.ts +2 -2
- package/internals/index.d.ts +3 -7
- package/internals/index.js +1 -1
- package/internals/models/fields.d.ts +2 -20
- package/internals/models/index.d.ts +0 -1
- package/internals/models/index.js +0 -1
- package/internals/models/muiPickersAdapter.d.ts +1 -10
- package/internals/models/props/basePickerProps.d.ts +3 -3
- package/internals/models/props/tabs.d.ts +1 -1
- package/internals/models/props/toolbar.d.ts +1 -1
- package/internals/utils/time-utils.d.ts +2 -1
- package/internals/utils/utils.d.ts +1 -1
- package/internals/utils/utils.js +3 -3
- package/internals/utils/validation.d.ts +1 -1
- package/internals/utils/valueManagers.d.ts +2 -4
- package/internals/utils/valueManagers.js +8 -8
- package/internals/utils/views.d.ts +1 -1
- package/legacy/AdapterDateFnsJalali/index.js +68 -0
- package/legacy/AdapterLuxon/index.js +12 -3
- package/legacy/index.js +1 -1
- package/legacy/internals/demo/DemoContainer.js +12 -6
- package/legacy/internals/hooks/useField/useField.js +10 -8
- package/legacy/internals/hooks/useField/useField.utils.js +76 -54
- package/legacy/internals/hooks/useField/useFieldState.js +94 -67
- package/legacy/internals/hooks/useViews.js +10 -0
- package/legacy/internals/index.js +1 -1
- package/legacy/internals/models/index.js +0 -1
- package/legacy/internals/utils/utils.js +3 -3
- package/legacy/internals/utils/valueManagers.js +10 -12
- package/legacy/locales/daDK.js +91 -0
- package/legacy/locales/nbNO.js +12 -10
- package/legacy/locales/svSE.js +12 -10
- package/legacy/models/index.js +3 -1
- package/locales/daDK.d.ts +51 -0
- package/locales/daDK.js +59 -0
- package/locales/nbNO.js +8 -10
- package/locales/nlNL.d.ts +4 -4
- package/locales/svSE.js +8 -10
- package/locales/utils/pickersLocaleTextApi.d.ts +2 -1
- package/models/fields.d.ts +117 -0
- package/models/fields.js +1 -0
- package/models/index.d.ts +3 -6
- package/models/index.js +3 -1
- package/models/validation.d.ts +8 -0
- package/models/validation.js +1 -0
- package/models/views.js +1 -0
- package/modern/AdapterDateFnsJalali/index.js +68 -0
- package/modern/AdapterLuxon/index.js +12 -3
- package/modern/index.js +1 -1
- package/modern/internals/demo/DemoContainer.js +15 -7
- package/modern/internals/hooks/useField/useField.js +8 -6
- package/modern/internals/hooks/useField/useField.utils.js +68 -50
- package/modern/internals/hooks/useField/useFieldState.js +88 -62
- package/modern/internals/hooks/useViews.js +8 -0
- package/modern/internals/index.js +1 -1
- package/modern/internals/models/index.js +0 -1
- package/modern/internals/utils/utils.js +3 -3
- package/modern/internals/utils/valueManagers.js +8 -8
- package/modern/locales/daDK.js +56 -0
- package/modern/locales/nbNO.js +8 -10
- package/modern/locales/svSE.js +8 -10
- package/modern/models/fields.js +1 -0
- package/modern/models/index.js +3 -1
- package/modern/models/validation.js +1 -0
- package/modern/models/views.js +1 -0
- package/node/AdapterDateFnsJalali/index.js +68 -0
- package/node/AdapterLuxon/index.js +12 -3
- package/node/index.js +1 -1
- package/node/internals/demo/DemoContainer.js +15 -7
- package/node/internals/hooks/useField/useField.js +8 -6
- package/node/internals/hooks/useField/useField.utils.js +71 -52
- package/node/internals/hooks/useField/useFieldState.js +87 -61
- package/node/internals/hooks/useViews.js +8 -0
- package/node/internals/index.js +0 -6
- package/node/internals/models/index.js +0 -11
- package/node/internals/utils/utils.js +3 -3
- package/node/internals/utils/valueManagers.js +7 -7
- package/node/locales/daDK.js +62 -0
- package/node/locales/nbNO.js +8 -10
- package/node/locales/svSE.js +8 -10
- package/node/models/index.js +33 -0
- package/node/models/validation.js +5 -0
- package/node/models/views.js +5 -0
- package/package.json +1 -1
- package/themeAugmentation/props.d.ts +1 -1
- package/timeViewRenderers/timeViewRenderers.d.ts +1 -1
- /package/{internals/models/views.js → legacy/models/fields.js} +0 -0
- /package/legacy/{internals/models/views.js → models/validation.js} +0 -0
- /package/{modern/internals → legacy}/models/views.js +0 -0
- /package/{internals/models → models}/views.d.ts +0 -0
- /package/node/{internals/models/views.js → models/fields.js} +0 -0
|
@@ -23,7 +23,8 @@ export const useField = params => {
|
|
|
23
23
|
updateSectionValue,
|
|
24
24
|
updateValueFromValueStr,
|
|
25
25
|
setTempAndroidValueStr,
|
|
26
|
-
sectionsValueBoundaries
|
|
26
|
+
sectionsValueBoundaries,
|
|
27
|
+
placeholder
|
|
27
28
|
} = useFieldState(params);
|
|
28
29
|
const {
|
|
29
30
|
applyCharacterEditing,
|
|
@@ -59,7 +60,8 @@ export const useField = params => {
|
|
|
59
60
|
const handleRef = useForkRef(inputRefProp, inputRef);
|
|
60
61
|
const focusTimeoutRef = React.useRef(undefined);
|
|
61
62
|
const theme = useTheme();
|
|
62
|
-
const
|
|
63
|
+
const isRTL = theme.direction === 'rtl';
|
|
64
|
+
const sectionOrder = React.useMemo(() => getSectionOrder(state.sections, isRTL), [state.sections, isRTL]);
|
|
63
65
|
const syncSelectionFromDOM = () => {
|
|
64
66
|
var _selectionStart;
|
|
65
67
|
if (readOnly) {
|
|
@@ -151,7 +153,7 @@ export const useField = params => {
|
|
|
151
153
|
if (selectedSectionIndexes.startIndex === 0 && selectedSectionIndexes.endIndex === state.sections.length - 1) {
|
|
152
154
|
keyPressed = cleanValueStr;
|
|
153
155
|
} else {
|
|
154
|
-
const prevValueStr = cleanString(fieldValueManager.getValueStrFromSections(state.sections));
|
|
156
|
+
const prevValueStr = cleanString(fieldValueManager.getValueStrFromSections(state.sections, isRTL));
|
|
155
157
|
let startOfDiffIndex = -1;
|
|
156
158
|
let endOfDiffIndex = -1;
|
|
157
159
|
for (let i = 0; i < prevValueStr.length; i += 1) {
|
|
@@ -256,7 +258,7 @@ export const useField = params => {
|
|
|
256
258
|
}
|
|
257
259
|
const activeSection = state.sections[selectedSectionIndexes.startIndex];
|
|
258
260
|
const activeDateManager = fieldValueManager.getActiveDateManager(utils, state, activeSection);
|
|
259
|
-
const newSectionValue = adjustSectionValue(utils, activeSection, event.key, sectionsValueBoundaries, activeDateManager.
|
|
261
|
+
const newSectionValue = adjustSectionValue(utils, activeSection, event.key, sectionsValueBoundaries, activeDateManager.date);
|
|
260
262
|
updateSectionValue({
|
|
261
263
|
activeSection,
|
|
262
264
|
newSectionValue,
|
|
@@ -324,8 +326,8 @@ export const useField = params => {
|
|
|
324
326
|
|
|
325
327
|
const valueStr = React.useMemo(() => {
|
|
326
328
|
var _state$tempValueStrAn;
|
|
327
|
-
return (_state$tempValueStrAn = state.tempValueStrAndroid) != null ? _state$tempValueStrAn : fieldValueManager.getValueStrFromSections(state.sections);
|
|
328
|
-
}, [state.sections, fieldValueManager, state.tempValueStrAndroid]);
|
|
329
|
+
return (_state$tempValueStrAn = state.tempValueStrAndroid) != null ? _state$tempValueStrAn : fieldValueManager.getValueStrFromSections(state.sections, isRTL);
|
|
330
|
+
}, [state.sections, fieldValueManager, state.tempValueStrAndroid, isRTL]);
|
|
329
331
|
const inputMode = React.useMemo(() => {
|
|
330
332
|
if (selectedSectionIndexes == null) {
|
|
331
333
|
return 'text';
|
|
@@ -353,7 +355,7 @@ export const useField = params => {
|
|
|
353
355
|
setSelectedSections: activeSectionIndex => setSelectedSections(activeSectionIndex)
|
|
354
356
|
}));
|
|
355
357
|
return _extends({
|
|
356
|
-
placeholder
|
|
358
|
+
placeholder,
|
|
357
359
|
autoComplete: 'off'
|
|
358
360
|
}, otherForwardedProps, {
|
|
359
361
|
value: shouldShowPlaceholder ? '' : valueStr,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { MuiPickersAdapter } from '../../models';
|
|
3
|
+
import { FieldSectionType, FieldSection, FieldSelectedSections } from '../../../models';
|
|
3
4
|
import type { PickerValueManager } from '../usePicker';
|
|
4
5
|
import { InferError, Validator } from '../validation/useValidation';
|
|
5
|
-
import { PickersLocaleText } from '../../../locales/utils/pickersLocaleTextApi';
|
|
6
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;
|
|
@@ -103,76 +103,6 @@ export type UseFieldResponse<TForwardedProps extends UseFieldForwardedProps> = O
|
|
|
103
103
|
readOnly: boolean;
|
|
104
104
|
autoComplete: 'off';
|
|
105
105
|
};
|
|
106
|
-
export interface FieldSection {
|
|
107
|
-
/**
|
|
108
|
-
* Value of the section, as rendered inside the input.
|
|
109
|
-
* For example, in the date `May 25, 1995`, the value of the month section is "May".
|
|
110
|
-
*/
|
|
111
|
-
value: string;
|
|
112
|
-
/**
|
|
113
|
-
* Format token used to parse the value of this section from the date object.
|
|
114
|
-
* For example, in the format `MMMM D, YYYY`, the format of the month section is "MMMM".
|
|
115
|
-
*/
|
|
116
|
-
format: string;
|
|
117
|
-
/**
|
|
118
|
-
* Placeholder rendered when the value of this section is empty.
|
|
119
|
-
*/
|
|
120
|
-
placeholder: string;
|
|
121
|
-
/**
|
|
122
|
-
* Type of the section.
|
|
123
|
-
*/
|
|
124
|
-
type: FieldSectionType;
|
|
125
|
-
/**
|
|
126
|
-
* Type of content of the section.
|
|
127
|
-
* Will determine if we should apply a digit-based editing or a letter-based editing.
|
|
128
|
-
*/
|
|
129
|
-
contentType: 'digit' | 'letter';
|
|
130
|
-
/**
|
|
131
|
-
* If `true`, the value of this section is supposed to have leading zeroes.
|
|
132
|
-
* For example, the value `1` should be rendered as "01" instead of "1".
|
|
133
|
-
*/
|
|
134
|
-
hasLeadingZeros: boolean;
|
|
135
|
-
/**
|
|
136
|
-
* If `true`, the section value has been modified since the last time the sections were generated from a valid date.
|
|
137
|
-
* When we can generate a valid date from the section, we don't directly pass it to `onChange`,
|
|
138
|
-
* Otherwise, we would lose all the information contained in the original date, things like:
|
|
139
|
-
* - time if the format does not contain it
|
|
140
|
-
* - timezone / UTC
|
|
141
|
-
*
|
|
142
|
-
* To avoid losing that information, we transfer the values of the modified sections from the newly generated date to the original date.
|
|
143
|
-
*/
|
|
144
|
-
modified: boolean;
|
|
145
|
-
/**
|
|
146
|
-
* Start index of the section in the format
|
|
147
|
-
*/
|
|
148
|
-
start: number;
|
|
149
|
-
/**
|
|
150
|
-
* End index of the section in the format
|
|
151
|
-
*/
|
|
152
|
-
end: number;
|
|
153
|
-
/**
|
|
154
|
-
* Start index of the section value in the input.
|
|
155
|
-
* Takes into account invisible unicode characters such as \u2069 but does not include them
|
|
156
|
-
*/
|
|
157
|
-
startInInput: number;
|
|
158
|
-
/**
|
|
159
|
-
* End index of the section value in the input.
|
|
160
|
-
* Takes into account invisible unicode characters such as \u2069 but does not include them
|
|
161
|
-
*/
|
|
162
|
-
endInInput: number;
|
|
163
|
-
/**
|
|
164
|
-
* Separator displayed before the value of the section in the input.
|
|
165
|
-
* If it contains escaped characters, then it must not have the escaping characters.
|
|
166
|
-
* For example, on Day.js, the `year` section of the format `YYYY [year]` has an end separator equal to `year` not `[year]`
|
|
167
|
-
*/
|
|
168
|
-
startSeparator: string;
|
|
169
|
-
/**
|
|
170
|
-
* Separator displayed after the value of the section in the input.
|
|
171
|
-
* If it contains escaped characters, then it must not have the escaping characters.
|
|
172
|
-
* For example, on Day.js, the `year` section of the format `[year] YYYY` has a start separator equal to `[year]`
|
|
173
|
-
*/
|
|
174
|
-
endSeparator: string;
|
|
175
|
-
}
|
|
176
106
|
export type FieldSectionWithoutPosition<TSection extends FieldSection = FieldSection> = Omit<TSection, 'start' | 'end' | 'startInInput' | 'endInInput'>;
|
|
177
107
|
export type FieldSectionValueBoundaries<TDate, SectionType extends FieldSectionType> = {
|
|
178
108
|
minimum: number;
|
|
@@ -192,25 +122,32 @@ export interface FieldChangeHandlerContext<TError> {
|
|
|
192
122
|
validationError: TError;
|
|
193
123
|
}
|
|
194
124
|
/**
|
|
195
|
-
* Object used to access and update the active
|
|
125
|
+
* Object used to access and update the active date (i.e: the date containing the active section).
|
|
196
126
|
* Mainly useful in the range fields where we need to update the date containing the active section without impacting the other one.
|
|
197
127
|
*/
|
|
198
|
-
interface FieldActiveDateManager<TValue, TDate> {
|
|
128
|
+
interface FieldActiveDateManager<TValue, TDate, TSection extends FieldSection> {
|
|
199
129
|
/**
|
|
200
|
-
*
|
|
130
|
+
* Active date from `state.value`.
|
|
201
131
|
*/
|
|
202
|
-
|
|
132
|
+
date: TDate | null;
|
|
203
133
|
/**
|
|
204
|
-
*
|
|
134
|
+
* Active date from the `state.referenceValue`.
|
|
205
135
|
*/
|
|
206
|
-
|
|
136
|
+
referenceDate: TDate;
|
|
137
|
+
/**
|
|
138
|
+
* @template TSection
|
|
139
|
+
* @param {TSection[]} sections The sections of the full value.
|
|
140
|
+
* @returns {TSection[]} The sections of the active date.
|
|
141
|
+
* Get the sections of the active date.
|
|
142
|
+
*/
|
|
143
|
+
getSections: (sections: TSection[]) => TSection[];
|
|
207
144
|
/**
|
|
208
145
|
* Creates the new value and reference value based on the new active date and the current state.
|
|
209
146
|
* @template TValue, TDate
|
|
210
147
|
* @param {TDate | null} newActiveDate The new value of the date containing the active section.
|
|
211
148
|
* @returns {Pick<UseFieldState<TValue, any>, 'value' | 'referenceValue'>} The new value and reference value to publish and store in the state.
|
|
212
149
|
*/
|
|
213
|
-
|
|
150
|
+
getNewValuesFromNewActiveDate: (newActiveDate: TDate | null) => Pick<UseFieldState<TValue, any>, 'value' | 'referenceValue'>;
|
|
214
151
|
}
|
|
215
152
|
export type FieldSelectedSectionsIndexes = {
|
|
216
153
|
startIndex: number;
|
|
@@ -221,49 +158,36 @@ export type FieldSelectedSectionsIndexes = {
|
|
|
221
158
|
*/
|
|
222
159
|
shouldSelectBoundarySelectors?: boolean;
|
|
223
160
|
};
|
|
224
|
-
export type FieldSelectedSections = number | FieldSectionType | null | 'all' | {
|
|
225
|
-
startIndex: number;
|
|
226
|
-
endIndex: number;
|
|
227
|
-
};
|
|
228
161
|
export interface FieldValueManager<TValue, TDate, TSection extends FieldSection, TError> {
|
|
229
162
|
/**
|
|
230
163
|
* Creates the section list from the current value.
|
|
231
164
|
* The `prevSections` are used on the range fields to avoid losing the sections of a partially filled date when editing the other date.
|
|
232
165
|
* @template TValue, TDate, TSection
|
|
233
166
|
* @param {MuiPickersAdapter<TDate>} utils The utils to manipulate the date.
|
|
234
|
-
* @param {PickersLocaleText<TDate>} localeText The localization object to generate the placeholders.
|
|
235
|
-
* @param {TSection[] | null} sections The sections to use as a fallback if a date is null or invalid.
|
|
236
167
|
* @param {TValue} value The current value to generate sections from.
|
|
237
|
-
* @param {
|
|
168
|
+
* @param {TSection[] | null} fallbackSections The sections to use as a fallback if a date is null or invalid.
|
|
169
|
+
* @param {boolean} isRTL `true` if the direction is "right to left".
|
|
170
|
+
* @param {(date: TDate) => FieldSectionWithoutPosition[]} getSectionsFromDate Returns the sections of the given date.
|
|
238
171
|
* @returns {TSection[]} The new section list.
|
|
239
172
|
*/
|
|
240
|
-
getSectionsFromValue: (utils: MuiPickersAdapter<TDate>,
|
|
173
|
+
getSectionsFromValue: (utils: MuiPickersAdapter<TDate>, value: TValue, fallbackSections: TSection[] | null, isRTL: boolean, getSectionsFromDate: (date: TDate) => FieldSectionWithoutPosition[]) => TSection[];
|
|
241
174
|
/**
|
|
242
175
|
* Creates the string value to render in the input based on the current section list.
|
|
243
176
|
* @template TSection
|
|
244
177
|
* @param {TSection[]} sections The current section list.
|
|
178
|
+
* @param {boolean} isRTL `true` is the current orientation is "right to left"
|
|
245
179
|
* @returns {string} The string value to render in the input.
|
|
246
180
|
*/
|
|
247
|
-
getValueStrFromSections: (sections: TSection[]) => string;
|
|
248
|
-
/**
|
|
249
|
-
* Filter the section list to only keep the sections in the same date as the active section.
|
|
250
|
-
* On a single date field does nothing.
|
|
251
|
-
* On a range date range, returns the sections of the start date if editing the start date and the end date otherwise.
|
|
252
|
-
* @template TSection
|
|
253
|
-
* @param {TSection[]} sections The full section list.
|
|
254
|
-
* @param {TSection} activeSection The active section.
|
|
255
|
-
* @returns {TSection[]} The sections in the same date as the active section.
|
|
256
|
-
*/
|
|
257
|
-
getActiveDateSections: (sections: TSection[], activeSection: TSection) => TSection[];
|
|
181
|
+
getValueStrFromSections: (sections: TSection[], isRTL: boolean) => string;
|
|
258
182
|
/**
|
|
259
183
|
* Returns the manager of the active date.
|
|
260
184
|
* @template TValue, TDate, TSection
|
|
261
185
|
* @param {MuiPickersAdapter<TDate>} utils The utils to manipulate the date.
|
|
262
186
|
* @param {UseFieldState<TValue, TSection>} state The current state of the field.
|
|
263
187
|
* @param {TSection} activeSection The active section.
|
|
264
|
-
* @returns {FieldActiveDateManager<TValue, TDate>} The manager of the active date.
|
|
188
|
+
* @returns {FieldActiveDateManager<TValue, TDate, TSection>} The manager of the active date.
|
|
265
189
|
*/
|
|
266
|
-
getActiveDateManager: (utils: MuiPickersAdapter<TDate>, state: UseFieldState<TValue, TSection>, activeSection: TSection) => FieldActiveDateManager<TValue, TDate>;
|
|
190
|
+
getActiveDateManager: (utils: MuiPickersAdapter<TDate>, state: UseFieldState<TValue, TSection>, activeSection: TSection) => FieldActiveDateManager<TValue, TDate, TSection>;
|
|
267
191
|
/**
|
|
268
192
|
* Parses a string version (most of the time coming from the input).
|
|
269
193
|
* This method should only be used when the change does not come from a single section.
|
|
@@ -299,10 +223,6 @@ export interface UseFieldState<TValue, TSection extends FieldSection> {
|
|
|
299
223
|
* It is updated whenever we have a valid date (for the range picker we update only the portion of the range that is valid).
|
|
300
224
|
*/
|
|
301
225
|
referenceValue: TValue;
|
|
302
|
-
/**
|
|
303
|
-
* A localized format string built from sections.
|
|
304
|
-
*/
|
|
305
|
-
placeholder: string;
|
|
306
226
|
sections: TSection[];
|
|
307
227
|
/**
|
|
308
228
|
* Android `onChange` behavior when the input selection is not empty is quite different from a desktop behavior.
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { MuiPickersAdapter
|
|
1
|
+
import { AvailableAdjustKeyCode, FieldSectionsValueBoundaries, SectionOrdering, FieldValueType, FieldSectionWithoutPosition, FieldSectionValueBoundaries } from './useField.types';
|
|
2
|
+
import { MuiPickersAdapter } from '../../models';
|
|
3
|
+
import { FieldSectionType, FieldSection } from '../../../models';
|
|
3
4
|
import { PickersLocaleText } from '../../../locales/utils/pickersLocaleTextApi';
|
|
4
5
|
export declare const getDateSectionConfigFromFormatToken: <TDate>(utils: MuiPickersAdapter<TDate>, formatToken: string) => Pick<FieldSection, 'type' | 'contentType'>;
|
|
5
6
|
export declare const getDaysInWeekStr: <TDate>(utils: MuiPickersAdapter<TDate>, format: string) => string[];
|
|
6
7
|
export declare const getLetterEditingOptions: <TDate>(utils: MuiPickersAdapter<TDate>, sectionType: FieldSectionType, format: string) => string[];
|
|
7
8
|
export declare const cleanDigitSectionValue: <TDate>(utils: MuiPickersAdapter<TDate>, value: number, sectionType: FieldSectionType, format: string, hasLeadingZeros: boolean, sectionBoundaries: FieldSectionValueBoundaries<TDate, any>) => string;
|
|
8
9
|
export declare const adjustSectionValue: <TDate, TSection extends FieldSection>(utils: MuiPickersAdapter<TDate>, section: TSection, keyCode: AvailableAdjustKeyCode, sectionsValueBoundaries: FieldSectionsValueBoundaries<TDate>, activeDate: TDate | null) => string;
|
|
10
|
+
export declare const getSectionVisibleValue: (section: FieldSectionWithoutPosition, target: 'input-rtl' | 'input-ltr' | 'non-input') => string;
|
|
9
11
|
export declare const cleanString: (dirtyString: string) => string;
|
|
10
|
-
export declare const addPositionPropertiesToSections: <TSection extends FieldSection>(sections: FieldSectionWithoutPosition<TSection>[]) => TSection[];
|
|
12
|
+
export declare const addPositionPropertiesToSections: <TSection extends FieldSection>(sections: FieldSectionWithoutPosition<TSection>[], isRTL: boolean) => TSection[];
|
|
11
13
|
export declare const changeSectionValueFormat: <TDate>(utils: MuiPickersAdapter<TDate>, valueStr: string, currentFormat: string, newFormat: string) => string;
|
|
12
14
|
export declare const doesSectionHaveLeadingZeros: <TDate>(utils: MuiPickersAdapter<TDate>, contentType: 'digit' | 'letter', sectionType: FieldSectionType, format: string) => boolean;
|
|
13
15
|
export declare const splitFormatIntoSections: <TDate>(utils: MuiPickersAdapter<TDate>, localeText: PickersLocaleText<TDate>, format: string, date: TDate | null) => FieldSectionWithoutPosition<FieldSection>[];
|
|
@@ -16,10 +18,10 @@ export declare const splitFormatIntoSections: <TDate>(utils: MuiPickersAdapter<T
|
|
|
16
18
|
* To make sure that the parsing works, we are building a format and a date without any separator.
|
|
17
19
|
*/
|
|
18
20
|
export declare const getDateFromDateSections: <TDate>(utils: MuiPickersAdapter<TDate>, sections: FieldSection[]) => TDate | null;
|
|
19
|
-
export declare const createDateStrForInputFromSections: (sections: FieldSection[]) => string;
|
|
21
|
+
export declare const createDateStrForInputFromSections: (sections: FieldSection[], isRTL: boolean) => string;
|
|
20
22
|
export declare const getSectionsBoundaries: <TDate>(utils: MuiPickersAdapter<TDate>) => FieldSectionsValueBoundaries<TDate>;
|
|
21
23
|
export declare const validateSections: <TSection extends FieldSection>(sections: TSection[], valueType: FieldValueType) => void;
|
|
22
24
|
export declare const mergeDateIntoReferenceDate: <TDate>(utils: MuiPickersAdapter<TDate>, dateToTransferFrom: TDate, sections: FieldSectionWithoutPosition[], referenceDate: TDate, shouldLimitToEditedSections: boolean) => TDate;
|
|
23
25
|
export declare const isAndroid: () => boolean;
|
|
24
|
-
export declare const
|
|
26
|
+
export declare const clampDaySectionIfPossible: <TDate, TSection extends FieldSection>(utils: MuiPickersAdapter<TDate>, sections: TSection[], sectionsValueBoundaries: FieldSectionsValueBoundaries<TDate>) => TSection[] | null;
|
|
25
27
|
export declare const getSectionOrder: (sections: FieldSectionWithoutPosition[], isRTL: boolean) => SectionOrdering;
|
|
@@ -147,32 +147,31 @@ export const adjustSectionValue = (utils, section, keyCode, sectionsValueBoundar
|
|
|
147
147
|
}
|
|
148
148
|
return adjustLetterSection();
|
|
149
149
|
};
|
|
150
|
-
const getSectionVisibleValue = (section,
|
|
151
|
-
|
|
150
|
+
export const getSectionVisibleValue = (section, target) => {
|
|
151
|
+
let value = section.value || section.placeholder;
|
|
152
152
|
|
|
153
153
|
// In the input, we add an empty character at the end of each section without leading zeros.
|
|
154
154
|
// This makes sure that `onChange` will always be fired.
|
|
155
155
|
// Otherwise, when your input value equals `1/dd/yyyy` (format `M/DD/YYYY` on DayJs),
|
|
156
156
|
// If you press `1`, on the first section, the new value is also `1/dd/yyyy`,
|
|
157
157
|
// So the browser will not fire the input `onChange`.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return `\u2068${value}\u200e\u2069`;
|
|
158
|
+
const shouldAddInvisibleSpace = ['input-rtl', 'input-ltr'].includes(target) && section.contentType === 'digit' && !section.hasLeadingZeros && value.length === 1;
|
|
159
|
+
if (shouldAddInvisibleSpace) {
|
|
160
|
+
value = `${value}\u200e`;
|
|
162
161
|
}
|
|
163
|
-
if (
|
|
164
|
-
|
|
162
|
+
if (target === 'input-rtl') {
|
|
163
|
+
value = `\u2068${value}\u2069`;
|
|
165
164
|
}
|
|
166
165
|
return value;
|
|
167
166
|
};
|
|
168
167
|
export const cleanString = dirtyString => dirtyString.replace(/[\u2066\u2067\u2068\u2069]/g, '');
|
|
169
|
-
export const addPositionPropertiesToSections = sections => {
|
|
168
|
+
export const addPositionPropertiesToSections = (sections, isRTL) => {
|
|
170
169
|
let position = 0;
|
|
171
|
-
let positionInInput = 1;
|
|
170
|
+
let positionInInput = isRTL ? 1 : 0;
|
|
172
171
|
const newSections = [];
|
|
173
172
|
for (let i = 0; i < sections.length; i += 1) {
|
|
174
173
|
const section = sections[i];
|
|
175
|
-
const renderedValue = getSectionVisibleValue(section,
|
|
174
|
+
const renderedValue = getSectionVisibleValue(section, isRTL ? 'input-rtl' : 'input-ltr');
|
|
176
175
|
const sectionStr = `${section.startSeparator}${renderedValue}${section.endSeparator}`;
|
|
177
176
|
const sectionLength = cleanString(sectionStr).length;
|
|
178
177
|
const sectionLengthInInput = sectionStr.length;
|
|
@@ -317,10 +316,6 @@ export const splitFormatIntoSections = (utils, localeText, format, date) => {
|
|
|
317
316
|
if (token === '') {
|
|
318
317
|
return null;
|
|
319
318
|
}
|
|
320
|
-
const expandedToken = utils.expandFormat(token);
|
|
321
|
-
if (expandedToken !== token) {
|
|
322
|
-
return expandedToken;
|
|
323
|
-
}
|
|
324
319
|
const sectionConfig = getDateSectionConfigFromFormatToken(utils, token);
|
|
325
320
|
const sectionValue = date == null || !utils.isValid(date) ? '' : utils.formatByString(date, token);
|
|
326
321
|
const hasLeadingZeros = doesSectionHaveLeadingZeros(utils, sectionConfig.contentType, sectionConfig.type, token);
|
|
@@ -335,39 +330,50 @@ export const splitFormatIntoSections = (utils, localeText, format, date) => {
|
|
|
335
330
|
}));
|
|
336
331
|
return null;
|
|
337
332
|
};
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
333
|
+
|
|
334
|
+
// Expand the provided format
|
|
335
|
+
let formatExpansionOverflow = 10;
|
|
336
|
+
let prevFormat = format;
|
|
337
|
+
let nextFormat = utils.expandFormat(format);
|
|
338
|
+
while (nextFormat !== prevFormat) {
|
|
339
|
+
prevFormat = nextFormat;
|
|
340
|
+
nextFormat = utils.expandFormat(prevFormat);
|
|
341
|
+
formatExpansionOverflow -= 1;
|
|
342
|
+
if (formatExpansionOverflow < 0) {
|
|
343
|
+
throw new Error('MUI: The format expansion seems to be enter in an infinite loop. Please open an issue with the format passed to the picker component');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
const expandedFormat = nextFormat;
|
|
347
|
+
|
|
348
|
+
// Get start/end indexes of escaped sections
|
|
349
|
+
const escapedParts = getEscapedPartsFromFormat(utils, expandedFormat);
|
|
350
|
+
|
|
351
|
+
// This RegExp test if the beginning of a string correspond to a supported token
|
|
352
|
+
const isTokenStartRegExp = new RegExp(`^(${Object.keys(utils.formatTokenMap).join('|')})`);
|
|
353
|
+
let currentTokenValue = '';
|
|
354
|
+
for (let i = 0; i < expandedFormat.length; i += 1) {
|
|
355
|
+
const escapedPartOfCurrentChar = escapedParts.find(escapeIndex => escapeIndex.start <= i && escapeIndex.end >= i);
|
|
356
|
+
const char = expandedFormat[i];
|
|
357
|
+
const isEscapedChar = escapedPartOfCurrentChar != null;
|
|
358
|
+
const potentialToken = `${currentTokenValue}${expandedFormat.slice(i)}`;
|
|
359
|
+
if (!isEscapedChar && char.match(/([A-Za-z]+)/) && isTokenStartRegExp.test(potentialToken)) {
|
|
360
|
+
currentTokenValue += char;
|
|
361
|
+
} else {
|
|
362
|
+
// If we are on the opening or closing character of an escaped part of the format,
|
|
363
|
+
// Then we ignore this character.
|
|
364
|
+
const isEscapeBoundary = isEscapedChar && (escapedPartOfCurrentChar == null ? void 0 : escapedPartOfCurrentChar.start) === i || (escapedPartOfCurrentChar == null ? void 0 : escapedPartOfCurrentChar.end) === i;
|
|
365
|
+
if (!isEscapeBoundary) {
|
|
366
|
+
commitToken(currentTokenValue);
|
|
367
|
+
currentTokenValue = '';
|
|
368
|
+
if (sections.length === 0) {
|
|
369
|
+
startSeparator += char;
|
|
370
|
+
} else {
|
|
371
|
+
sections[sections.length - 1].endSeparator += char;
|
|
362
372
|
}
|
|
363
373
|
}
|
|
364
374
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
splitFormat(expandedToken);
|
|
368
|
-
}
|
|
369
|
-
};
|
|
370
|
-
splitFormat(format);
|
|
375
|
+
}
|
|
376
|
+
commitToken(currentTokenValue);
|
|
371
377
|
return sections.map(section => {
|
|
372
378
|
const cleanSeparator = separator => {
|
|
373
379
|
let cleanedSeparator = separator;
|
|
@@ -401,22 +407,26 @@ export const getDateFromDateSections = (utils, sections) => {
|
|
|
401
407
|
const shouldSkip = shouldSkipWeekDays && section.type === 'weekDay';
|
|
402
408
|
if (!shouldSkip) {
|
|
403
409
|
sectionFormats.push(section.format);
|
|
404
|
-
sectionValues.push(getSectionVisibleValue(section,
|
|
410
|
+
sectionValues.push(getSectionVisibleValue(section, 'non-input'));
|
|
405
411
|
}
|
|
406
412
|
}
|
|
407
413
|
const formatWithoutSeparator = sectionFormats.join(' ');
|
|
408
414
|
const dateWithoutSeparatorStr = sectionValues.join(' ');
|
|
409
415
|
return utils.parse(dateWithoutSeparatorStr, formatWithoutSeparator);
|
|
410
416
|
};
|
|
411
|
-
export const createDateStrForInputFromSections = sections => {
|
|
412
|
-
const
|
|
417
|
+
export const createDateStrForInputFromSections = (sections, isRTL) => {
|
|
418
|
+
const formattedSections = sections.map(section => `${section.startSeparator}${getSectionVisibleValue(section, isRTL ? 'input-rtl' : 'input-ltr')}${section.endSeparator}`);
|
|
419
|
+
const dateStr = formattedSections.join('');
|
|
420
|
+
if (!isRTL) {
|
|
421
|
+
return dateStr;
|
|
422
|
+
}
|
|
413
423
|
|
|
414
424
|
// \u2066: start left-to-right isolation
|
|
415
425
|
// \u2067: start right-to-left isolation
|
|
416
426
|
// \u2068: start first strong character isolation
|
|
417
427
|
// \u2069: pop isolation
|
|
418
428
|
// wrap into an isolated group such that separators can split the string in smaller ones by adding \u2069\u2068
|
|
419
|
-
return `\u2066${
|
|
429
|
+
return `\u2066${dateStr}\u2069`;
|
|
420
430
|
};
|
|
421
431
|
export const getSectionsBoundaries = utils => {
|
|
422
432
|
const today = utils.date();
|
|
@@ -583,7 +593,15 @@ export const mergeDateIntoReferenceDate = (utils, dateToTransferFrom, sections,
|
|
|
583
593
|
return mergedDate;
|
|
584
594
|
}, referenceDate);
|
|
585
595
|
export const isAndroid = () => navigator.userAgent.toLowerCase().indexOf('android') > -1;
|
|
586
|
-
export const
|
|
596
|
+
export const clampDaySectionIfPossible = (utils, sections, sectionsValueBoundaries) => {
|
|
597
|
+
// We can only clamp the day value if:
|
|
598
|
+
// 1. if all the sections are filled (except the week day section which can be empty)
|
|
599
|
+
// 2. there is a day section
|
|
600
|
+
const canClamp = sections.every(section => section.type === 'weekDay' || section.value !== '') && sections.some(section => section.type === 'day');
|
|
601
|
+
if (!canClamp) {
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
|
|
587
605
|
// We try to generate a valid date representing the start of the month of the invalid date typed by the user.
|
|
588
606
|
const sectionsForStartOfMonth = sections.map(section => {
|
|
589
607
|
if (section.type !== 'day') {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FieldSection } from '../../../models';
|
|
2
|
+
import { FieldSectionsValueBoundaries } from './useField.types';
|
|
2
3
|
import { UpdateSectionValueParams } from './useFieldState';
|
|
3
4
|
interface ApplyCharacterEditingParams {
|
|
4
5
|
keyPressed: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UseFieldForwardedProps, UseFieldInternalProps, UseFieldParams, UseFieldState, FieldSelectedSectionsIndexes } from './useField.types';
|
|
2
|
+
import { FieldSection, FieldSelectedSections } from '../../../models';
|
|
2
3
|
export interface UpdateSectionValueParams<TSection extends FieldSection> {
|
|
3
4
|
/**
|
|
4
5
|
* The section on which we want to apply the new value.
|
|
@@ -23,4 +24,5 @@ export declare const useFieldState: <TValue, TDate, TSection extends FieldSectio
|
|
|
23
24
|
updateValueFromValueStr: (valueStr: string) => void;
|
|
24
25
|
setTempAndroidValueStr: (tempValueStrAndroid: string | null) => void;
|
|
25
26
|
sectionsValueBoundaries: import("./useField.types").FieldSectionsValueBoundaries<TDate>;
|
|
27
|
+
placeholder: string;
|
|
26
28
|
};
|