@instructure/ui-date-time-input 8.23.1-snapshot.7 → 8.24.0
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 +11 -0
- package/es/DateTimeInput/index.js +52 -3
- package/es/DateTimeInput/props.js +6 -2
- package/lib/DateTimeInput/index.js +52 -3
- package/lib/DateTimeInput/props.js +6 -2
- package/package.json +19 -20
- package/src/DateTimeInput/README.md +80 -15
- package/src/DateTimeInput/index.tsx +47 -2
- package/src/DateTimeInput/props.ts +36 -3
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/DateTimeInput/index.d.ts +3 -0
- package/types/DateTimeInput/index.d.ts.map +1 -1
- package/types/DateTimeInput/props.d.ts +15 -1
- package/types/DateTimeInput/props.d.ts.map +1 -1
- package/LICENSE.md +0 -27
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
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
|
+
# [8.24.0](https://github.com/instructure/instructure-ui/compare/v8.23.0...v8.24.0) (2022-04-26)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **ui-date-time-input:** fix Date input to fill container in `DateTimeInput` ([4069706](https://github.com/instructure/instructure-ui/commit/40697060749bb4770120e822ef2b2466279b1497))
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- **ui-date-time-input:** allow to disable dates in the calendar.
|
|
15
|
+
- **ui-date-time-input:** add `rowSpacing` and `colSpacing` props to DateTimeInput ([5e829fa](https://github.com/instructure/instructure-ui/commit/5e829fae6b005f080497818df8b3fff19365aab3))
|
|
16
|
+
|
|
6
17
|
# [8.23.0](https://github.com/instructure/instructure-ui/compare/v8.22.0...v8.23.0) (2022-04-07)
|
|
7
18
|
|
|
8
19
|
**Note:** Version bump only for package @instructure/ui-date-time-input
|
|
@@ -254,6 +254,29 @@ let DateTimeInput = (_dec = testable(), _dec(_class = (_class2 = class DateTimeI
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
const newTimeSelectValue = (_this$state = this.state) !== null && _this$state !== void 0 && _this$state.timeSelectValue ? this.state.timeSelectValue : (_this$_timeInput = this._timeInput) === null || _this$_timeInput === void 0 ? void 0 : _this$_timeInput.getBaseDate().minute(parsed.minute()).hour(parsed.hour()).toISOString();
|
|
257
|
+
|
|
258
|
+
if (this.isDisabledDate(parsed)) {
|
|
259
|
+
let text = typeof this.props.disabledDateTimeMessage === 'function' ? this.props.disabledDateTimeMessage(parsed.toISOString(true)) : this.props.disabledDateTimeMessage;
|
|
260
|
+
|
|
261
|
+
if (!text) {
|
|
262
|
+
text = typeof this.props.invalidDateTimeMessage === 'function' ? this.props.invalidDateTimeMessage(parsed.toISOString(true)) : this.props.invalidDateTimeMessage;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
errorMsg = text ? {
|
|
266
|
+
text,
|
|
267
|
+
type: 'error'
|
|
268
|
+
} : void 0;
|
|
269
|
+
return {
|
|
270
|
+
iso: parsed.clone(),
|
|
271
|
+
calendarSelectedDate: parsed.clone(),
|
|
272
|
+
dateInputTextChanged: false,
|
|
273
|
+
dateInputText: parsed.format(this.dateFormat),
|
|
274
|
+
message: errorMsg,
|
|
275
|
+
timeSelectValue: newTimeSelectValue,
|
|
276
|
+
renderedDate: parsed.clone()
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
257
280
|
return {
|
|
258
281
|
iso: parsed.clone(),
|
|
259
282
|
calendarSelectedDate: parsed.clone(),
|
|
@@ -309,6 +332,26 @@ let DateTimeInput = (_dec = testable(), _dec(_class = (_class2 = class DateTimeI
|
|
|
309
332
|
|
|
310
333
|
get dateFormat() {
|
|
311
334
|
return this.props.dateFormat;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
isDisabledDate(date) {
|
|
338
|
+
const disabledDates = this.props.disabledDates;
|
|
339
|
+
|
|
340
|
+
if (!disabledDates) {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (Array.isArray(disabledDates)) {
|
|
345
|
+
for (const aDisabledDate of disabledDates) {
|
|
346
|
+
if (date.isSame(aDisabledDate, 'day')) {
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return disabledDates(date.toISOString());
|
|
312
355
|
} // Called when the user enters text into dateInput
|
|
313
356
|
|
|
314
357
|
|
|
@@ -369,7 +412,8 @@ let DateTimeInput = (_dec = testable(), _dec(_class = (_class2 = class DateTimeI
|
|
|
369
412
|
isOutsideMonth: !date.isSame(renderedDate, 'month'),
|
|
370
413
|
label: date.format('D MMMM YYYY') // used by screen readers
|
|
371
414
|
,
|
|
372
|
-
onClick: this.handleDayClick
|
|
415
|
+
onClick: this.handleDayClick,
|
|
416
|
+
interaction: this.isDisabledDate(date) ? 'disabled' : 'enabled'
|
|
373
417
|
}, date.format('DD'));
|
|
374
418
|
});
|
|
375
419
|
} // The default weekdays rendered in the calendar
|
|
@@ -439,18 +483,21 @@ let DateTimeInput = (_dec = testable(), _dec(_class = (_class2 = class DateTimeI
|
|
|
439
483
|
timezone = _this$props2.timezone,
|
|
440
484
|
messages = _this$props2.messages,
|
|
441
485
|
layout = _this$props2.layout,
|
|
486
|
+
rowSpacing = _this$props2.rowSpacing,
|
|
487
|
+
colSpacing = _this$props2.colSpacing,
|
|
442
488
|
isRequired = _this$props2.isRequired,
|
|
443
489
|
interaction = _this$props2.interaction,
|
|
444
490
|
renderWeekdayLabels = _this$props2.renderWeekdayLabels;
|
|
445
491
|
return /*#__PURE__*/React.createElement(FormFieldGroup, {
|
|
446
492
|
description: description,
|
|
447
|
-
colSpacing: "medium",
|
|
448
|
-
rowSpacing: "small",
|
|
449
493
|
layout: layout,
|
|
494
|
+
rowSpacing: rowSpacing,
|
|
495
|
+
colSpacing: colSpacing,
|
|
450
496
|
vAlign: "top",
|
|
451
497
|
elementRef: this.handleRef,
|
|
452
498
|
messages: [...(this.state.message ? [this.state.message] : []), ...(messages || [])]
|
|
453
499
|
}, /*#__PURE__*/React.createElement(DateInput, {
|
|
500
|
+
display: "block",
|
|
454
501
|
value: this.state.dateInputText,
|
|
455
502
|
onChange: this.handleDateTextChange,
|
|
456
503
|
onBlur: this.handleBlur,
|
|
@@ -489,6 +536,8 @@ let DateTimeInput = (_dec = testable(), _dec(_class = (_class2 = class DateTimeI
|
|
|
489
536
|
|
|
490
537
|
}, _class2.displayName = "DateTimeInput", _class2.DEFAULT_MESSAGE_FORMAT = 'LLLL', _class2.propTypes = propTypes, _class2.allowedProps = allowedProps, _class2.defaultProps = {
|
|
491
538
|
layout: 'inline',
|
|
539
|
+
colSpacing: 'medium',
|
|
540
|
+
rowSpacing: 'small',
|
|
492
541
|
timeStep: 30,
|
|
493
542
|
messageFormat: _class2.DEFAULT_MESSAGE_FORMAT,
|
|
494
543
|
isRequired: false,
|
|
@@ -42,6 +42,8 @@ const propTypes = {
|
|
|
42
42
|
messages: PropTypes.arrayOf(FormPropTypes.message),
|
|
43
43
|
messageFormat: PropTypes.string,
|
|
44
44
|
layout: PropTypes.oneOf(['stacked', 'columns', 'inline']),
|
|
45
|
+
rowSpacing: PropTypes.oneOf(['none', 'small', 'medium', 'large']),
|
|
46
|
+
colSpacing: PropTypes.oneOf(['none', 'small', 'medium', 'large']),
|
|
45
47
|
value: controllable(I18nPropTypes.iso8601, 'onChange'),
|
|
46
48
|
defaultValue: I18nPropTypes.iso8601,
|
|
47
49
|
renderWeekdayLabels: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.node])),
|
|
@@ -49,7 +51,9 @@ const propTypes = {
|
|
|
49
51
|
onChange: PropTypes.func,
|
|
50
52
|
dateInputRef: PropTypes.func,
|
|
51
53
|
timeInputRef: PropTypes.func,
|
|
52
|
-
onBlur: PropTypes.func
|
|
54
|
+
onBlur: PropTypes.func,
|
|
55
|
+
disabledDates: PropTypes.oneOfType([PropTypes.func, PropTypes.arrayOf(PropTypes.string)]),
|
|
56
|
+
disabledDateTimeMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.func])
|
|
53
57
|
};
|
|
54
|
-
const allowedProps = ['description', 'dateRenderLabel', 'prevMonthLabel', 'nextMonthLabel', 'datePlaceholder', 'dateFormat', 'interaction', 'timeRenderLabel', 'timeStep', 'timeFormat', 'locale', 'timezone', 'invalidDateTimeMessage', 'messages', 'messageFormat', 'layout', 'value', 'defaultValue', 'renderWeekdayLabels', 'isRequired', 'onChange', 'dateInputRef', 'timeInputRef', 'onBlur'];
|
|
58
|
+
const allowedProps = ['description', 'dateRenderLabel', 'prevMonthLabel', 'nextMonthLabel', 'datePlaceholder', 'dateFormat', 'interaction', 'timeRenderLabel', 'timeStep', 'timeFormat', 'locale', 'timezone', 'invalidDateTimeMessage', 'messages', 'messageFormat', 'layout', 'rowSpacing', 'colSpacing', 'value', 'defaultValue', 'renderWeekdayLabels', 'isRequired', 'onChange', 'dateInputRef', 'timeInputRef', 'onBlur', 'disabledDates', 'disabledDateTimeMessage'];
|
|
55
59
|
export { propTypes, allowedProps };
|
|
@@ -260,6 +260,29 @@ let DateTimeInput = (_dec = (0, _testable.testable)(), _dec(_class = (_class2 =
|
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
const newTimeSelectValue = (_this$state = this.state) !== null && _this$state !== void 0 && _this$state.timeSelectValue ? this.state.timeSelectValue : (_this$_timeInput = this._timeInput) === null || _this$_timeInput === void 0 ? void 0 : _this$_timeInput.getBaseDate().minute(parsed.minute()).hour(parsed.hour()).toISOString();
|
|
263
|
+
|
|
264
|
+
if (this.isDisabledDate(parsed)) {
|
|
265
|
+
let text = typeof this.props.disabledDateTimeMessage === 'function' ? this.props.disabledDateTimeMessage(parsed.toISOString(true)) : this.props.disabledDateTimeMessage;
|
|
266
|
+
|
|
267
|
+
if (!text) {
|
|
268
|
+
text = typeof this.props.invalidDateTimeMessage === 'function' ? this.props.invalidDateTimeMessage(parsed.toISOString(true)) : this.props.invalidDateTimeMessage;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
errorMsg = text ? {
|
|
272
|
+
text,
|
|
273
|
+
type: 'error'
|
|
274
|
+
} : void 0;
|
|
275
|
+
return {
|
|
276
|
+
iso: parsed.clone(),
|
|
277
|
+
calendarSelectedDate: parsed.clone(),
|
|
278
|
+
dateInputTextChanged: false,
|
|
279
|
+
dateInputText: parsed.format(this.dateFormat),
|
|
280
|
+
message: errorMsg,
|
|
281
|
+
timeSelectValue: newTimeSelectValue,
|
|
282
|
+
renderedDate: parsed.clone()
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
263
286
|
return {
|
|
264
287
|
iso: parsed.clone(),
|
|
265
288
|
calendarSelectedDate: parsed.clone(),
|
|
@@ -315,6 +338,26 @@ let DateTimeInput = (_dec = (0, _testable.testable)(), _dec(_class = (_class2 =
|
|
|
315
338
|
|
|
316
339
|
get dateFormat() {
|
|
317
340
|
return this.props.dateFormat;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
isDisabledDate(date) {
|
|
344
|
+
const disabledDates = this.props.disabledDates;
|
|
345
|
+
|
|
346
|
+
if (!disabledDates) {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (Array.isArray(disabledDates)) {
|
|
351
|
+
for (const aDisabledDate of disabledDates) {
|
|
352
|
+
if (date.isSame(aDisabledDate, 'day')) {
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return disabledDates(date.toISOString());
|
|
318
361
|
} // Called when the user enters text into dateInput
|
|
319
362
|
|
|
320
363
|
|
|
@@ -378,7 +421,8 @@ let DateTimeInput = (_dec = (0, _testable.testable)(), _dec(_class = (_class2 =
|
|
|
378
421
|
isOutsideMonth: !date.isSame(renderedDate, 'month'),
|
|
379
422
|
label: date.format('D MMMM YYYY') // used by screen readers
|
|
380
423
|
,
|
|
381
|
-
onClick: this.handleDayClick
|
|
424
|
+
onClick: this.handleDayClick,
|
|
425
|
+
interaction: this.isDisabledDate(date) ? 'disabled' : 'enabled'
|
|
382
426
|
}, date.format('DD'));
|
|
383
427
|
});
|
|
384
428
|
} // The default weekdays rendered in the calendar
|
|
@@ -450,18 +494,21 @@ let DateTimeInput = (_dec = (0, _testable.testable)(), _dec(_class = (_class2 =
|
|
|
450
494
|
timezone = _this$props2.timezone,
|
|
451
495
|
messages = _this$props2.messages,
|
|
452
496
|
layout = _this$props2.layout,
|
|
497
|
+
rowSpacing = _this$props2.rowSpacing,
|
|
498
|
+
colSpacing = _this$props2.colSpacing,
|
|
453
499
|
isRequired = _this$props2.isRequired,
|
|
454
500
|
interaction = _this$props2.interaction,
|
|
455
501
|
renderWeekdayLabels = _this$props2.renderWeekdayLabels;
|
|
456
502
|
return /*#__PURE__*/_react.default.createElement(_FormFieldGroup.FormFieldGroup, {
|
|
457
503
|
description: description,
|
|
458
|
-
colSpacing: "medium",
|
|
459
|
-
rowSpacing: "small",
|
|
460
504
|
layout: layout,
|
|
505
|
+
rowSpacing: rowSpacing,
|
|
506
|
+
colSpacing: colSpacing,
|
|
461
507
|
vAlign: "top",
|
|
462
508
|
elementRef: this.handleRef,
|
|
463
509
|
messages: [...(this.state.message ? [this.state.message] : []), ...(messages || [])]
|
|
464
510
|
}, /*#__PURE__*/_react.default.createElement(_DateInput.DateInput, {
|
|
511
|
+
display: "block",
|
|
465
512
|
value: this.state.dateInputText,
|
|
466
513
|
onChange: this.handleDateTextChange,
|
|
467
514
|
onBlur: this.handleBlur,
|
|
@@ -500,6 +547,8 @@ let DateTimeInput = (_dec = (0, _testable.testable)(), _dec(_class = (_class2 =
|
|
|
500
547
|
|
|
501
548
|
}, _class2.displayName = "DateTimeInput", _class2.DEFAULT_MESSAGE_FORMAT = 'LLLL', _class2.propTypes = _props.propTypes, _class2.allowedProps = _props.allowedProps, _class2.defaultProps = {
|
|
502
549
|
layout: 'inline',
|
|
550
|
+
colSpacing: 'medium',
|
|
551
|
+
rowSpacing: 'small',
|
|
503
552
|
timeStep: 30,
|
|
504
553
|
messageFormat: _class2.DEFAULT_MESSAGE_FORMAT,
|
|
505
554
|
isRequired: false,
|
|
@@ -55,6 +55,8 @@ const propTypes = {
|
|
|
55
55
|
messages: _propTypes.default.arrayOf(_FormPropTypes.FormPropTypes.message),
|
|
56
56
|
messageFormat: _propTypes.default.string,
|
|
57
57
|
layout: _propTypes.default.oneOf(['stacked', 'columns', 'inline']),
|
|
58
|
+
rowSpacing: _propTypes.default.oneOf(['none', 'small', 'medium', 'large']),
|
|
59
|
+
colSpacing: _propTypes.default.oneOf(['none', 'small', 'medium', 'large']),
|
|
58
60
|
value: (0, _controllable.controllable)(_I18nPropTypes.I18nPropTypes.iso8601, 'onChange'),
|
|
59
61
|
defaultValue: _I18nPropTypes.I18nPropTypes.iso8601,
|
|
60
62
|
renderWeekdayLabels: _propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.node])),
|
|
@@ -62,8 +64,10 @@ const propTypes = {
|
|
|
62
64
|
onChange: _propTypes.default.func,
|
|
63
65
|
dateInputRef: _propTypes.default.func,
|
|
64
66
|
timeInputRef: _propTypes.default.func,
|
|
65
|
-
onBlur: _propTypes.default.func
|
|
67
|
+
onBlur: _propTypes.default.func,
|
|
68
|
+
disabledDates: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.arrayOf(_propTypes.default.string)]),
|
|
69
|
+
disabledDateTimeMessage: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func])
|
|
66
70
|
};
|
|
67
71
|
exports.propTypes = propTypes;
|
|
68
|
-
const allowedProps = ['description', 'dateRenderLabel', 'prevMonthLabel', 'nextMonthLabel', 'datePlaceholder', 'dateFormat', 'interaction', 'timeRenderLabel', 'timeStep', 'timeFormat', 'locale', 'timezone', 'invalidDateTimeMessage', 'messages', 'messageFormat', 'layout', 'value', 'defaultValue', 'renderWeekdayLabels', 'isRequired', 'onChange', 'dateInputRef', 'timeInputRef', 'onBlur'];
|
|
72
|
+
const allowedProps = ['description', 'dateRenderLabel', 'prevMonthLabel', 'nextMonthLabel', 'datePlaceholder', 'dateFormat', 'interaction', 'timeRenderLabel', 'timeStep', 'timeFormat', 'locale', 'timezone', 'invalidDateTimeMessage', 'messages', 'messageFormat', 'layout', 'rowSpacing', 'colSpacing', 'value', 'defaultValue', 'renderWeekdayLabels', 'isRequired', 'onChange', 'dateInputRef', 'timeInputRef', 'onBlur', 'disabledDates', 'disabledDateTimeMessage'];
|
|
69
73
|
exports.allowedProps = allowedProps;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instructure/ui-date-time-input",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.24.0",
|
|
4
4
|
"description": "A UI component that allows to select date and time.",
|
|
5
5
|
"author": "Instructure, Inc. Engineering and Product Design",
|
|
6
6
|
"module": "./es/index.js",
|
|
@@ -23,26 +23,26 @@
|
|
|
23
23
|
},
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@instructure/ui-babel-preset": "8.
|
|
27
|
-
"@instructure/ui-test-locator": "8.
|
|
28
|
-
"@instructure/ui-test-utils": "8.
|
|
26
|
+
"@instructure/ui-babel-preset": "8.24.0",
|
|
27
|
+
"@instructure/ui-test-locator": "8.24.0",
|
|
28
|
+
"@instructure/ui-test-utils": "8.24.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@babel/runtime": "^7.13.10",
|
|
32
|
-
"@instructure/debounce": "8.
|
|
33
|
-
"@instructure/emotion": "8.
|
|
34
|
-
"@instructure/ui-a11y-content": "8.
|
|
35
|
-
"@instructure/ui-buttons": "8.
|
|
36
|
-
"@instructure/ui-calendar": "8.
|
|
37
|
-
"@instructure/ui-date-input": "8.
|
|
38
|
-
"@instructure/ui-form-field": "8.
|
|
39
|
-
"@instructure/ui-i18n": "8.
|
|
40
|
-
"@instructure/ui-icons": "8.
|
|
41
|
-
"@instructure/ui-prop-types": "8.
|
|
42
|
-
"@instructure/ui-react-utils": "8.
|
|
43
|
-
"@instructure/ui-testable": "8.
|
|
44
|
-
"@instructure/ui-time-select": "8.
|
|
45
|
-
"@instructure/ui-utils": "8.
|
|
32
|
+
"@instructure/debounce": "8.24.0",
|
|
33
|
+
"@instructure/emotion": "8.24.0",
|
|
34
|
+
"@instructure/ui-a11y-content": "8.24.0",
|
|
35
|
+
"@instructure/ui-buttons": "8.24.0",
|
|
36
|
+
"@instructure/ui-calendar": "8.24.0",
|
|
37
|
+
"@instructure/ui-date-input": "8.24.0",
|
|
38
|
+
"@instructure/ui-form-field": "8.24.0",
|
|
39
|
+
"@instructure/ui-i18n": "8.24.0",
|
|
40
|
+
"@instructure/ui-icons": "8.24.0",
|
|
41
|
+
"@instructure/ui-prop-types": "8.24.0",
|
|
42
|
+
"@instructure/ui-react-utils": "8.24.0",
|
|
43
|
+
"@instructure/ui-testable": "8.24.0",
|
|
44
|
+
"@instructure/ui-time-select": "8.24.0",
|
|
45
|
+
"@instructure/ui-utils": "8.24.0",
|
|
46
46
|
"prop-types": "^15"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
@@ -51,6 +51,5 @@
|
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
|
-
"sideEffects": false
|
|
55
|
-
"gitHead": "67fb0a5bed0138c5152872999bf1138dd2fd8fd7"
|
|
54
|
+
"sideEffects": false
|
|
56
55
|
}
|
|
@@ -5,13 +5,19 @@ describes: DateTimeInput
|
|
|
5
5
|
A DateTimeInput component is used to enter a date-time value. It is built as a composition
|
|
6
6
|
of the [DateInput](#DateInput) and [TimeSelect](#TimeSelect) components.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
The properties of DateTimeInput prefaced with _date_ are passed to the underlying [DateInput](#DateInput)
|
|
9
|
+
(e.g. _dateLabel_ is DateInput's _label_), while the properties prefaced
|
|
10
|
+
with _time_ are forwarded to the underlying
|
|
11
|
+
[TimeSelect](#TimeSelect). Others are either shared by both sub-components (e.g. locale), or
|
|
12
|
+
are unique to DateTimeInput (e.g. description).
|
|
13
|
+
|
|
14
|
+
### Localization
|
|
9
15
|
|
|
10
16
|
The component is localized via its `locale` and `timezone` parameters. Both are read from `props`, `context` and from the browser's locale in this priority order. `locale` determines the language and format dates and time are displayed in (e.g. month names, AM/PM or 24-hour format) and the beginning of the week (e.g. Monday in Germany, Sunday in the U.S.) in the dropdown calendar.
|
|
11
17
|
|
|
12
|
-
|
|
18
|
+
### Examples
|
|
13
19
|
|
|
14
|
-
A DateTimeInput with `columns` layout and a default value:
|
|
20
|
+
#### A DateTimeInput with `columns` layout and a default value:
|
|
15
21
|
|
|
16
22
|
```js
|
|
17
23
|
---
|
|
@@ -21,7 +27,7 @@ render: false
|
|
|
21
27
|
class Example extends React.Component {
|
|
22
28
|
render () {
|
|
23
29
|
return (
|
|
24
|
-
<div style= { {height:
|
|
30
|
+
<div style= { {height: '10rem',width: '40em'}}>
|
|
25
31
|
<DateTimeInput
|
|
26
32
|
description="Pick a date and time"
|
|
27
33
|
datePlaceholder="Choose a date"
|
|
@@ -39,7 +45,7 @@ class Example extends React.Component {
|
|
|
39
45
|
render(<Example />)
|
|
40
46
|
```
|
|
41
47
|
|
|
42
|
-
A required DateInput with `stacked` layout that warns if the value in the past:
|
|
48
|
+
#### A required DateInput with `stacked` layout that warns if the value in the past:
|
|
43
49
|
|
|
44
50
|
```js
|
|
45
51
|
---
|
|
@@ -69,9 +75,9 @@ class Example extends React.Component {
|
|
|
69
75
|
render () {
|
|
70
76
|
const text = this.state.value ? new Date(this.state.value).toString() : 'N/A'
|
|
71
77
|
return (
|
|
72
|
-
<div style={{width: '
|
|
78
|
+
<div style={{width: '25em'}}>
|
|
73
79
|
<div style={{marginBottom: '1em', fontStyle: 'italic'}}>You entered:<br/>{text}</div>
|
|
74
|
-
<div style={{height:
|
|
80
|
+
<div style={{height: '14rem'}}>
|
|
75
81
|
<DateTimeInput
|
|
76
82
|
description={<ScreenReaderContent>Pick a date and time</ScreenReaderContent>}
|
|
77
83
|
datePlaceholder="Choose"
|
|
@@ -94,7 +100,7 @@ class Example extends React.Component {
|
|
|
94
100
|
render(<Example />)
|
|
95
101
|
```
|
|
96
102
|
|
|
97
|
-
A disabled DateTimeInput:
|
|
103
|
+
#### A disabled DateTimeInput:
|
|
98
104
|
|
|
99
105
|
```js
|
|
100
106
|
---
|
|
@@ -115,7 +121,7 @@ render: true
|
|
|
115
121
|
/>
|
|
116
122
|
```
|
|
117
123
|
|
|
118
|
-
A DateTimeInput in a different locale and timezone where these are set from the React `context`:
|
|
124
|
+
#### A DateTimeInput in a different locale and timezone where these are set from the React `context`:
|
|
119
125
|
|
|
120
126
|
```js
|
|
121
127
|
---
|
|
@@ -126,7 +132,7 @@ class Example extends React.Component {
|
|
|
126
132
|
render() {
|
|
127
133
|
return (
|
|
128
134
|
<ApplyLocale locale="fr" timezone="Africa/Nairobi">
|
|
129
|
-
<div style={{ height:
|
|
135
|
+
<div style={{ height: '12rem', width: '40em' }}>
|
|
130
136
|
<DateTimeInput
|
|
131
137
|
description="Pick a date and time"
|
|
132
138
|
datePlaceholder="Choose a date"
|
|
@@ -147,8 +153,67 @@ class Example extends React.Component {
|
|
|
147
153
|
render(<Example />)
|
|
148
154
|
```
|
|
149
155
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
#### A `DateTimeInput` with some disabled dates that are supplied via a `string` array:
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
---
|
|
160
|
+
example: true
|
|
161
|
+
render: true
|
|
162
|
+
---
|
|
163
|
+
<DateTimeInput
|
|
164
|
+
description="Pick a date and time"
|
|
165
|
+
datePlaceholder="Choose a date"
|
|
166
|
+
dateRenderLabel="Date"
|
|
167
|
+
timeRenderLabel="Time"
|
|
168
|
+
invalidDateTimeMessage="Invalid date"
|
|
169
|
+
disabledDateTimeMessage="Disabled date"
|
|
170
|
+
prevMonthLabel="Previous month"
|
|
171
|
+
nextMonthLabel="Next month"
|
|
172
|
+
defaultValue="2022-04-08T13:30"
|
|
173
|
+
layout="columns"
|
|
174
|
+
disabledDates={['2022-04-01T13:30', '2022-04-03T13:30', '2022-04-04T13:30']}
|
|
175
|
+
locale="en-us"
|
|
176
|
+
timezone="America/Denver"
|
|
177
|
+
/>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### A `DateTimeInput` with some disabled dates that are supplied via a `function`:
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
---
|
|
184
|
+
example: true
|
|
185
|
+
render: false
|
|
186
|
+
---
|
|
187
|
+
const locale = 'en-us'
|
|
188
|
+
const timezone = 'America/Denver'
|
|
189
|
+
|
|
190
|
+
class Example extends React.Component {
|
|
191
|
+
getDisabledDates(isoDateToCheck) {
|
|
192
|
+
const parsed = moment.tz(isoDateToCheck, [moment.ISO_8601], locale, timezone)
|
|
193
|
+
const now = moment().locale(locale).tz(timezone)
|
|
194
|
+
return parsed.isBefore(now)
|
|
195
|
+
}
|
|
196
|
+
render() {
|
|
197
|
+
return (
|
|
198
|
+
<div style= { {height: '12rem', width: '40em'}}>
|
|
199
|
+
<DateTimeInput
|
|
200
|
+
description="Pick a date and time"
|
|
201
|
+
datePlaceholder="Choose a date"
|
|
202
|
+
dateRenderLabel="Date"
|
|
203
|
+
timeRenderLabel="Time"
|
|
204
|
+
invalidDateTimeMessage={(rawDateValue) => 'Invalid date: ' + rawDateValue}
|
|
205
|
+
disabledDateTimeMessage={(rawDateValue) => 'Disabled date: ' + rawDateValue}
|
|
206
|
+
prevMonthLabel="Previous month"
|
|
207
|
+
nextMonthLabel="Next month"
|
|
208
|
+
defaultValue="2022-04-08T13:30"
|
|
209
|
+
layout="columns"
|
|
210
|
+
disabledDates={this.getDisabledDates}
|
|
211
|
+
locale={locale}
|
|
212
|
+
timezone={timezone}
|
|
213
|
+
/>
|
|
214
|
+
</div>)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
render(<Example />)
|
|
219
|
+
```
|
|
@@ -56,6 +56,8 @@ class DateTimeInput extends Component<DateTimeInputProps, DateTimeInputState> {
|
|
|
56
56
|
static allowedProps = allowedProps
|
|
57
57
|
static defaultProps = {
|
|
58
58
|
layout: 'inline',
|
|
59
|
+
colSpacing: 'medium',
|
|
60
|
+
rowSpacing: 'small',
|
|
59
61
|
timeStep: 30,
|
|
60
62
|
messageFormat: DateTimeInput.DEFAULT_MESSAGE_FORMAT,
|
|
61
63
|
isRequired: false,
|
|
@@ -141,6 +143,28 @@ class DateTimeInput extends Component<DateTimeInputProps, DateTimeInputState> {
|
|
|
141
143
|
.minute(parsed.minute())
|
|
142
144
|
.hour(parsed.hour())
|
|
143
145
|
.toISOString()
|
|
146
|
+
if (this.isDisabledDate(parsed)) {
|
|
147
|
+
let text =
|
|
148
|
+
typeof this.props.disabledDateTimeMessage === 'function'
|
|
149
|
+
? this.props.disabledDateTimeMessage(parsed.toISOString(true))
|
|
150
|
+
: this.props.disabledDateTimeMessage
|
|
151
|
+
if (!text) {
|
|
152
|
+
text =
|
|
153
|
+
typeof this.props.invalidDateTimeMessage === 'function'
|
|
154
|
+
? this.props.invalidDateTimeMessage(parsed.toISOString(true))
|
|
155
|
+
: this.props.invalidDateTimeMessage
|
|
156
|
+
}
|
|
157
|
+
errorMsg = text ? { text, type: 'error' } : undefined
|
|
158
|
+
return {
|
|
159
|
+
iso: parsed.clone(),
|
|
160
|
+
calendarSelectedDate: parsed.clone(),
|
|
161
|
+
dateInputTextChanged: false,
|
|
162
|
+
dateInputText: parsed.format(this.dateFormat),
|
|
163
|
+
message: errorMsg,
|
|
164
|
+
timeSelectValue: newTimeSelectValue,
|
|
165
|
+
renderedDate: parsed.clone()
|
|
166
|
+
}
|
|
167
|
+
}
|
|
144
168
|
return {
|
|
145
169
|
iso: parsed.clone(),
|
|
146
170
|
calendarSelectedDate: parsed.clone(),
|
|
@@ -194,6 +218,22 @@ class DateTimeInput extends Component<DateTimeInputProps, DateTimeInputState> {
|
|
|
194
218
|
return this.props.dateFormat
|
|
195
219
|
}
|
|
196
220
|
|
|
221
|
+
isDisabledDate(date: Moment) {
|
|
222
|
+
const disabledDates = this.props.disabledDates
|
|
223
|
+
if (!disabledDates) {
|
|
224
|
+
return false
|
|
225
|
+
}
|
|
226
|
+
if (Array.isArray(disabledDates)) {
|
|
227
|
+
for (const aDisabledDate of disabledDates) {
|
|
228
|
+
if (date.isSame(aDisabledDate, 'day')) {
|
|
229
|
+
return true
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return false
|
|
233
|
+
}
|
|
234
|
+
return disabledDates(date.toISOString())
|
|
235
|
+
}
|
|
236
|
+
|
|
197
237
|
// Called when the user enters text into dateInput
|
|
198
238
|
handleDateTextChange = (_event: SyntheticEvent, date: { value: string }) => {
|
|
199
239
|
const dateParsed = this.tryParseDate(date.value)
|
|
@@ -406,6 +446,7 @@ class DateTimeInput extends Component<DateTimeInputProps, DateTimeInputState> {
|
|
|
406
446
|
isOutsideMonth={!date.isSame(renderedDate, 'month')}
|
|
407
447
|
label={date.format('D MMMM YYYY')} // used by screen readers
|
|
408
448
|
onClick={this.handleDayClick}
|
|
449
|
+
interaction={this.isDisabledDate(date) ? 'disabled' : 'enabled'}
|
|
409
450
|
>
|
|
410
451
|
{date.format('DD')}
|
|
411
452
|
</DateInput.Day>
|
|
@@ -491,16 +532,19 @@ class DateTimeInput extends Component<DateTimeInputProps, DateTimeInputState> {
|
|
|
491
532
|
timezone,
|
|
492
533
|
messages,
|
|
493
534
|
layout,
|
|
535
|
+
rowSpacing,
|
|
536
|
+
colSpacing,
|
|
494
537
|
isRequired,
|
|
495
538
|
interaction,
|
|
496
539
|
renderWeekdayLabels
|
|
497
540
|
} = this.props
|
|
541
|
+
|
|
498
542
|
return (
|
|
499
543
|
<FormFieldGroup
|
|
500
544
|
description={description}
|
|
501
|
-
colSpacing="medium"
|
|
502
|
-
rowSpacing="small"
|
|
503
545
|
layout={layout}
|
|
546
|
+
rowSpacing={rowSpacing}
|
|
547
|
+
colSpacing={colSpacing}
|
|
504
548
|
vAlign="top"
|
|
505
549
|
elementRef={this.handleRef}
|
|
506
550
|
messages={[
|
|
@@ -509,6 +553,7 @@ class DateTimeInput extends Component<DateTimeInputProps, DateTimeInputState> {
|
|
|
509
553
|
]}
|
|
510
554
|
>
|
|
511
555
|
<DateInput
|
|
556
|
+
display="block"
|
|
512
557
|
value={this.state.dateInputText}
|
|
513
558
|
onChange={this.handleDateTextChange}
|
|
514
559
|
onBlur={this.handleBlur}
|
|
@@ -152,6 +152,14 @@ type DateTimeInputProps = {
|
|
|
152
152
|
* See [FormFieldGroup](#FormFieldGroup) for details.
|
|
153
153
|
**/
|
|
154
154
|
layout?: 'stacked' | 'columns' | 'inline'
|
|
155
|
+
/**
|
|
156
|
+
* Controls the spacing between the inputs when they are in a vertical layout.
|
|
157
|
+
**/
|
|
158
|
+
rowSpacing?: 'none' | 'small' | 'medium' | 'large'
|
|
159
|
+
/**
|
|
160
|
+
* Controls the spacing between the inputs when they are in a horizontal layout.
|
|
161
|
+
**/
|
|
162
|
+
colSpacing?: 'none' | 'small' | 'medium' | 'large'
|
|
155
163
|
/**
|
|
156
164
|
* An ISO 8601 formatted date string representing the current date-time
|
|
157
165
|
* (must be accompanied by an onChange prop).
|
|
@@ -197,7 +205,7 @@ type DateTimeInputProps = {
|
|
|
197
205
|
* Called when the date-time value has changed.
|
|
198
206
|
* The passed in parameters are:
|
|
199
207
|
* - *event*: The triggering event (which may be from the underlying
|
|
200
|
-
*
|
|
208
|
+
* `DateInput` or `TimeSelect`)
|
|
201
209
|
* - *isoValue*: The new date value in ISO8601 format, undefined if its invalid
|
|
202
210
|
**/
|
|
203
211
|
onChange?: (event: SyntheticEvent, isoValue?: string) => void
|
|
@@ -215,6 +223,17 @@ type DateTimeInputProps = {
|
|
|
215
223
|
* component
|
|
216
224
|
*/
|
|
217
225
|
onBlur?: (e: SyntheticEvent) => void
|
|
226
|
+
/*
|
|
227
|
+
* Specify which date(s) will be shown as disabled in the calendar.
|
|
228
|
+
* You can either supply an array of ISO8601 timeDate strings or
|
|
229
|
+
* a function that will be called for each date shown in the calendar.
|
|
230
|
+
*/
|
|
231
|
+
disabledDates?: string[] | ((isoDateToCheck: string) => boolean)
|
|
232
|
+
/**
|
|
233
|
+
* Error message shown to the user if they enter a date that is disabled.
|
|
234
|
+
* If not specified the component will show the `invalidDateTimeMessage`.
|
|
235
|
+
*/
|
|
236
|
+
disabledDateTimeMessage?: string | ((rawDateValue: string) => string)
|
|
218
237
|
}
|
|
219
238
|
|
|
220
239
|
type DateTimeInputState = {
|
|
@@ -264,6 +283,8 @@ const propTypes: PropValidators<PropKeys> = {
|
|
|
264
283
|
messages: PropTypes.arrayOf(FormPropTypes.message),
|
|
265
284
|
messageFormat: PropTypes.string,
|
|
266
285
|
layout: PropTypes.oneOf(['stacked', 'columns', 'inline']),
|
|
286
|
+
rowSpacing: PropTypes.oneOf(['none', 'small', 'medium', 'large']),
|
|
287
|
+
colSpacing: PropTypes.oneOf(['none', 'small', 'medium', 'large']),
|
|
267
288
|
value: controllable(I18nPropTypes.iso8601, 'onChange'),
|
|
268
289
|
defaultValue: I18nPropTypes.iso8601,
|
|
269
290
|
renderWeekdayLabels: PropTypes.arrayOf(
|
|
@@ -273,7 +294,15 @@ const propTypes: PropValidators<PropKeys> = {
|
|
|
273
294
|
onChange: PropTypes.func,
|
|
274
295
|
dateInputRef: PropTypes.func,
|
|
275
296
|
timeInputRef: PropTypes.func,
|
|
276
|
-
onBlur: PropTypes.func
|
|
297
|
+
onBlur: PropTypes.func,
|
|
298
|
+
disabledDates: PropTypes.oneOfType([
|
|
299
|
+
PropTypes.func,
|
|
300
|
+
PropTypes.arrayOf(PropTypes.string)
|
|
301
|
+
]),
|
|
302
|
+
disabledDateTimeMessage: PropTypes.oneOfType([
|
|
303
|
+
PropTypes.string,
|
|
304
|
+
PropTypes.func
|
|
305
|
+
])
|
|
277
306
|
}
|
|
278
307
|
|
|
279
308
|
const allowedProps: AllowedPropKeys = [
|
|
@@ -293,6 +322,8 @@ const allowedProps: AllowedPropKeys = [
|
|
|
293
322
|
'messages',
|
|
294
323
|
'messageFormat',
|
|
295
324
|
'layout',
|
|
325
|
+
'rowSpacing',
|
|
326
|
+
'colSpacing',
|
|
296
327
|
'value',
|
|
297
328
|
'defaultValue',
|
|
298
329
|
'renderWeekdayLabels',
|
|
@@ -300,7 +331,9 @@ const allowedProps: AllowedPropKeys = [
|
|
|
300
331
|
'onChange',
|
|
301
332
|
'dateInputRef',
|
|
302
333
|
'timeInputRef',
|
|
303
|
-
'onBlur'
|
|
334
|
+
'onBlur',
|
|
335
|
+
'disabledDates',
|
|
336
|
+
'disabledDateTimeMessage'
|
|
304
337
|
]
|
|
305
338
|
|
|
306
339
|
export type { DateTimeInputProps, DateTimeInputState }
|