@mui/x-date-pickers 6.3.0 → 6.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -2
- package/DateField/DateField.js +4 -0
- package/DateTimeField/DateTimeField.js +4 -0
- package/DateTimeField/DateTimeField.types.d.ts +2 -10
- package/DateTimePicker/shared.d.ts +5 -12
- package/DesktopTimePicker/DesktopTimePicker.js +4 -2
- package/TimeClock/TimeClock.types.d.ts +2 -1
- package/TimeField/TimeField.js +4 -0
- package/index.js +1 -1
- package/internals/hooks/useField/useField.utils.d.ts +1 -1
- package/internals/hooks/useField/useField.utils.js +2 -2
- package/internals/hooks/useField/useFieldState.js +2 -2
- package/internals/hooks/usePicker/usePickerViews.d.ts +2 -2
- package/internals/index.d.ts +1 -1
- package/internals/models/props/clock.d.ts +1 -1
- package/internals/models/validation.d.ts +13 -0
- package/internals/utils/validation/extractValidationProps.d.ts +1 -1
- package/internals/utils/validation/extractValidationProps.js +1 -1
- package/legacy/DateField/DateField.js +4 -0
- package/legacy/DateTimeField/DateTimeField.js +4 -0
- package/legacy/DesktopTimePicker/DesktopTimePicker.js +4 -2
- package/legacy/TimeField/TimeField.js +4 -0
- package/legacy/index.js +1 -1
- package/legacy/internals/hooks/useField/useField.utils.js +2 -2
- package/legacy/internals/hooks/useField/useFieldState.js +2 -2
- package/legacy/internals/utils/validation/extractValidationProps.js +1 -1
- package/legacy/tests/describeValidation/testTextFieldValidation.js +26 -0
- package/modern/DateField/DateField.js +4 -0
- package/modern/DateTimeField/DateTimeField.js +4 -0
- package/modern/DesktopTimePicker/DesktopTimePicker.js +3 -1
- package/modern/TimeField/TimeField.js +4 -0
- package/modern/index.js +1 -1
- package/modern/internals/hooks/useField/useField.utils.js +2 -2
- package/modern/internals/hooks/useField/useFieldState.js +2 -2
- package/modern/internals/utils/validation/extractValidationProps.js +1 -1
- package/modern/tests/describeValidation/testTextFieldValidation.js +27 -0
- package/node/DateField/DateField.js +4 -0
- package/node/DateTimeField/DateTimeField.js +4 -0
- package/node/DesktopTimePicker/DesktopTimePicker.js +3 -1
- package/node/TimeField/TimeField.js +4 -0
- package/node/index.js +1 -1
- package/node/internals/hooks/useField/useField.utils.js +2 -2
- package/node/internals/hooks/useField/useFieldState.js +2 -2
- package/node/internals/utils/validation/extractValidationProps.js +1 -1
- package/node/tests/describeValidation/testTextFieldValidation.js +27 -0
- package/package.json +2 -2
- package/tests/describeValidation/testTextFieldValidation.js +27 -0
- package/timeViewRenderers/timeViewRenderers.d.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,52 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## 6.3.1
|
|
7
|
+
|
|
8
|
+
_May 5, 2023_
|
|
9
|
+
|
|
10
|
+
We'd like to offer a big thanks to the 7 contributors who made this release possible. Here are some highlights ✨:
|
|
11
|
+
|
|
12
|
+
- 🐞 Bugfixes
|
|
13
|
+
- 📚 Documentation improvements
|
|
14
|
+
|
|
15
|
+
### `@mui/x-data-grid@v6.3.1` / `@mui/x-data-grid-pro@v6.3.1` / `@mui/x-data-grid-premium@v6.3.1`
|
|
16
|
+
|
|
17
|
+
#### Changes
|
|
18
|
+
|
|
19
|
+
- [DataGrid] Fix broken filtering in the value formatter demo (#8621) @cherniavskii
|
|
20
|
+
- [DataGrid] Fix falsy filter values not showing in filter button tooltip (#8550) @ithrforu
|
|
21
|
+
- [DataGrid] Fix missing watermark in Pro and Premium packages (#8797) @cherniavskii
|
|
22
|
+
- [DataGrid] Remove unwarranted warning log (#8847) @romgrk
|
|
23
|
+
- [DataGrid] Add Joy UI slots (`Select`, `SelectOption`, `InputLabel`, `FormControl`) (#8747) @cherniavskii
|
|
24
|
+
- [DataGridPremium] Fix expanded groups being collapsed after calling `updateRows` (#8823) @cherniavskii
|
|
25
|
+
|
|
26
|
+
### `@mui/x-date-pickers@v6.3.1` / `@mui/x-date-pickers-pro@v6.3.1`
|
|
27
|
+
|
|
28
|
+
#### Changes
|
|
29
|
+
|
|
30
|
+
- [pickers] Fix `minutesStep` validation prop behavior (#8794) @LukasTy
|
|
31
|
+
- [pickers] Fix time picker `viewRenderers` overriding (#8830) @LukasTy
|
|
32
|
+
- [pickers] Remove last additional character when using LTR (#8848) @alexfauquette
|
|
33
|
+
|
|
34
|
+
### Docs
|
|
35
|
+
|
|
36
|
+
- [docs] Fix controlled mode demo on Editing page (#8800) @yaredtsy
|
|
37
|
+
- [docs] Fix scrolling demo not working with React 18 (#6489) @cherniavskii
|
|
38
|
+
- [docs] Update demo to support agregation on popular feature cell (#8617) @BalaM314
|
|
39
|
+
- [docs] Clarify what `<path>` is (#8764) @alexfauquette
|
|
40
|
+
|
|
41
|
+
### Core
|
|
42
|
+
|
|
43
|
+
- [core] Do not include playground pages in `yarn typescript` script (#8822) @cherniavskii
|
|
44
|
+
- [core] Limit `typescript:ci` step memory limit (#8796) @LukasTy
|
|
45
|
+
- [core] Upgrade monorepo (#8835) @cherniavskii
|
|
46
|
+
- [test] Use `fake` clock on `MobileDateRangePicker` (#8861) @LukasTy
|
|
47
|
+
- [charts] Clean some styling (#8778) @alexfauquette
|
|
48
|
+
- [charts] Improve tooltip (#8792) @alexfauquette
|
|
49
|
+
- [charts] Improvement and docs on axis (#8654) @alexfauquette
|
|
50
|
+
- [charts] Defaultize attributes (#8788) @alexfauquette
|
|
51
|
+
|
|
6
52
|
## 6.3.0
|
|
7
53
|
|
|
8
54
|
_Apr 28, 2023_
|
|
@@ -264,9 +310,9 @@ We'd like to offer a big thanks to the 9 contributors who made this release poss
|
|
|
264
310
|
|
|
265
311
|
- [fields] Add missing tokens to `AdapterDateFnsJalali` (#8402) @flaviendelangle
|
|
266
312
|
- [fields] Clean the active date manager (#8370) @flaviendelangle
|
|
267
|
-
- [fields] Cleanup `useFieldState`
|
|
313
|
+
- [fields] Cleanup `useFieldState` (#8292) @flaviendelangle
|
|
268
314
|
- [fields] Only add RTL characters when needed (#8325) @flaviendelangle
|
|
269
|
-
- [pickers] Add support for single input fields in range pickers
|
|
315
|
+
- [pickers] Add support for single input fields in range pickers (#7927) @flaviendelangle
|
|
270
316
|
- [pickers] Allows non token characters in format (#8256) @alexfauquette
|
|
271
317
|
- [pickers] Avoid root imports and move public models to the models folder (#8337) @flaviendelangle
|
|
272
318
|
- [pickers] Update `view` when `views` or `openTo` changes (#8361) @LukasTy
|
package/DateField/DateField.js
CHANGED
|
@@ -205,6 +205,10 @@ process.env.NODE_ENV !== "production" ? DateField.propTypes = {
|
|
|
205
205
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
206
206
|
*/
|
|
207
207
|
onChange: PropTypes.func,
|
|
208
|
+
/**
|
|
209
|
+
* @ignore
|
|
210
|
+
*/
|
|
211
|
+
onClick: PropTypes.func,
|
|
208
212
|
/**
|
|
209
213
|
* Callback fired when the error associated to the current value changes.
|
|
210
214
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
|
@@ -238,6 +238,10 @@ process.env.NODE_ENV !== "production" ? DateTimeField.propTypes = {
|
|
|
238
238
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
239
239
|
*/
|
|
240
240
|
onChange: PropTypes.func,
|
|
241
|
+
/**
|
|
242
|
+
* @ignore
|
|
243
|
+
*/
|
|
244
|
+
onClick: PropTypes.func,
|
|
241
245
|
/**
|
|
242
246
|
* Callback fired when the error associated to the current value changes.
|
|
243
247
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
|
@@ -4,27 +4,19 @@ import TextField from '@mui/material/TextField';
|
|
|
4
4
|
import { DateTimeValidationError, FieldSection } from '../models';
|
|
5
5
|
import { UseFieldInternalProps } from '../internals/hooks/useField';
|
|
6
6
|
import { DefaultizedProps, MakeOptional } from '../internals/models/helpers';
|
|
7
|
-
import { BaseDateValidationProps, BaseTimeValidationProps, DayValidationProps, MonthValidationProps, TimeValidationProps, YearValidationProps } from '../internals/models/validation';
|
|
7
|
+
import { BaseDateValidationProps, BaseTimeValidationProps, DateTimeValidationProps, DayValidationProps, MonthValidationProps, TimeValidationProps, YearValidationProps } from '../internals/models/validation';
|
|
8
8
|
import { FieldsTextFieldProps } from '../internals/models/fields';
|
|
9
9
|
import { UncapitalizeObjectKeys } from '../internals/utils/slots-migration';
|
|
10
10
|
export interface UseDateTimeFieldParams<TDate, TChildProps extends {}> {
|
|
11
11
|
props: UseDateTimeFieldComponentProps<TDate, TChildProps>;
|
|
12
12
|
inputRef?: React.Ref<HTMLInputElement>;
|
|
13
13
|
}
|
|
14
|
-
export interface UseDateTimeFieldProps<TDate> extends MakeOptional<UseFieldInternalProps<TDate | null, FieldSection, DateTimeValidationError>, 'format'>, DayValidationProps<TDate>, MonthValidationProps<TDate>, YearValidationProps<TDate>, BaseDateValidationProps<TDate>, TimeValidationProps<TDate>, BaseTimeValidationProps {
|
|
14
|
+
export interface UseDateTimeFieldProps<TDate> extends MakeOptional<UseFieldInternalProps<TDate | null, FieldSection, DateTimeValidationError>, 'format'>, DayValidationProps<TDate>, MonthValidationProps<TDate>, YearValidationProps<TDate>, BaseDateValidationProps<TDate>, TimeValidationProps<TDate>, BaseTimeValidationProps, DateTimeValidationProps<TDate> {
|
|
15
15
|
/**
|
|
16
16
|
* 12h/24h view for hour selection clock.
|
|
17
17
|
* @default `utils.is12HourCycleInCurrentLocale()`
|
|
18
18
|
*/
|
|
19
19
|
ampm?: boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Minimal selectable moment of time with binding to date, to set min time in each day use `minTime`.
|
|
22
|
-
*/
|
|
23
|
-
minDateTime?: TDate;
|
|
24
|
-
/**
|
|
25
|
-
* Maximal selectable moment of time with binding to date, to set max time in each day use `maxTime`.
|
|
26
|
-
*/
|
|
27
|
-
maxDateTime?: TDate;
|
|
28
20
|
}
|
|
29
21
|
export type UseDateTimeFieldDefaultizedProps<TDate> = DefaultizedProps<UseDateTimeFieldProps<TDate>, keyof BaseDateValidationProps<TDate> | keyof BaseTimeValidationProps | 'format'>;
|
|
30
22
|
export type UseDateTimeFieldComponentProps<TDate, TChildProps extends {}> = Omit<TChildProps, keyof UseDateTimeFieldProps<TDate>> & UseDateTimeFieldProps<TDate>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { DefaultizedProps } from '../internals/models/helpers';
|
|
3
|
-
import { DateOrTimeView, DateTimeValidationError
|
|
3
|
+
import { DateOrTimeView, DateTimeValidationError } from '../models';
|
|
4
4
|
import { DateCalendarSlotsComponent, DateCalendarSlotsComponentsProps, ExportedDateCalendarProps } from '../DateCalendar/DateCalendar.types';
|
|
5
5
|
import { TimeClockSlotsComponent, TimeClockSlotsComponentsProps } from '../TimeClock/TimeClock.types';
|
|
6
6
|
import { BasePickerInputProps } from '../internals/models/props/basePickerProps';
|
|
7
7
|
import { DateTimePickerTabsProps, ExportedDateTimePickerTabsProps } from './DateTimePickerTabs';
|
|
8
|
-
import { BaseDateValidationProps, BaseTimeValidationProps } from '../internals/models/validation';
|
|
8
|
+
import { BaseDateValidationProps, BaseTimeValidationProps, DateTimeValidationProps } from '../internals/models/validation';
|
|
9
9
|
import { LocalizedComponent } from '../locales/utils/pickersLocaleTextApi';
|
|
10
10
|
import { DateTimePickerToolbarProps, ExportedDateTimePickerToolbarProps } from './DateTimePickerToolbar';
|
|
11
11
|
import { PickerViewRendererLookup } from '../internals/hooks/usePicker/usePickerViews';
|
|
@@ -13,6 +13,7 @@ import { DateViewRendererProps } from '../dateViewRenderers';
|
|
|
13
13
|
import { TimeViewRendererProps } from '../timeViewRenderers';
|
|
14
14
|
import { UncapitalizeObjectKeys } from '../internals/utils/slots-migration';
|
|
15
15
|
import { BaseClockProps, ExportedBaseClockProps } from '../internals/models/props/clock';
|
|
16
|
+
import { TimeViewWithMeridiem } from '../internals/models';
|
|
16
17
|
export interface BaseDateTimePickerSlotsComponent<TDate> extends DateCalendarSlotsComponent<TDate>, TimeClockSlotsComponent {
|
|
17
18
|
/**
|
|
18
19
|
* Tabs enabling toggling between date and time pickers.
|
|
@@ -35,20 +36,12 @@ export interface BaseDateTimePickerSlotsComponentsProps<TDate> extends DateCalen
|
|
|
35
36
|
*/
|
|
36
37
|
toolbar?: ExportedDateTimePickerToolbarProps;
|
|
37
38
|
}
|
|
38
|
-
export interface BaseDateTimePickerProps<TDate> extends BasePickerInputProps<TDate | null, TDate, DateOrTimeView, DateTimeValidationError>, Omit<ExportedDateCalendarProps<TDate>, 'onViewChange'>, ExportedBaseClockProps<TDate> {
|
|
39
|
+
export interface BaseDateTimePickerProps<TDate> extends BasePickerInputProps<TDate | null, TDate, DateOrTimeView, DateTimeValidationError>, Omit<ExportedDateCalendarProps<TDate>, 'onViewChange'>, ExportedBaseClockProps<TDate>, DateTimeValidationProps<TDate> {
|
|
39
40
|
/**
|
|
40
41
|
* Display ampm controls under the clock (instead of in the toolbar).
|
|
41
42
|
* @default true on desktop, false on mobile
|
|
42
43
|
*/
|
|
43
44
|
ampmInClock?: boolean;
|
|
44
|
-
/**
|
|
45
|
-
* Minimal selectable moment of time with binding to date, to set min time in each day use `minTime`.
|
|
46
|
-
*/
|
|
47
|
-
minDateTime?: TDate;
|
|
48
|
-
/**
|
|
49
|
-
* Maximal selectable moment of time with binding to date, to set max time in each day use `maxTime`.
|
|
50
|
-
*/
|
|
51
|
-
maxDateTime?: TDate;
|
|
52
45
|
/**
|
|
53
46
|
* Overridable components.
|
|
54
47
|
* @default {}
|
|
@@ -76,7 +69,7 @@ export interface BaseDateTimePickerProps<TDate> extends BasePickerInputProps<TDa
|
|
|
76
69
|
* If `null`, the section will only have field editing.
|
|
77
70
|
* If `undefined`, internally defined view will be the used.
|
|
78
71
|
*/
|
|
79
|
-
viewRenderers?: Partial<PickerViewRendererLookup<TDate | null, DateOrTimeView, DateViewRendererProps<TDate, DateOrTimeView> & TimeViewRendererProps<
|
|
72
|
+
viewRenderers?: Partial<PickerViewRendererLookup<TDate | null, DateOrTimeView, DateViewRendererProps<TDate, DateOrTimeView> & TimeViewRendererProps<TimeViewWithMeridiem, BaseClockProps<TDate, TimeViewWithMeridiem>>, {}>>;
|
|
80
73
|
}
|
|
81
74
|
type UseDateTimePickerDefaultizedProps<TDate, Props extends BaseDateTimePickerProps<TDate>> = LocalizedComponent<TDate, DefaultizedProps<Props, 'views' | 'openTo' | 'orientation' | 'ampm' | keyof BaseDateValidationProps<TDate> | keyof BaseTimeValidationProps>>;
|
|
82
75
|
export declare function useDateTimePickerDefaultizedProps<TDate, Props extends BaseDateTimePickerProps<TDate>>(props: Props, name: string): Omit<UseDateTimePickerDefaultizedProps<TDate, Props>, 'components' | 'componentsProps'>;
|
|
@@ -11,7 +11,7 @@ import { useDesktopPicker } from '../internals/hooks/useDesktopPicker';
|
|
|
11
11
|
import { extractValidationProps } from '../internals/utils/validation/extractValidationProps';
|
|
12
12
|
import { renderDigitalClockTimeView, renderMultiSectionDigitalClockTimeView } from '../timeViewRenderers';
|
|
13
13
|
const DesktopTimePicker = /*#__PURE__*/React.forwardRef(function DesktopTimePicker(inProps, ref) {
|
|
14
|
-
var _defaultizedProps$thr, _defaultizedProps$amp, _defaultizedProps$slo2, _defaultizedProps$slo3;
|
|
14
|
+
var _defaultizedProps$thr, _defaultizedProps$amp, _viewRenderers$hours, _defaultizedProps$slo2, _defaultizedProps$slo3;
|
|
15
15
|
const localeText = useLocaleText();
|
|
16
16
|
|
|
17
17
|
// Props with the default values common to all time pickers
|
|
@@ -32,7 +32,9 @@ const DesktopTimePicker = /*#__PURE__*/React.forwardRef(function DesktopTimePick
|
|
|
32
32
|
}, defaultizedProps.viewRenderers);
|
|
33
33
|
const ampmInClock = (_defaultizedProps$amp = defaultizedProps.ampmInClock) != null ? _defaultizedProps$amp : true;
|
|
34
34
|
const actionBarActions = shouldRenderTimeInASingleColumn ? [] : ['accept'];
|
|
35
|
-
|
|
35
|
+
// Need to avoid adding the `meridiem` view when unexpected renderer is specified
|
|
36
|
+
const shouldHoursRendererContainMeridiemView = ((_viewRenderers$hours = viewRenderers.hours) == null ? void 0 : _viewRenderers$hours.name) === renderMultiSectionDigitalClockTimeView.name;
|
|
37
|
+
const views = defaultizedProps.ampm && shouldHoursRendererContainMeridiemView ? [...defaultizedProps.views, 'meridiem'] : defaultizedProps.views;
|
|
36
38
|
|
|
37
39
|
// Props with the default values specific to the desktop variant
|
|
38
40
|
const props = _extends({}, defaultizedProps, {
|
|
@@ -3,6 +3,7 @@ import { PickersArrowSwitcherSlotsComponent, PickersArrowSwitcherSlotsComponents
|
|
|
3
3
|
import { UncapitalizeObjectKeys } from '../internals/utils/slots-migration';
|
|
4
4
|
import { BaseClockProps, ExportedBaseClockProps } from '../internals/models/props/clock';
|
|
5
5
|
import { TimeView } from '../models';
|
|
6
|
+
import { TimeViewWithMeridiem } from '../internals/models';
|
|
6
7
|
export interface ExportedTimeClockProps<TDate> extends ExportedBaseClockProps<TDate> {
|
|
7
8
|
/**
|
|
8
9
|
* Display ampm controls under the clock (instead of in the toolbar).
|
|
@@ -14,7 +15,7 @@ export interface TimeClockSlotsComponent extends PickersArrowSwitcherSlotsCompon
|
|
|
14
15
|
}
|
|
15
16
|
export interface TimeClockSlotsComponentsProps extends PickersArrowSwitcherSlotsComponentsProps {
|
|
16
17
|
}
|
|
17
|
-
export interface TimeClockProps<TDate> extends ExportedTimeClockProps<TDate>, BaseClockProps<TDate,
|
|
18
|
+
export interface TimeClockProps<TDate, TView extends TimeViewWithMeridiem = TimeView> extends ExportedTimeClockProps<TDate>, BaseClockProps<TDate, TView> {
|
|
18
19
|
/**
|
|
19
20
|
* Override or extend the styles applied to the component.
|
|
20
21
|
*/
|
package/TimeField/TimeField.js
CHANGED
|
@@ -222,6 +222,10 @@ process.env.NODE_ENV !== "production" ? TimeField.propTypes = {
|
|
|
222
222
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
223
223
|
*/
|
|
224
224
|
onChange: PropTypes.func,
|
|
225
|
+
/**
|
|
226
|
+
* @ignore
|
|
227
|
+
*/
|
|
228
|
+
onClick: PropTypes.func,
|
|
225
229
|
/**
|
|
226
230
|
* Callback fired when the error associated to the current value changes.
|
|
227
231
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
package/index.js
CHANGED
|
@@ -14,7 +14,7 @@ export declare const cleanString: (dirtyString: string) => string;
|
|
|
14
14
|
export declare const addPositionPropertiesToSections: <TSection extends FieldSection>(sections: FieldSectionWithoutPosition<TSection>[], isRTL: boolean) => TSection[];
|
|
15
15
|
export declare const changeSectionValueFormat: <TDate>(utils: MuiPickersAdapter<TDate>, valueStr: string, currentFormat: string, newFormat: string) => string;
|
|
16
16
|
export declare const doesSectionFormatHaveLeadingZeros: <TDate>(utils: MuiPickersAdapter<TDate>, contentType: FieldSectionContentType, sectionType: FieldSectionType, format: string) => boolean;
|
|
17
|
-
export declare const splitFormatIntoSections: <TDate>(utils: MuiPickersAdapter<TDate>, localeText: PickersLocaleText<TDate>, format: string, date: TDate | null, formatDensity: 'dense' | 'spacious', shouldRespectLeadingZeros: boolean) => FieldSectionWithoutPosition[];
|
|
17
|
+
export declare const splitFormatIntoSections: <TDate>(utils: MuiPickersAdapter<TDate>, localeText: PickersLocaleText<TDate>, format: string, date: TDate | null, formatDensity: 'dense' | 'spacious', shouldRespectLeadingZeros: boolean, isRTL: boolean) => FieldSectionWithoutPosition[];
|
|
18
18
|
/**
|
|
19
19
|
* Some date libraries like `dayjs` don't support parsing from date with escaped characters.
|
|
20
20
|
* To make sure that the parsing works, we are building a format and a date without any separator.
|
|
@@ -312,7 +312,7 @@ const getEscapedPartsFromFormat = (utils, format) => {
|
|
|
312
312
|
}
|
|
313
313
|
return escapedParts;
|
|
314
314
|
};
|
|
315
|
-
export const splitFormatIntoSections = (utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros) => {
|
|
315
|
+
export const splitFormatIntoSections = (utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL) => {
|
|
316
316
|
let startSeparator = '';
|
|
317
317
|
const sections = [];
|
|
318
318
|
const now = utils.date();
|
|
@@ -400,7 +400,7 @@ export const splitFormatIntoSections = (utils, localeText, format, date, formatD
|
|
|
400
400
|
return sections.map(section => {
|
|
401
401
|
const cleanSeparator = separator => {
|
|
402
402
|
let cleanedSeparator = separator;
|
|
403
|
-
if (cleanedSeparator !== null && cleanedSeparator.includes(' ')) {
|
|
403
|
+
if (isRTL && cleanedSeparator !== null && cleanedSeparator.includes(' ')) {
|
|
404
404
|
cleanedSeparator = `\u2069${cleanedSeparator}\u2066`;
|
|
405
405
|
}
|
|
406
406
|
if (formatDensity === 'spacious' && ['/', '.', '-'].includes(cleanedSeparator)) {
|
|
@@ -31,7 +31,7 @@ export const useFieldState = params => {
|
|
|
31
31
|
const firstDefaultValue = React.useRef(defaultValue);
|
|
32
32
|
const valueFromTheOutside = (_ref = valueProp != null ? valueProp : firstDefaultValue.current) != null ? _ref : valueManager.emptyValue;
|
|
33
33
|
const sectionsValueBoundaries = React.useMemo(() => getSectionsBoundaries(utils), [utils]);
|
|
34
|
-
const getSectionsFromValue = React.useCallback((value, fallbackSections = null) => fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, isRTL, date => splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros)), [fieldValueManager, format, localeText, isRTL, shouldRespectLeadingZeros, utils, formatDensity]);
|
|
34
|
+
const getSectionsFromValue = React.useCallback((value, fallbackSections = null) => fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, isRTL, date => splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL)), [fieldValueManager, format, localeText, isRTL, shouldRespectLeadingZeros, utils, formatDensity]);
|
|
35
35
|
const placeholder = React.useMemo(() => fieldValueManager.getValueStrFromSections(getSectionsFromValue(valueManager.emptyValue), isRTL), [fieldValueManager, getSectionsFromValue, valueManager.emptyValue, isRTL]);
|
|
36
36
|
const [state, setState] = React.useState(() => {
|
|
37
37
|
const sections = getSectionsFromValue(valueFromTheOutside);
|
|
@@ -155,7 +155,7 @@ export const useFieldState = params => {
|
|
|
155
155
|
if (date == null || !utils.isValid(date)) {
|
|
156
156
|
return null;
|
|
157
157
|
}
|
|
158
|
-
const sections = splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros);
|
|
158
|
+
const sections = splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL);
|
|
159
159
|
return mergeDateIntoReferenceDate(utils, date, sections, referenceDate, false);
|
|
160
160
|
};
|
|
161
161
|
const newValue = fieldValueManager.parseValueStr(valueStr, state.referenceValue, parseDateStr);
|
|
@@ -13,8 +13,8 @@ export type PickerViewsRendererProps<TValue, TView extends DateOrTimeViewWithMer
|
|
|
13
13
|
onFocusedViewChange: (viewToFocus: TView, hasFocus: boolean) => void;
|
|
14
14
|
};
|
|
15
15
|
type PickerViewRenderer<TValue, TView extends DateOrTimeViewWithMeridiem, TExternalProps extends PickerViewsRendererBaseExternalProps<TView>, TAdditionalProps extends {}> = (props: PickerViewsRendererProps<TValue, TView, TExternalProps, TAdditionalProps>) => React.ReactNode;
|
|
16
|
-
export type PickerViewRendererLookup<TValue, TView extends DateOrTimeViewWithMeridiem, TExternalProps extends PickerViewsRendererBaseExternalProps<
|
|
17
|
-
[K in TView]: PickerViewRenderer<TValue,
|
|
16
|
+
export type PickerViewRendererLookup<TValue, TView extends DateOrTimeViewWithMeridiem, TExternalProps extends PickerViewsRendererBaseExternalProps<any>, TAdditionalProps extends {}> = {
|
|
17
|
+
[K in TView]: PickerViewRenderer<TValue, K, TExternalProps, TAdditionalProps> | null;
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
20
|
* Props used to handle the views that are common to all pickers.
|
package/internals/index.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export type { BasePickerProps, BasePickerInputProps, BaseNonStaticPickerProps, }
|
|
|
41
41
|
export type { BaseToolbarProps, ExportedBaseToolbarProps } from './models/props/toolbar';
|
|
42
42
|
export type { DefaultizedProps, MakeOptional } from './models/helpers';
|
|
43
43
|
export type { WrapperVariant } from './models/common';
|
|
44
|
-
export type { BaseDateValidationProps, BaseTimeValidationProps, TimeValidationProps, MonthValidationProps, YearValidationProps, DayValidationProps, } from './models/validation';
|
|
44
|
+
export type { BaseDateValidationProps, BaseTimeValidationProps, TimeValidationProps, MonthValidationProps, YearValidationProps, DayValidationProps, DateTimeValidationProps, } from './models/validation';
|
|
45
45
|
export { applyDefaultDate, replaceInvalidDateByNull, areDatesEqual } from './utils/date-utils';
|
|
46
46
|
export { executeInTheNextEventLoopTick, getActiveElement, onSpaceOrEnter, DEFAULT_DESKTOP_MODE_MEDIA_QUERY, } from './utils/utils';
|
|
47
47
|
export { defaultReduceAnimations } from './utils/defaultReduceAnimations';
|
|
@@ -48,7 +48,7 @@ export interface BaseClockProps<TDate, TView extends TimeViewWithMeridiem> exten
|
|
|
48
48
|
*/
|
|
49
49
|
readOnly?: boolean;
|
|
50
50
|
}
|
|
51
|
-
export interface DesktopOnlyTimePickerProps<TDate> extends Omit<ExportedDigitalClockProps<TDate>, 'timeStep'>, Omit<ExportedMultiSectionDigitalClockProps<TDate>, '
|
|
51
|
+
export interface DesktopOnlyTimePickerProps<TDate> extends Omit<ExportedDigitalClockProps<TDate>, 'timeStep'>, Omit<ExportedMultiSectionDigitalClockProps<TDate>, 'timeSteps'> {
|
|
52
52
|
/**
|
|
53
53
|
* Amount of time options below or at which the single column time renderer is used.
|
|
54
54
|
* @default 24
|
|
@@ -108,4 +108,17 @@ export interface YearValidationProps<TDate> {
|
|
|
108
108
|
*/
|
|
109
109
|
shouldDisableYear?: (year: TDate) => boolean;
|
|
110
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Props used to validate a date time value.
|
|
113
|
+
*/
|
|
114
|
+
export interface DateTimeValidationProps<TDate> {
|
|
115
|
+
/**
|
|
116
|
+
* Minimal selectable moment of time with binding to date, to set min time in each day use `minTime`.
|
|
117
|
+
*/
|
|
118
|
+
minDateTime?: TDate;
|
|
119
|
+
/**
|
|
120
|
+
* Maximal selectable moment of time with binding to date, to set max time in each day use `maxTime`.
|
|
121
|
+
*/
|
|
122
|
+
maxDateTime?: TDate;
|
|
123
|
+
}
|
|
111
124
|
export {};
|
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare const extractValidationProps: <Props extends {
|
|
6
6
|
[key: string]: any;
|
|
7
|
-
}>(props: Props) => Pick<Props, "disableFuture" | "disablePast" | "shouldDisableDate" | "shouldDisableMonth" | "shouldDisableYear" | "minDate" | "maxDate" | "minTime" | "maxTime" | "shouldDisableTime" | "shouldDisableClock" | "
|
|
7
|
+
}>(props: Props) => Pick<Props, "disableFuture" | "disablePast" | "shouldDisableDate" | "shouldDisableMonth" | "shouldDisableYear" | "minDate" | "maxDate" | "minutesStep" | "minTime" | "maxTime" | "shouldDisableTime" | "shouldDisableClock" | "disableIgnoringDatePartForTimeValidation" | "minDateTime" | "maxDateTime">;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const VALIDATION_PROP_NAMES = ['disablePast', 'disableFuture', 'minDate', 'maxDate', 'minTime', 'maxTime', 'minDateTime', 'maxDateTime', 'shouldDisableDate', 'shouldDisableMonth', 'shouldDisableYear', 'shouldDisableClock', 'shouldDisableTime', '
|
|
1
|
+
const VALIDATION_PROP_NAMES = ['disablePast', 'disableFuture', 'minDate', 'maxDate', 'minTime', 'maxTime', 'minDateTime', 'maxDateTime', 'shouldDisableDate', 'shouldDisableMonth', 'shouldDisableYear', 'shouldDisableClock', 'shouldDisableTime', 'minutesStep'];
|
|
2
2
|
/**
|
|
3
3
|
* Extract the validation props for the props received by a component.
|
|
4
4
|
* Limit the risk of forgetting some of them and reduce the bundle size.
|
|
@@ -199,6 +199,10 @@ process.env.NODE_ENV !== "production" ? DateField.propTypes = {
|
|
|
199
199
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
200
200
|
*/
|
|
201
201
|
onChange: PropTypes.func,
|
|
202
|
+
/**
|
|
203
|
+
* @ignore
|
|
204
|
+
*/
|
|
205
|
+
onClick: PropTypes.func,
|
|
202
206
|
/**
|
|
203
207
|
* Callback fired when the error associated to the current value changes.
|
|
204
208
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
|
@@ -232,6 +232,10 @@ process.env.NODE_ENV !== "production" ? DateTimeField.propTypes = {
|
|
|
232
232
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
233
233
|
*/
|
|
234
234
|
onChange: PropTypes.func,
|
|
235
|
+
/**
|
|
236
|
+
* @ignore
|
|
237
|
+
*/
|
|
238
|
+
onClick: PropTypes.func,
|
|
235
239
|
/**
|
|
236
240
|
* Callback fired when the error associated to the current value changes.
|
|
237
241
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
|
@@ -12,7 +12,7 @@ import { useDesktopPicker } from '../internals/hooks/useDesktopPicker';
|
|
|
12
12
|
import { extractValidationProps } from '../internals/utils/validation/extractValidationProps';
|
|
13
13
|
import { renderDigitalClockTimeView, renderMultiSectionDigitalClockTimeView } from '../timeViewRenderers';
|
|
14
14
|
var DesktopTimePicker = /*#__PURE__*/React.forwardRef(function DesktopTimePicker(inProps, ref) {
|
|
15
|
-
var _defaultizedProps$thr, _defaultizedProps$amp, _defaultizedProps$slo2, _defaultizedProps$slo3;
|
|
15
|
+
var _defaultizedProps$thr, _defaultizedProps$amp, _viewRenderers$hours, _defaultizedProps$slo2, _defaultizedProps$slo3;
|
|
16
16
|
var localeText = useLocaleText();
|
|
17
17
|
|
|
18
18
|
// Props with the default values common to all time pickers
|
|
@@ -33,7 +33,9 @@ var DesktopTimePicker = /*#__PURE__*/React.forwardRef(function DesktopTimePicker
|
|
|
33
33
|
}, defaultizedProps.viewRenderers);
|
|
34
34
|
var ampmInClock = (_defaultizedProps$amp = defaultizedProps.ampmInClock) != null ? _defaultizedProps$amp : true;
|
|
35
35
|
var actionBarActions = shouldRenderTimeInASingleColumn ? [] : ['accept'];
|
|
36
|
-
|
|
36
|
+
// Need to avoid adding the `meridiem` view when unexpected renderer is specified
|
|
37
|
+
var shouldHoursRendererContainMeridiemView = ((_viewRenderers$hours = viewRenderers.hours) == null ? void 0 : _viewRenderers$hours.name) === renderMultiSectionDigitalClockTimeView.name;
|
|
38
|
+
var views = defaultizedProps.ampm && shouldHoursRendererContainMeridiemView ? [].concat(_toConsumableArray(defaultizedProps.views), ['meridiem']) : defaultizedProps.views;
|
|
37
39
|
|
|
38
40
|
// Props with the default values specific to the desktop variant
|
|
39
41
|
var props = _extends({}, defaultizedProps, {
|
|
@@ -216,6 +216,10 @@ process.env.NODE_ENV !== "production" ? TimeField.propTypes = {
|
|
|
216
216
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
217
217
|
*/
|
|
218
218
|
onChange: PropTypes.func,
|
|
219
|
+
/**
|
|
220
|
+
* @ignore
|
|
221
|
+
*/
|
|
222
|
+
onClick: PropTypes.func,
|
|
219
223
|
/**
|
|
220
224
|
* Callback fired when the error associated to the current value changes.
|
|
221
225
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
package/legacy/index.js
CHANGED
|
@@ -323,7 +323,7 @@ var getEscapedPartsFromFormat = function getEscapedPartsFromFormat(utils, format
|
|
|
323
323
|
}
|
|
324
324
|
return escapedParts;
|
|
325
325
|
};
|
|
326
|
-
export var splitFormatIntoSections = function splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros) {
|
|
326
|
+
export var splitFormatIntoSections = function splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL) {
|
|
327
327
|
var startSeparator = '';
|
|
328
328
|
var sections = [];
|
|
329
329
|
var now = utils.date();
|
|
@@ -416,7 +416,7 @@ export var splitFormatIntoSections = function splitFormatIntoSections(utils, loc
|
|
|
416
416
|
return sections.map(function (section) {
|
|
417
417
|
var cleanSeparator = function cleanSeparator(separator) {
|
|
418
418
|
var cleanedSeparator = separator;
|
|
419
|
-
if (cleanedSeparator !== null && cleanedSeparator.includes(' ')) {
|
|
419
|
+
if (isRTL && cleanedSeparator !== null && cleanedSeparator.includes(' ')) {
|
|
420
420
|
cleanedSeparator = "\u2069".concat(cleanedSeparator, "\u2066");
|
|
421
421
|
}
|
|
422
422
|
if (formatDensity === 'spacious' && ['/', '.', '-'].includes(cleanedSeparator)) {
|
|
@@ -37,7 +37,7 @@ export var useFieldState = function useFieldState(params) {
|
|
|
37
37
|
var getSectionsFromValue = React.useCallback(function (value) {
|
|
38
38
|
var fallbackSections = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
39
39
|
return fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, isRTL, function (date) {
|
|
40
|
-
return splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros);
|
|
40
|
+
return splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL);
|
|
41
41
|
});
|
|
42
42
|
}, [fieldValueManager, format, localeText, isRTL, shouldRespectLeadingZeros, utils, formatDensity]);
|
|
43
43
|
var placeholder = React.useMemo(function () {
|
|
@@ -180,7 +180,7 @@ export var useFieldState = function useFieldState(params) {
|
|
|
180
180
|
if (date == null || !utils.isValid(date)) {
|
|
181
181
|
return null;
|
|
182
182
|
}
|
|
183
|
-
var sections = splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros);
|
|
183
|
+
var sections = splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL);
|
|
184
184
|
return mergeDateIntoReferenceDate(utils, date, sections, referenceDate, false);
|
|
185
185
|
};
|
|
186
186
|
var newValue = fieldValueManager.parseValueStr(valueStr, state.referenceValue, parseDateStr);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var VALIDATION_PROP_NAMES = ['disablePast', 'disableFuture', 'minDate', 'maxDate', 'minTime', 'maxTime', 'minDateTime', 'maxDateTime', 'shouldDisableDate', 'shouldDisableMonth', 'shouldDisableYear', 'shouldDisableClock', 'shouldDisableTime', '
|
|
1
|
+
var VALIDATION_PROP_NAMES = ['disablePast', 'disableFuture', 'minDate', 'maxDate', 'minTime', 'maxTime', 'minDateTime', 'maxDateTime', 'shouldDisableDate', 'shouldDisableMonth', 'shouldDisableYear', 'shouldDisableClock', 'shouldDisableTime', 'minutesStep'];
|
|
2
2
|
/**
|
|
3
3
|
* Extract the validation props for the props received by a component.
|
|
4
4
|
* Limit the risk of forgetting some of them and reduce the bundle size.
|
|
@@ -433,5 +433,31 @@ export var testTextFieldValidation = function testTextFieldValidation(ElementToT
|
|
|
433
433
|
expect(onErrorMock.lastCall.args[0]).to.equal(null);
|
|
434
434
|
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
435
435
|
});
|
|
436
|
+
it('should apply minutesStep', function test() {
|
|
437
|
+
if (['picker', 'field'].includes(componentFamily) && !withTime) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
var onErrorMock = spy();
|
|
441
|
+
var _render14 = render( /*#__PURE__*/_jsx(ElementToTest, {
|
|
442
|
+
onError: onErrorMock,
|
|
443
|
+
value: adapterToUse.date(new Date(2019, 5, 15, 10, 15)),
|
|
444
|
+
minutesStep: 30
|
|
445
|
+
})),
|
|
446
|
+
setProps = _render14.setProps;
|
|
447
|
+
if (withTime) {
|
|
448
|
+
expect(onErrorMock.callCount).to.equal(1);
|
|
449
|
+
expect(onErrorMock.lastCall.args[0]).to.equal('minutesStep');
|
|
450
|
+
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'true');
|
|
451
|
+
setProps({
|
|
452
|
+
value: adapterToUse.date(new Date(2019, 5, 15, 10, 30))
|
|
453
|
+
});
|
|
454
|
+
expect(onErrorMock.callCount).to.equal(2);
|
|
455
|
+
expect(onErrorMock.lastCall.args[0]).to.equal(null);
|
|
456
|
+
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
457
|
+
} else {
|
|
458
|
+
expect(onErrorMock.callCount).to.equal(0);
|
|
459
|
+
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
460
|
+
}
|
|
461
|
+
});
|
|
436
462
|
});
|
|
437
463
|
};
|
|
@@ -204,6 +204,10 @@ process.env.NODE_ENV !== "production" ? DateField.propTypes = {
|
|
|
204
204
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
205
205
|
*/
|
|
206
206
|
onChange: PropTypes.func,
|
|
207
|
+
/**
|
|
208
|
+
* @ignore
|
|
209
|
+
*/
|
|
210
|
+
onClick: PropTypes.func,
|
|
207
211
|
/**
|
|
208
212
|
* Callback fired when the error associated to the current value changes.
|
|
209
213
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
|
@@ -237,6 +237,10 @@ process.env.NODE_ENV !== "production" ? DateTimeField.propTypes = {
|
|
|
237
237
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
238
238
|
*/
|
|
239
239
|
onChange: PropTypes.func,
|
|
240
|
+
/**
|
|
241
|
+
* @ignore
|
|
242
|
+
*/
|
|
243
|
+
onClick: PropTypes.func,
|
|
240
244
|
/**
|
|
241
245
|
* Callback fired when the error associated to the current value changes.
|
|
242
246
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
|
@@ -31,7 +31,9 @@ const DesktopTimePicker = /*#__PURE__*/React.forwardRef(function DesktopTimePick
|
|
|
31
31
|
}, defaultizedProps.viewRenderers);
|
|
32
32
|
const ampmInClock = defaultizedProps.ampmInClock ?? true;
|
|
33
33
|
const actionBarActions = shouldRenderTimeInASingleColumn ? [] : ['accept'];
|
|
34
|
-
|
|
34
|
+
// Need to avoid adding the `meridiem` view when unexpected renderer is specified
|
|
35
|
+
const shouldHoursRendererContainMeridiemView = viewRenderers.hours?.name === renderMultiSectionDigitalClockTimeView.name;
|
|
36
|
+
const views = defaultizedProps.ampm && shouldHoursRendererContainMeridiemView ? [...defaultizedProps.views, 'meridiem'] : defaultizedProps.views;
|
|
35
37
|
|
|
36
38
|
// Props with the default values specific to the desktop variant
|
|
37
39
|
const props = _extends({}, defaultizedProps, {
|
|
@@ -221,6 +221,10 @@ process.env.NODE_ENV !== "production" ? TimeField.propTypes = {
|
|
|
221
221
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
222
222
|
*/
|
|
223
223
|
onChange: PropTypes.func,
|
|
224
|
+
/**
|
|
225
|
+
* @ignore
|
|
226
|
+
*/
|
|
227
|
+
onClick: PropTypes.func,
|
|
224
228
|
/**
|
|
225
229
|
* Callback fired when the error associated to the current value changes.
|
|
226
230
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
package/modern/index.js
CHANGED
|
@@ -312,7 +312,7 @@ const getEscapedPartsFromFormat = (utils, format) => {
|
|
|
312
312
|
}
|
|
313
313
|
return escapedParts;
|
|
314
314
|
};
|
|
315
|
-
export const splitFormatIntoSections = (utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros) => {
|
|
315
|
+
export const splitFormatIntoSections = (utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL) => {
|
|
316
316
|
let startSeparator = '';
|
|
317
317
|
const sections = [];
|
|
318
318
|
const now = utils.date();
|
|
@@ -400,7 +400,7 @@ export const splitFormatIntoSections = (utils, localeText, format, date, formatD
|
|
|
400
400
|
return sections.map(section => {
|
|
401
401
|
const cleanSeparator = separator => {
|
|
402
402
|
let cleanedSeparator = separator;
|
|
403
|
-
if (cleanedSeparator !== null && cleanedSeparator.includes(' ')) {
|
|
403
|
+
if (isRTL && cleanedSeparator !== null && cleanedSeparator.includes(' ')) {
|
|
404
404
|
cleanedSeparator = `\u2069${cleanedSeparator}\u2066`;
|
|
405
405
|
}
|
|
406
406
|
if (formatDensity === 'spacious' && ['/', '.', '-'].includes(cleanedSeparator)) {
|
|
@@ -30,7 +30,7 @@ export const useFieldState = params => {
|
|
|
30
30
|
const firstDefaultValue = React.useRef(defaultValue);
|
|
31
31
|
const valueFromTheOutside = valueProp ?? firstDefaultValue.current ?? valueManager.emptyValue;
|
|
32
32
|
const sectionsValueBoundaries = React.useMemo(() => getSectionsBoundaries(utils), [utils]);
|
|
33
|
-
const getSectionsFromValue = React.useCallback((value, fallbackSections = null) => fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, isRTL, date => splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros)), [fieldValueManager, format, localeText, isRTL, shouldRespectLeadingZeros, utils, formatDensity]);
|
|
33
|
+
const getSectionsFromValue = React.useCallback((value, fallbackSections = null) => fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, isRTL, date => splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL)), [fieldValueManager, format, localeText, isRTL, shouldRespectLeadingZeros, utils, formatDensity]);
|
|
34
34
|
const placeholder = React.useMemo(() => fieldValueManager.getValueStrFromSections(getSectionsFromValue(valueManager.emptyValue), isRTL), [fieldValueManager, getSectionsFromValue, valueManager.emptyValue, isRTL]);
|
|
35
35
|
const [state, setState] = React.useState(() => {
|
|
36
36
|
const sections = getSectionsFromValue(valueFromTheOutside);
|
|
@@ -154,7 +154,7 @@ export const useFieldState = params => {
|
|
|
154
154
|
if (date == null || !utils.isValid(date)) {
|
|
155
155
|
return null;
|
|
156
156
|
}
|
|
157
|
-
const sections = splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros);
|
|
157
|
+
const sections = splitFormatIntoSections(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL);
|
|
158
158
|
return mergeDateIntoReferenceDate(utils, date, sections, referenceDate, false);
|
|
159
159
|
};
|
|
160
160
|
const newValue = fieldValueManager.parseValueStr(valueStr, state.referenceValue, parseDateStr);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const VALIDATION_PROP_NAMES = ['disablePast', 'disableFuture', 'minDate', 'maxDate', 'minTime', 'maxTime', 'minDateTime', 'maxDateTime', 'shouldDisableDate', 'shouldDisableMonth', 'shouldDisableYear', 'shouldDisableClock', 'shouldDisableTime', '
|
|
1
|
+
const VALIDATION_PROP_NAMES = ['disablePast', 'disableFuture', 'minDate', 'maxDate', 'minTime', 'maxTime', 'minDateTime', 'maxDateTime', 'shouldDisableDate', 'shouldDisableMonth', 'shouldDisableYear', 'shouldDisableClock', 'shouldDisableTime', 'minutesStep'];
|
|
2
2
|
/**
|
|
3
3
|
* Extract the validation props for the props received by a component.
|
|
4
4
|
* Limit the risk of forgetting some of them and reduce the bundle size.
|
|
@@ -439,5 +439,32 @@ export const testTextFieldValidation = (ElementToTest, getOptions) => {
|
|
|
439
439
|
expect(onErrorMock.lastCall.args[0]).to.equal(null);
|
|
440
440
|
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
441
441
|
});
|
|
442
|
+
it('should apply minutesStep', function test() {
|
|
443
|
+
if (['picker', 'field'].includes(componentFamily) && !withTime) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const onErrorMock = spy();
|
|
447
|
+
const {
|
|
448
|
+
setProps
|
|
449
|
+
} = render( /*#__PURE__*/_jsx(ElementToTest, {
|
|
450
|
+
onError: onErrorMock,
|
|
451
|
+
value: adapterToUse.date(new Date(2019, 5, 15, 10, 15)),
|
|
452
|
+
minutesStep: 30
|
|
453
|
+
}));
|
|
454
|
+
if (withTime) {
|
|
455
|
+
expect(onErrorMock.callCount).to.equal(1);
|
|
456
|
+
expect(onErrorMock.lastCall.args[0]).to.equal('minutesStep');
|
|
457
|
+
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'true');
|
|
458
|
+
setProps({
|
|
459
|
+
value: adapterToUse.date(new Date(2019, 5, 15, 10, 30))
|
|
460
|
+
});
|
|
461
|
+
expect(onErrorMock.callCount).to.equal(2);
|
|
462
|
+
expect(onErrorMock.lastCall.args[0]).to.equal(null);
|
|
463
|
+
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
464
|
+
} else {
|
|
465
|
+
expect(onErrorMock.callCount).to.equal(0);
|
|
466
|
+
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
467
|
+
}
|
|
468
|
+
});
|
|
442
469
|
});
|
|
443
470
|
};
|
|
@@ -214,6 +214,10 @@ process.env.NODE_ENV !== "production" ? DateField.propTypes = {
|
|
|
214
214
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
215
215
|
*/
|
|
216
216
|
onChange: _propTypes.default.func,
|
|
217
|
+
/**
|
|
218
|
+
* @ignore
|
|
219
|
+
*/
|
|
220
|
+
onClick: _propTypes.default.func,
|
|
217
221
|
/**
|
|
218
222
|
* Callback fired when the error associated to the current value changes.
|
|
219
223
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
|
@@ -247,6 +247,10 @@ process.env.NODE_ENV !== "production" ? DateTimeField.propTypes = {
|
|
|
247
247
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
248
248
|
*/
|
|
249
249
|
onChange: _propTypes.default.func,
|
|
250
|
+
/**
|
|
251
|
+
* @ignore
|
|
252
|
+
*/
|
|
253
|
+
onClick: _propTypes.default.func,
|
|
250
254
|
/**
|
|
251
255
|
* Callback fired when the error associated to the current value changes.
|
|
252
256
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
|
@@ -40,7 +40,9 @@ const DesktopTimePicker = /*#__PURE__*/React.forwardRef(function DesktopTimePick
|
|
|
40
40
|
}, defaultizedProps.viewRenderers);
|
|
41
41
|
const ampmInClock = defaultizedProps.ampmInClock ?? true;
|
|
42
42
|
const actionBarActions = shouldRenderTimeInASingleColumn ? [] : ['accept'];
|
|
43
|
-
|
|
43
|
+
// Need to avoid adding the `meridiem` view when unexpected renderer is specified
|
|
44
|
+
const shouldHoursRendererContainMeridiemView = viewRenderers.hours?.name === _timeViewRenderers.renderMultiSectionDigitalClockTimeView.name;
|
|
45
|
+
const views = defaultizedProps.ampm && shouldHoursRendererContainMeridiemView ? [...defaultizedProps.views, 'meridiem'] : defaultizedProps.views;
|
|
44
46
|
|
|
45
47
|
// Props with the default values specific to the desktop variant
|
|
46
48
|
const props = (0, _extends2.default)({}, defaultizedProps, {
|
|
@@ -231,6 +231,10 @@ process.env.NODE_ENV !== "production" ? TimeField.propTypes = {
|
|
|
231
231
|
* @param {FieldChangeHandlerContext<TError>} context The context containing the validation result of the current value.
|
|
232
232
|
*/
|
|
233
233
|
onChange: _propTypes.default.func,
|
|
234
|
+
/**
|
|
235
|
+
* @ignore
|
|
236
|
+
*/
|
|
237
|
+
onClick: _propTypes.default.func,
|
|
234
238
|
/**
|
|
235
239
|
* Callback fired when the error associated to the current value changes.
|
|
236
240
|
* @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value.
|
package/node/index.js
CHANGED
|
@@ -330,7 +330,7 @@ const getEscapedPartsFromFormat = (utils, format) => {
|
|
|
330
330
|
}
|
|
331
331
|
return escapedParts;
|
|
332
332
|
};
|
|
333
|
-
const splitFormatIntoSections = (utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros) => {
|
|
333
|
+
const splitFormatIntoSections = (utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL) => {
|
|
334
334
|
let startSeparator = '';
|
|
335
335
|
const sections = [];
|
|
336
336
|
const now = utils.date();
|
|
@@ -418,7 +418,7 @@ const splitFormatIntoSections = (utils, localeText, format, date, formatDensity,
|
|
|
418
418
|
return sections.map(section => {
|
|
419
419
|
const cleanSeparator = separator => {
|
|
420
420
|
let cleanedSeparator = separator;
|
|
421
|
-
if (cleanedSeparator !== null && cleanedSeparator.includes(' ')) {
|
|
421
|
+
if (isRTL && cleanedSeparator !== null && cleanedSeparator.includes(' ')) {
|
|
422
422
|
cleanedSeparator = `\u2069${cleanedSeparator}\u2066`;
|
|
423
423
|
}
|
|
424
424
|
if (formatDensity === 'spacious' && ['/', '.', '-'].includes(cleanedSeparator)) {
|
|
@@ -39,7 +39,7 @@ const useFieldState = params => {
|
|
|
39
39
|
const firstDefaultValue = React.useRef(defaultValue);
|
|
40
40
|
const valueFromTheOutside = valueProp ?? firstDefaultValue.current ?? valueManager.emptyValue;
|
|
41
41
|
const sectionsValueBoundaries = React.useMemo(() => (0, _useField.getSectionsBoundaries)(utils), [utils]);
|
|
42
|
-
const getSectionsFromValue = React.useCallback((value, fallbackSections = null) => fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, isRTL, date => (0, _useField.splitFormatIntoSections)(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros)), [fieldValueManager, format, localeText, isRTL, shouldRespectLeadingZeros, utils, formatDensity]);
|
|
42
|
+
const getSectionsFromValue = React.useCallback((value, fallbackSections = null) => fieldValueManager.getSectionsFromValue(utils, value, fallbackSections, isRTL, date => (0, _useField.splitFormatIntoSections)(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL)), [fieldValueManager, format, localeText, isRTL, shouldRespectLeadingZeros, utils, formatDensity]);
|
|
43
43
|
const placeholder = React.useMemo(() => fieldValueManager.getValueStrFromSections(getSectionsFromValue(valueManager.emptyValue), isRTL), [fieldValueManager, getSectionsFromValue, valueManager.emptyValue, isRTL]);
|
|
44
44
|
const [state, setState] = React.useState(() => {
|
|
45
45
|
const sections = getSectionsFromValue(valueFromTheOutside);
|
|
@@ -163,7 +163,7 @@ const useFieldState = params => {
|
|
|
163
163
|
if (date == null || !utils.isValid(date)) {
|
|
164
164
|
return null;
|
|
165
165
|
}
|
|
166
|
-
const sections = (0, _useField.splitFormatIntoSections)(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros);
|
|
166
|
+
const sections = (0, _useField.splitFormatIntoSections)(utils, localeText, format, date, formatDensity, shouldRespectLeadingZeros, isRTL);
|
|
167
167
|
return (0, _useField.mergeDateIntoReferenceDate)(utils, date, sections, referenceDate, false);
|
|
168
168
|
};
|
|
169
169
|
const newValue = fieldValueManager.parseValueStr(valueStr, state.referenceValue, parseDateStr);
|
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.extractValidationProps = void 0;
|
|
7
|
-
const VALIDATION_PROP_NAMES = ['disablePast', 'disableFuture', 'minDate', 'maxDate', 'minTime', 'maxTime', 'minDateTime', 'maxDateTime', 'shouldDisableDate', 'shouldDisableMonth', 'shouldDisableYear', 'shouldDisableClock', 'shouldDisableTime', '
|
|
7
|
+
const VALIDATION_PROP_NAMES = ['disablePast', 'disableFuture', 'minDate', 'maxDate', 'minTime', 'maxTime', 'minDateTime', 'maxDateTime', 'shouldDisableDate', 'shouldDisableMonth', 'shouldDisableYear', 'shouldDisableClock', 'shouldDisableTime', 'minutesStep'];
|
|
8
8
|
/**
|
|
9
9
|
* Extract the validation props for the props received by a component.
|
|
10
10
|
* Limit the risk of forgetting some of them and reduce the bundle size.
|
|
@@ -448,6 +448,33 @@ const testTextFieldValidation = (ElementToTest, getOptions) => {
|
|
|
448
448
|
(0, _chai.expect)(onErrorMock.lastCall.args[0]).to.equal(null);
|
|
449
449
|
(0, _chai.expect)(_utils.screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
450
450
|
});
|
|
451
|
+
it('should apply minutesStep', function test() {
|
|
452
|
+
if (['picker', 'field'].includes(componentFamily) && !withTime) {
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
const onErrorMock = (0, _sinon.spy)();
|
|
456
|
+
const {
|
|
457
|
+
setProps
|
|
458
|
+
} = render( /*#__PURE__*/(0, _jsxRuntime.jsx)(ElementToTest, {
|
|
459
|
+
onError: onErrorMock,
|
|
460
|
+
value: _pickersUtils.adapterToUse.date(new Date(2019, 5, 15, 10, 15)),
|
|
461
|
+
minutesStep: 30
|
|
462
|
+
}));
|
|
463
|
+
if (withTime) {
|
|
464
|
+
(0, _chai.expect)(onErrorMock.callCount).to.equal(1);
|
|
465
|
+
(0, _chai.expect)(onErrorMock.lastCall.args[0]).to.equal('minutesStep');
|
|
466
|
+
(0, _chai.expect)(_utils.screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'true');
|
|
467
|
+
setProps({
|
|
468
|
+
value: _pickersUtils.adapterToUse.date(new Date(2019, 5, 15, 10, 30))
|
|
469
|
+
});
|
|
470
|
+
(0, _chai.expect)(onErrorMock.callCount).to.equal(2);
|
|
471
|
+
(0, _chai.expect)(onErrorMock.lastCall.args[0]).to.equal(null);
|
|
472
|
+
(0, _chai.expect)(_utils.screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
473
|
+
} else {
|
|
474
|
+
(0, _chai.expect)(onErrorMock.callCount).to.equal(0);
|
|
475
|
+
(0, _chai.expect)(_utils.screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
476
|
+
}
|
|
477
|
+
});
|
|
451
478
|
});
|
|
452
479
|
};
|
|
453
480
|
exports.testTextFieldValidation = testTextFieldValidation;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/x-date-pickers",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.1",
|
|
4
4
|
"description": "The community edition of the date picker components (MUI X).",
|
|
5
5
|
"author": "MUI Team",
|
|
6
6
|
"main": "./node/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@babel/runtime": "^7.21.0",
|
|
37
|
-
"@mui/utils": "^5.12.
|
|
37
|
+
"@mui/utils": "^5.12.3",
|
|
38
38
|
"@types/react-transition-group": "^4.4.5",
|
|
39
39
|
"clsx": "^1.2.1",
|
|
40
40
|
"prop-types": "^15.8.1",
|
|
@@ -439,5 +439,32 @@ export const testTextFieldValidation = (ElementToTest, getOptions) => {
|
|
|
439
439
|
expect(onErrorMock.lastCall.args[0]).to.equal(null);
|
|
440
440
|
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
441
441
|
});
|
|
442
|
+
it('should apply minutesStep', function test() {
|
|
443
|
+
if (['picker', 'field'].includes(componentFamily) && !withTime) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const onErrorMock = spy();
|
|
447
|
+
const {
|
|
448
|
+
setProps
|
|
449
|
+
} = render( /*#__PURE__*/_jsx(ElementToTest, {
|
|
450
|
+
onError: onErrorMock,
|
|
451
|
+
value: adapterToUse.date(new Date(2019, 5, 15, 10, 15)),
|
|
452
|
+
minutesStep: 30
|
|
453
|
+
}));
|
|
454
|
+
if (withTime) {
|
|
455
|
+
expect(onErrorMock.callCount).to.equal(1);
|
|
456
|
+
expect(onErrorMock.lastCall.args[0]).to.equal('minutesStep');
|
|
457
|
+
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'true');
|
|
458
|
+
setProps({
|
|
459
|
+
value: adapterToUse.date(new Date(2019, 5, 15, 10, 30))
|
|
460
|
+
});
|
|
461
|
+
expect(onErrorMock.callCount).to.equal(2);
|
|
462
|
+
expect(onErrorMock.lastCall.args[0]).to.equal(null);
|
|
463
|
+
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
464
|
+
} else {
|
|
465
|
+
expect(onErrorMock.callCount).to.equal(0);
|
|
466
|
+
expect(screen.getByRole('textbox')).to.have.attribute('aria-invalid', 'false');
|
|
467
|
+
}
|
|
468
|
+
});
|
|
442
469
|
});
|
|
443
470
|
};
|
|
@@ -11,6 +11,6 @@ export type TimeViewRendererProps<TView extends TimeViewWithMeridiem, TComponent
|
|
|
11
11
|
onViewChange?: (view: TView) => void;
|
|
12
12
|
views: readonly TView[];
|
|
13
13
|
};
|
|
14
|
-
export declare const renderTimeViewClock: <TDate extends unknown>({ view, onViewChange, focusedView, onFocusedViewChange, views, value, defaultValue, onChange, className, classes, disableFuture, disablePast, minTime, maxTime, shouldDisableTime, shouldDisableClock, minutesStep, ampm, ampmInClock, components, componentsProps, slots, slotProps, readOnly, disabled, sx, autoFocus, showViewSwitcher, disableIgnoringDatePartForTimeValidation, }: TimeViewRendererProps<
|
|
14
|
+
export declare const renderTimeViewClock: <TDate extends unknown>({ view, onViewChange, focusedView, onFocusedViewChange, views, value, defaultValue, onChange, className, classes, disableFuture, disablePast, minTime, maxTime, shouldDisableTime, shouldDisableClock, minutesStep, ampm, ampmInClock, components, componentsProps, slots, slotProps, readOnly, disabled, sx, autoFocus, showViewSwitcher, disableIgnoringDatePartForTimeValidation, }: TimeViewRendererProps<TimeViewWithMeridiem, TimeClockProps<TDate, TimeViewWithMeridiem>>) => JSX.Element;
|
|
15
15
|
export declare const renderDigitalClockTimeView: <TDate extends unknown>({ view, onViewChange, focusedView, onFocusedViewChange, views, value, defaultValue, onChange, className, classes, disableFuture, disablePast, minTime, maxTime, shouldDisableTime, shouldDisableClock, minutesStep, ampm, components, componentsProps, slots, slotProps, readOnly, disabled, sx, autoFocus, disableIgnoringDatePartForTimeValidation, timeSteps, skipDisabled, }: TimeViewRendererProps<"hours", Omit<DigitalClockProps<TDate>, "timeStep"> & Pick<TimePickerProps<TDate>, "timeSteps">>) => JSX.Element;
|
|
16
|
-
export declare const renderMultiSectionDigitalClockTimeView: <TDate extends unknown>({ view, onViewChange, focusedView, onFocusedViewChange, views, value, defaultValue, onChange, className, classes, disableFuture, disablePast, minTime, maxTime, shouldDisableTime, shouldDisableClock, minutesStep, ampm, components, componentsProps, slots, slotProps, readOnly, disabled, sx, autoFocus, disableIgnoringDatePartForTimeValidation, timeSteps, skipDisabled, }: TimeViewRendererProps<TimeViewWithMeridiem,
|
|
16
|
+
export declare const renderMultiSectionDigitalClockTimeView: <TDate extends unknown>({ view, onViewChange, focusedView, onFocusedViewChange, views, value, defaultValue, onChange, className, classes, disableFuture, disablePast, minTime, maxTime, shouldDisableTime, shouldDisableClock, minutesStep, ampm, components, componentsProps, slots, slotProps, readOnly, disabled, sx, autoFocus, disableIgnoringDatePartForTimeValidation, timeSteps, skipDisabled, }: TimeViewRendererProps<TimeViewWithMeridiem, MultiSectionDigitalClockProps<TDate>>) => JSX.Element;
|