@instructure/ui-date-time-input 11.7.3-snapshot-25 → 11.7.3-snapshot-26

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 CHANGED
@@ -3,9 +3,12 @@
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
- ## [11.7.3-snapshot-25](https://github.com/instructure/instructure-ui/compare/v11.7.2...v11.7.3-snapshot-25) (2026-04-30)
6
+ ## [11.7.3-snapshot-26](https://github.com/instructure/instructure-ui/compare/v11.7.2...v11.7.3-snapshot-26) (2026-05-05)
7
7
 
8
- **Note:** Version bump only for package @instructure/ui-date-time-input
8
+
9
+ ### Bug Fixes
10
+
11
+ * **many:** update dependencies, remove lots of Babel plugins, remove Webpack 4 support ([f916fca](https://github.com/instructure/instructure-ui/commit/f916fcafdddcb2d7de401f93e8ff92cfdfa47bba))
9
12
 
10
13
 
11
14
 
@@ -1,4 +1,3 @@
1
- var _DateTimeInput, _IconArrowOpenStartSo, _IconArrowOpenEndSoli;
2
1
  /*
3
2
  * The MIT License (MIT)
4
3
  *
@@ -42,168 +41,40 @@ category: components
42
41
  **/
43
42
  import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
44
43
  class DateTimeInput extends Component {
44
+ static displayName = "DateTimeInput";
45
+ // extra verbose localized date and time
46
+ static DEFAULT_MESSAGE_FORMAT = 'LLLL';
47
+ static allowedProps = allowedProps;
48
+ static defaultProps = {
49
+ layout: 'inline',
50
+ colSpacing: 'medium',
51
+ rowSpacing: 'small',
52
+ timeStep: 30,
53
+ showMessages: true,
54
+ messageFormat: DateTimeInput.DEFAULT_MESSAGE_FORMAT,
55
+ isRequired: false,
56
+ dateFormat: 'LL',
57
+ // Localized date with full month, e.g. "August 6, 2014"
58
+ allowNonStepInput: false
59
+ };
60
+ static contextType = ApplyLocaleContext;
61
+ ref = null; // This is used by Tooltip for positioning
62
+
63
+ handleRef = el => {
64
+ this.ref = el;
65
+ };
45
66
  constructor(props) {
46
67
  super(props);
47
68
  // State needs to be calculated because render could be called before
48
69
  // componentDidMount()
49
- this.ref = null;
50
- // This is used by Tooltip for positioning
51
- this.handleRef = el => {
52
- this.ref = el;
53
- };
54
- this.reset = () => this.setState(this.recalculateState());
55
- // Called when the user enters text into dateInput
56
- this.handleDateTextChange = (_event, date) => {
57
- const dateParsed = this.tryParseDate(date.value);
58
- this.setState({
59
- dateInputText: date.value,
60
- dateInputTextChanged: true,
61
- calendarSelectedDate: dateParsed ? dateParsed : void 0,
62
- renderedDate: dateParsed ? dateParsed.clone() : DateTime.now(this.locale(), this.timezone())
63
- });
64
- };
65
- // date is returned es a ISO string, like 2021-09-14T22:00:00.000Z
66
- this.handleDayClick = (event, {
67
- date
68
- }) => {
69
- const dateParsed = DateTime.parse(date, this.locale(), this.timezone());
70
- this.updateStateBasedOnDateInput(dateParsed, event);
71
- };
72
- this.handleHideCalendar = event => {
73
- // prevent event pooling https://reactjs.org/docs/legacy-event-pooling.html
74
- // Remove if React 16 is no longer supported
75
- event.persist();
76
- // timeout is needed here because handleDayClick could be called in the same
77
- // frame, and it updates calendarSelectedDate which is read in here.
78
- setTimeout(() => {
79
- if (event.key === 'Enter') {
80
- // user pressed enter, use the selected value in the calendar
81
- this.updateStateBasedOnDateInput(this.state.calendarSelectedDate, event);
82
- } else {
83
- // user clicked outside/tabbed away/pressed esc, try to use the value in dateInputText
84
- const dateParsed = this.tryParseDate(this.state.dateInputText);
85
- this.updateStateBasedOnDateInput(dateParsed, event);
86
- }
87
- this.setState({
88
- isShowingCalendar: false,
89
- dateInputTextChanged: false
90
- });
91
- }, 0);
92
- };
93
- this.updateStateBasedOnTimeSelect = (event, option) => {
94
- // this.state.iso is undefined if date is invalid or not set.
95
- // in this case recalculate with the dateInput's text which will result in
96
- // an empty valid date (if isRequired is false) or an invalid date.
97
- const newValue = this.state.iso ? option.value : this.state.dateInputText;
98
- const newState = this.recalculateState(newValue, true, false);
99
- this.changeStateIfNeeded(newState, event);
100
- this.setState({
101
- timeSelectValue: option.value
102
- });
103
- };
104
- this.changeStateIfNeeded = (newState, e) => {
105
- const dateStr = newState.dateInputText;
106
- if (this.props.isRequired && !newState.iso || dateStr && dateStr.length > 0 && !newState.iso) {
107
- const text = typeof this.props.invalidDateTimeMessage === 'function' ? this.props.invalidDateTimeMessage(dateStr ? dateStr : '') : this.props.invalidDateTimeMessage;
108
- // eslint-disable-next-line no-param-reassign
109
- newState.message = {
110
- text: text,
111
- type: 'error'
112
- };
113
- }
114
- if (this.areDifferentDates(this.state.iso, newState.iso)) {
115
- if (typeof this.props.onChange === 'function') {
116
- var _newState$iso;
117
- const newDate = (_newState$iso = newState.iso) === null || _newState$iso === void 0 ? void 0 : _newState$iso.toISOString();
118
- // Timeout is needed here because users might change value in the
119
- // onChange event lister, which might not execute properly
120
- setTimeout(() => {
121
- var _this$props$onChange, _this$props;
122
- (_this$props$onChange = (_this$props = this.props).onChange) === null || _this$props$onChange === void 0 ? void 0 : _this$props$onChange.call(_this$props, e, newDate);
123
- }, 0);
124
- }
125
- }
126
- this.setState(newState);
127
- };
128
- this.areDifferentDates = (d1, d2) => {
129
- if (!d1 && !d2) {
130
- return false;
131
- }
132
- return !d1 || !d2 || !d1.isSame(d2);
133
- };
134
- this.handleBlur = e => {
135
- // when TABbing from the DateInput to TimeInput or visa-versa, the blur
136
- // happens on the target before the relatedTarget gets focus.
137
- // The timeout gives it a moment for that to happen
138
- if (typeof this.props.onBlur === 'function') {
139
- setTimeout(() => {
140
- var _this$props$onBlur, _this$props2;
141
- (_this$props$onBlur = (_this$props2 = this.props).onBlur) === null || _this$props$onBlur === void 0 ? void 0 : _this$props$onBlur.call(_this$props2, e);
142
- }, 0);
143
- }
144
- };
145
- this.handleShowCalendar = _event => {
146
- this.setState({
147
- isShowingCalendar: true
148
- });
149
- };
150
- this.handleSelectNextDay = _event => {
151
- let toAlter;
152
- if (this.state.calendarSelectedDate) {
153
- toAlter = this.state.calendarSelectedDate.clone();
154
- } else if (this.state.iso) {
155
- toAlter = this.state.iso.clone();
156
- } else {
157
- toAlter = DateTime.now(this.locale(), this.timezone());
158
- }
159
- toAlter.add({
160
- days: 1
161
- });
162
- this.setState({
163
- calendarSelectedDate: toAlter,
164
- renderedDate: toAlter.clone()
165
- });
166
- };
167
- this.handleSelectPrevDay = _event => {
168
- let toAlter;
169
- if (this.state.calendarSelectedDate) {
170
- toAlter = this.state.calendarSelectedDate.clone();
171
- } else if (this.state.iso) {
172
- toAlter = this.state.iso.clone();
173
- } else {
174
- toAlter = DateTime.now(this.locale(), this.timezone());
175
- }
176
- toAlter.subtract({
177
- days: 1
178
- });
179
- this.setState({
180
- calendarSelectedDate: toAlter,
181
- renderedDate: toAlter.clone()
182
- });
183
- };
184
- this.handleRenderNextMonth = _event => {
185
- this.setState({
186
- renderedDate: this.state.renderedDate.clone().add({
187
- months: 1
188
- })
189
- });
190
- };
191
- this.handleRenderPrevMonth = _event => {
192
- this.setState({
193
- renderedDate: this.state.renderedDate.clone().subtract({
194
- months: 1
195
- })
196
- });
197
- };
198
70
  this.state = this.recalculateState(props.value || props.defaultValue);
199
71
  }
200
72
  componentDidMount() {
201
- var _this$props$reset, _this$props3;
202
73
  // we'll need to recalculate the state because the context value is
203
74
  // set at this point (and it might change locale & timezone)
204
75
  const initState = this.recalculateState(this.props.value || this.props.defaultValue);
205
76
  this.setState(initState);
206
- (_this$props$reset = (_this$props3 = this.props).reset) === null || _this$props$reset === void 0 ? void 0 : _this$props$reset.call(_this$props3, this.reset);
77
+ this.props.reset?.(this.reset);
207
78
  }
208
79
  componentDidUpdate(prevProps) {
209
80
  const valueChanged = prevProps.value !== this.props.value || prevProps.defaultValue !== this.props.defaultValue;
@@ -221,7 +92,6 @@ class DateTimeInput extends Component {
221
92
  if (dateStr) {
222
93
  const parsed = DateTime.parse(dateStr, this.locale(), this.timezone());
223
94
  if (parsed.isValid()) {
224
- var _this$state;
225
95
  if (doNotChangeTime && this.state.timeSelectValue) {
226
96
  // There is a selected time, adjust the parsed date to its value
227
97
  const timeParsed = DateTime.parse(this.state.timeSelectValue, this.locale(), this.timezone());
@@ -230,7 +100,7 @@ class DateTimeInput extends Component {
230
100
  if (doNotChangeDate && this.state.iso) {
231
101
  parsed.date(this.state.iso.date()).month(this.state.iso.month()).year(this.state.iso.year());
232
102
  }
233
- if (this.props.initialTimeForNewDate && !((_this$state = this.state) !== null && _this$state !== void 0 && _this$state.timeSelectValue)) {
103
+ if (this.props.initialTimeForNewDate && !this.state?.timeSelectValue) {
234
104
  const hour = Number(this.props.initialTimeForNewDate.slice(0, 2));
235
105
  const minute = Number(this.props.initialTimeForNewDate.slice(3, 5));
236
106
  if (isNaN(hour) || isNaN(minute)) {
@@ -250,7 +120,7 @@ class DateTimeInput extends Component {
250
120
  errorMsg = text ? {
251
121
  text,
252
122
  type: 'error'
253
- } : void 0;
123
+ } : undefined;
254
124
  return {
255
125
  iso: parsed.clone(),
256
126
  calendarSelectedDate: parsed.clone(),
@@ -278,17 +148,18 @@ class DateTimeInput extends Component {
278
148
  // if there is no date string clear TimeSelect value
279
149
  const clearTimeSelect = dateStr ? {} : {
280
150
  timeSelectValue: '',
281
- message: void 0
151
+ message: undefined
282
152
  };
283
153
  return {
284
- iso: void 0,
285
- calendarSelectedDate: void 0,
154
+ iso: undefined,
155
+ calendarSelectedDate: undefined,
286
156
  dateInputText: dateStr ? dateStr : '',
287
157
  renderedDate: DateTime.now(this.locale(), this.timezone()),
288
158
  dateInputTextChanged: false,
289
159
  ...clearTimeSelect
290
160
  };
291
161
  }
162
+ reset = () => this.setState(this.recalculateState());
292
163
  locale() {
293
164
  if (this.props.locale) {
294
165
  return this.props.locale;
@@ -323,10 +194,50 @@ class DateTimeInput extends Component {
323
194
  }
324
195
  return disabledDates(date.toISOString());
325
196
  }
197
+
198
+ // Called when the user enters text into dateInput
199
+ handleDateTextChange = (_event, date) => {
200
+ const dateParsed = this.tryParseDate(date.value);
201
+ this.setState({
202
+ dateInputText: date.value,
203
+ dateInputTextChanged: true,
204
+ calendarSelectedDate: dateParsed ? dateParsed : undefined,
205
+ renderedDate: dateParsed ? dateParsed.clone() : DateTime.now(this.locale(), this.timezone())
206
+ });
207
+ };
326
208
  tryParseDate(val) {
327
209
  const parsed = DateTime.parse(val, this.locale(), this.timezone());
328
210
  return parsed.isValid() ? parsed : null;
329
211
  }
212
+
213
+ // date is returned es a ISO string, like 2021-09-14T22:00:00.000Z
214
+ handleDayClick = (event, {
215
+ date
216
+ }) => {
217
+ const dateParsed = DateTime.parse(date, this.locale(), this.timezone());
218
+ this.updateStateBasedOnDateInput(dateParsed, event);
219
+ };
220
+ handleHideCalendar = event => {
221
+ // prevent event pooling https://reactjs.org/docs/legacy-event-pooling.html
222
+ // Remove if React 16 is no longer supported
223
+ event.persist();
224
+ // timeout is needed here because handleDayClick could be called in the same
225
+ // frame, and it updates calendarSelectedDate which is read in here.
226
+ setTimeout(() => {
227
+ if (event.key === 'Enter') {
228
+ // user pressed enter, use the selected value in the calendar
229
+ this.updateStateBasedOnDateInput(this.state.calendarSelectedDate, event);
230
+ } else {
231
+ // user clicked outside/tabbed away/pressed esc, try to use the value in dateInputText
232
+ const dateParsed = this.tryParseDate(this.state.dateInputText);
233
+ this.updateStateBasedOnDateInput(dateParsed, event);
234
+ }
235
+ this.setState({
236
+ isShowingCalendar: false,
237
+ dateInputTextChanged: false
238
+ });
239
+ }, 0);
240
+ };
330
241
  updateStateBasedOnDateInput(dateParsed, event) {
331
242
  let newState;
332
243
  if (dateParsed && this.state.timeSelectValue && (!this.state.dateInputText || this.state.dateInputText == '')) {
@@ -341,10 +252,112 @@ class DateTimeInput extends Component {
341
252
  // if the text in the dateInput is not readable display error
342
253
  newState = this.recalculateState(this.state.dateInputText, false, true);
343
254
  } else {
344
- newState = this.recalculateState(dateParsed === null || dateParsed === void 0 ? void 0 : dateParsed.toISOString(), false, true);
255
+ newState = this.recalculateState(dateParsed?.toISOString(), false, true);
345
256
  }
346
257
  this.changeStateIfNeeded(newState, event);
347
258
  }
259
+ updateStateBasedOnTimeSelect = (event, option) => {
260
+ // this.state.iso is undefined if date is invalid or not set.
261
+ // in this case recalculate with the dateInput's text which will result in
262
+ // an empty valid date (if isRequired is false) or an invalid date.
263
+ const newValue = this.state.iso ? option.value : this.state.dateInputText;
264
+ const newState = this.recalculateState(newValue, true, false);
265
+ this.changeStateIfNeeded(newState, event);
266
+ this.setState({
267
+ timeSelectValue: option.value
268
+ });
269
+ };
270
+ changeStateIfNeeded = (newState, e) => {
271
+ const dateStr = newState.dateInputText;
272
+ if (this.props.isRequired && !newState.iso || dateStr && dateStr.length > 0 && !newState.iso) {
273
+ const text = typeof this.props.invalidDateTimeMessage === 'function' ? this.props.invalidDateTimeMessage(dateStr ? dateStr : '') : this.props.invalidDateTimeMessage;
274
+ // eslint-disable-next-line no-param-reassign
275
+ newState.message = {
276
+ text: text,
277
+ type: 'error'
278
+ };
279
+ }
280
+ if (this.areDifferentDates(this.state.iso, newState.iso)) {
281
+ if (typeof this.props.onChange === 'function') {
282
+ const newDate = newState.iso?.toISOString();
283
+ // Timeout is needed here because users might change value in the
284
+ // onChange event lister, which might not execute properly
285
+ setTimeout(() => {
286
+ this.props.onChange?.(e, newDate);
287
+ }, 0);
288
+ }
289
+ }
290
+ this.setState(newState);
291
+ };
292
+ areDifferentDates = (d1, d2) => {
293
+ if (!d1 && !d2) {
294
+ return false;
295
+ }
296
+ return !d1 || !d2 || !d1.isSame(d2);
297
+ };
298
+ handleBlur = e => {
299
+ // when TABbing from the DateInput to TimeInput or visa-versa, the blur
300
+ // happens on the target before the relatedTarget gets focus.
301
+ // The timeout gives it a moment for that to happen
302
+ if (typeof this.props.onBlur === 'function') {
303
+ setTimeout(() => {
304
+ this.props.onBlur?.(e);
305
+ }, 0);
306
+ }
307
+ };
308
+ handleShowCalendar = _event => {
309
+ this.setState({
310
+ isShowingCalendar: true
311
+ });
312
+ };
313
+ handleSelectNextDay = _event => {
314
+ let toAlter;
315
+ if (this.state.calendarSelectedDate) {
316
+ toAlter = this.state.calendarSelectedDate.clone();
317
+ } else if (this.state.iso) {
318
+ toAlter = this.state.iso.clone();
319
+ } else {
320
+ toAlter = DateTime.now(this.locale(), this.timezone());
321
+ }
322
+ toAlter.add({
323
+ days: 1
324
+ });
325
+ this.setState({
326
+ calendarSelectedDate: toAlter,
327
+ renderedDate: toAlter.clone()
328
+ });
329
+ };
330
+ handleSelectPrevDay = _event => {
331
+ let toAlter;
332
+ if (this.state.calendarSelectedDate) {
333
+ toAlter = this.state.calendarSelectedDate.clone();
334
+ } else if (this.state.iso) {
335
+ toAlter = this.state.iso.clone();
336
+ } else {
337
+ toAlter = DateTime.now(this.locale(), this.timezone());
338
+ }
339
+ toAlter.subtract({
340
+ days: 1
341
+ });
342
+ this.setState({
343
+ calendarSelectedDate: toAlter,
344
+ renderedDate: toAlter.clone()
345
+ });
346
+ };
347
+ handleRenderNextMonth = _event => {
348
+ this.setState({
349
+ renderedDate: this.state.renderedDate.clone().add({
350
+ months: 1
351
+ })
352
+ });
353
+ };
354
+ handleRenderPrevMonth = _event => {
355
+ this.setState({
356
+ renderedDate: this.state.renderedDate.clone().subtract({
357
+ months: 1
358
+ })
359
+ });
360
+ };
348
361
  renderDays() {
349
362
  const renderedDate = this.state.renderedDate;
350
363
  // Sets it to the first local day of the week counting back from the start of the month.
@@ -427,36 +440,37 @@ class DateTimeInput extends Component {
427
440
  size: "small",
428
441
  withBackground: false,
429
442
  withBorder: false,
430
- renderIcon: type === 'prev' ? _IconArrowOpenStartSo || (_IconArrowOpenStartSo = _jsx(IconArrowOpenStartSolid, {
443
+ renderIcon: type === 'prev' ? _jsx(IconArrowOpenStartSolid, {
431
444
  color: "primary"
432
- })) : _IconArrowOpenEndSoli || (_IconArrowOpenEndSoli = _jsx(IconArrowOpenEndSolid, {
445
+ }) : _jsx(IconArrowOpenEndSolid, {
433
446
  color: "primary"
434
- })),
447
+ }),
435
448
  screenReaderLabel: type === 'prev' ? this.props.prevMonthLabel : this.props.nextMonthLabel
436
449
  });
437
450
  }
438
451
  render() {
439
- const _this$props4 = this.props,
440
- description = _this$props4.description,
441
- datePlaceholder = _this$props4.datePlaceholder,
442
- timePlaceholder = _this$props4.timePlaceholder,
443
- dateRenderLabel = _this$props4.dateRenderLabel,
444
- dateInputRef = _this$props4.dateInputRef,
445
- timeRenderLabel = _this$props4.timeRenderLabel,
446
- timeFormat = _this$props4.timeFormat,
447
- timeStep = _this$props4.timeStep,
448
- timeInputRef = _this$props4.timeInputRef,
449
- locale = _this$props4.locale,
450
- timezone = _this$props4.timezone,
451
- showMessages = _this$props4.showMessages,
452
- messages = _this$props4.messages,
453
- layout = _this$props4.layout,
454
- rowSpacing = _this$props4.rowSpacing,
455
- colSpacing = _this$props4.colSpacing,
456
- isRequired = _this$props4.isRequired,
457
- interaction = _this$props4.interaction,
458
- renderWeekdayLabels = _this$props4.renderWeekdayLabels,
459
- allowNonStepInput = _this$props4.allowNonStepInput;
452
+ const {
453
+ description,
454
+ datePlaceholder,
455
+ timePlaceholder,
456
+ dateRenderLabel,
457
+ dateInputRef,
458
+ timeRenderLabel,
459
+ timeFormat,
460
+ timeStep,
461
+ timeInputRef,
462
+ locale,
463
+ timezone,
464
+ showMessages,
465
+ messages,
466
+ layout,
467
+ rowSpacing,
468
+ colSpacing,
469
+ isRequired,
470
+ interaction,
471
+ renderWeekdayLabels,
472
+ allowNonStepInput
473
+ } = this.props;
460
474
  const allMessages = [...(showMessages && this.state.message ? [this.state.message] : []), ...(messages || [])];
461
475
  const hasError = allMessages.find(m => m.type === 'newError' || m.type === 'error');
462
476
  // if the component is in error state, create an empty error message to pass down to the subcomponents (DateInput and TimeInput) so they get a red outline and red required asterisk
@@ -522,23 +536,5 @@ class DateTimeInput extends Component {
522
536
  });
523
537
  }
524
538
  }
525
- _DateTimeInput = DateTimeInput;
526
- DateTimeInput.displayName = "DateTimeInput";
527
- // extra verbose localized date and time
528
- DateTimeInput.DEFAULT_MESSAGE_FORMAT = 'LLLL';
529
- DateTimeInput.allowedProps = allowedProps;
530
- DateTimeInput.defaultProps = {
531
- layout: 'inline',
532
- colSpacing: 'medium',
533
- rowSpacing: 'small',
534
- timeStep: 30,
535
- showMessages: true,
536
- messageFormat: _DateTimeInput.DEFAULT_MESSAGE_FORMAT,
537
- isRequired: false,
538
- dateFormat: 'LL',
539
- // Localized date with full month, e.g. "August 6, 2014"
540
- allowNonStepInput: false
541
- };
542
- DateTimeInput.contextType = ApplyLocaleContext;
543
539
  export default DateTimeInput;
544
540
  export { DateTimeInput };