@instructure/ui-date-input 10.18.2-snapshot-3 → 10.18.2-snapshot-5

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
- ## [10.18.2-snapshot-3](https://github.com/instructure/instructure-ui/compare/v10.18.1...v10.18.2-snapshot-3) (2025-06-03)
6
+ ## [10.18.2-snapshot-5](https://github.com/instructure/instructure-ui/compare/v10.18.1...v10.18.2-snapshot-5) (2025-06-03)
7
7
 
8
- **Note:** Version bump only for package @instructure/ui-date-input
8
+
9
+ ### Bug Fixes
10
+
11
+ * **ui-date-input:** make DateInput2 date parsing work in every locale and timezone ([7d2ed73](https://github.com/instructure/instructure-ui/commit/7d2ed732a4b8608b6fc29996e416b51ac25faf0c))
9
12
 
10
13
 
11
14
 
@@ -24,14 +24,14 @@ var _IconCalendarMonthLin, _IconArrowOpenEndSoli, _IconArrowOpenStartSo;
24
24
  * SOFTWARE.
25
25
  */
26
26
 
27
- import { useState, useEffect, useContext, forwardRef } from 'react';
27
+ import { useState, useEffect, forwardRef } from 'react';
28
28
  import { Calendar } from '@instructure/ui-calendar';
29
29
  import { IconButton } from '@instructure/ui-buttons';
30
30
  import { IconCalendarMonthLine, IconArrowOpenEndSolid, IconArrowOpenStartSolid } from '@instructure/ui-icons';
31
31
  import { Popover } from '@instructure/ui-popover';
32
32
  import { TextInput } from '@instructure/ui-text-input';
33
33
  import { callRenderProp, passthroughProps } from '@instructure/ui-react-utils';
34
- import { ApplyLocaleContext, Locale } from '@instructure/ui-i18n';
34
+ import { getLocale, getTimezone } from '@instructure/ui-i18n';
35
35
  import { propTypes } from './props';
36
36
  import { jsx as _jsx } from "@emotion/react/jsx-runtime";
37
37
  function parseLocaleDate(dateString = '', locale, timeZone) {
@@ -70,10 +70,6 @@ function parseLocaleDate(dateString = '', locale, timeZone) {
70
70
 
71
71
  // create utc date from year, month (zero indexed) and day
72
72
  const date = new Date(Date.UTC(year, month - 1, day));
73
- if (date.getMonth() !== month - 1 || date.getDate() !== day) {
74
- // Check if the Date object adjusts the values. If it does, the input is invalid.
75
- return null;
76
- }
77
73
 
78
74
  // Format date string in the provided timezone. The locale here is irrelevant, we only care about how to time is adjusted for the timezone.
79
75
  const parts = new Intl.DateTimeFormat('en-US', {
@@ -135,25 +131,8 @@ const DateInput2 = /*#__PURE__*/forwardRef(({
135
131
  inputRef,
136
132
  ...rest
137
133
  }, ref) => {
138
- const localeContext = useContext(ApplyLocaleContext);
139
- const getLocale = () => {
140
- if (locale) {
141
- return locale;
142
- } else if (localeContext.locale) {
143
- return localeContext.locale;
144
- }
145
- // default to the system's locale
146
- return Locale.browserLocale();
147
- };
148
- const getTimezone = () => {
149
- if (timezone) {
150
- return timezone;
151
- } else if (localeContext.timezone) {
152
- return localeContext.timezone;
153
- }
154
- // default to the system's timezone
155
- return Intl.DateTimeFormat().resolvedOptions().timeZone;
156
- };
134
+ const userLocale = locale || getLocale();
135
+ const userTimezone = timezone || getTimezone();
157
136
  const _useState = useState(messages || []),
158
137
  _useState2 = _slicedToArray(_useState, 2),
159
138
  inputMessages = _useState2[0],
@@ -181,23 +160,23 @@ const DateInput2 = /*#__PURE__*/forwardRef(({
181
160
  if (dateFormat) {
182
161
  if (typeof dateFormat === 'string') {
183
162
  // use dateFormat instead of the user locale
184
- date = parseLocaleDate(dateString, dateFormat, getTimezone());
163
+ date = parseLocaleDate(dateString, dateFormat, userTimezone);
185
164
  } else if (dateFormat.parser) {
186
165
  date = dateFormat.parser(dateString);
187
166
  }
188
167
  } else {
189
168
  // no dateFormat prop passed, use locale for formatting
190
- date = parseLocaleDate(dateString, getLocale(), getTimezone());
169
+ date = parseLocaleDate(dateString, userLocale, userTimezone);
191
170
  }
192
171
  return date ? [formatDate(date), date.toISOString()] : ['', ''];
193
172
  };
194
- const formatDate = (date, timeZone = getTimezone()) => {
173
+ const formatDate = (date, timeZone = userTimezone) => {
195
174
  // use formatter function if provided
196
175
  if (typeof dateFormat !== 'string' && dateFormat !== null && dateFormat !== void 0 && dateFormat.formatter) {
197
176
  return dateFormat.formatter(date);
198
177
  }
199
178
  // if dateFormat set to a locale, use that, otherwise default to the user's locale
200
- return date.toLocaleDateString(typeof dateFormat === 'string' ? dateFormat : getLocale(), {
179
+ return date.toLocaleDateString(typeof dateFormat === 'string' ? dateFormat : userLocale, {
201
180
  timeZone,
202
181
  calendar: 'gregory',
203
182
  numberingSystem: 'latn'
@@ -213,9 +192,9 @@ const DateInput2 = /*#__PURE__*/forwardRef(({
213
192
  };
214
193
 
215
194
  // Replace the matched number with the same number of dashes
216
- const year = `${exampleDate.getFullYear()}`;
217
- const month = `${exampleDate.getMonth() + 1}`;
218
- const day = `${exampleDate.getDate()}`;
195
+ const year = '2024';
196
+ const month = '9';
197
+ const day = '1';
219
198
  return formattedDate.replace(regex(year), match => 'Y'.repeat(match.length)).replace(regex(month), match => 'M'.repeat(match.length)).replace(regex(day), match => 'D'.repeat(match.length));
220
199
  };
221
200
  const handleInputChange = (e, newValue) => {
@@ -286,8 +265,8 @@ const DateInput2 = /*#__PURE__*/forwardRef(({
286
265
  selectedDate: selectedDate,
287
266
  disabledDates: disabledDates,
288
267
  visibleMonth: selectedDate,
289
- locale: getLocale(),
290
- timezone: getTimezone(),
268
+ locale: userLocale,
269
+ timezone: userTimezone,
291
270
  renderNextMonthButton: _jsx(IconButton, {
292
271
  size: "small",
293
272
  withBackground: false,
@@ -16,8 +16,8 @@ var _Popover = require("@instructure/ui-popover/lib/Popover");
16
16
  var _TextInput = require("@instructure/ui-text-input/lib/TextInput");
17
17
  var _callRenderProp = require("@instructure/ui-react-utils/lib/callRenderProp.js");
18
18
  var _passthroughProps = require("@instructure/ui-react-utils/lib/passthroughProps.js");
19
- var _ApplyLocaleContext = require("@instructure/ui-i18n/lib/ApplyLocale/ApplyLocaleContext.js");
20
- var _Locale = require("@instructure/ui-i18n/lib/Locale.js");
19
+ var _getLocale = require("@instructure/ui-i18n/lib/getLocale.js");
20
+ var _getTimezone = require("@instructure/ui-i18n/lib/getTimezone.js");
21
21
  var _props = require("./props");
22
22
  var _jsxRuntime = require("@emotion/react/jsx-runtime");
23
23
  var _IconCalendarMonthLin, _IconArrowOpenEndSoli, _IconArrowOpenStartSo;
@@ -80,10 +80,6 @@ function parseLocaleDate(dateString = '', locale, timeZone) {
80
80
 
81
81
  // create utc date from year, month (zero indexed) and day
82
82
  const date = new Date(Date.UTC(year, month - 1, day));
83
- if (date.getMonth() !== month - 1 || date.getDate() !== day) {
84
- // Check if the Date object adjusts the values. If it does, the input is invalid.
85
- return null;
86
- }
87
83
 
88
84
  // Format date string in the provided timezone. The locale here is irrelevant, we only care about how to time is adjusted for the timezone.
89
85
  const parts = new Intl.DateTimeFormat('en-US', {
@@ -145,25 +141,8 @@ const DateInput2 = exports.DateInput2 = /*#__PURE__*/(0, _react.forwardRef)(({
145
141
  inputRef,
146
142
  ...rest
147
143
  }, ref) => {
148
- const localeContext = (0, _react.useContext)(_ApplyLocaleContext.ApplyLocaleContext);
149
- const getLocale = () => {
150
- if (locale) {
151
- return locale;
152
- } else if (localeContext.locale) {
153
- return localeContext.locale;
154
- }
155
- // default to the system's locale
156
- return _Locale.Locale.browserLocale();
157
- };
158
- const getTimezone = () => {
159
- if (timezone) {
160
- return timezone;
161
- } else if (localeContext.timezone) {
162
- return localeContext.timezone;
163
- }
164
- // default to the system's timezone
165
- return Intl.DateTimeFormat().resolvedOptions().timeZone;
166
- };
144
+ const userLocale = locale || (0, _getLocale.getLocale)();
145
+ const userTimezone = timezone || (0, _getTimezone.getTimezone)();
167
146
  const _useState = (0, _react.useState)(messages || []),
168
147
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
169
148
  inputMessages = _useState2[0],
@@ -191,23 +170,23 @@ const DateInput2 = exports.DateInput2 = /*#__PURE__*/(0, _react.forwardRef)(({
191
170
  if (dateFormat) {
192
171
  if (typeof dateFormat === 'string') {
193
172
  // use dateFormat instead of the user locale
194
- date = parseLocaleDate(dateString, dateFormat, getTimezone());
173
+ date = parseLocaleDate(dateString, dateFormat, userTimezone);
195
174
  } else if (dateFormat.parser) {
196
175
  date = dateFormat.parser(dateString);
197
176
  }
198
177
  } else {
199
178
  // no dateFormat prop passed, use locale for formatting
200
- date = parseLocaleDate(dateString, getLocale(), getTimezone());
179
+ date = parseLocaleDate(dateString, userLocale, userTimezone);
201
180
  }
202
181
  return date ? [formatDate(date), date.toISOString()] : ['', ''];
203
182
  };
204
- const formatDate = (date, timeZone = getTimezone()) => {
183
+ const formatDate = (date, timeZone = userTimezone) => {
205
184
  // use formatter function if provided
206
185
  if (typeof dateFormat !== 'string' && dateFormat !== null && dateFormat !== void 0 && dateFormat.formatter) {
207
186
  return dateFormat.formatter(date);
208
187
  }
209
188
  // if dateFormat set to a locale, use that, otherwise default to the user's locale
210
- return date.toLocaleDateString(typeof dateFormat === 'string' ? dateFormat : getLocale(), {
189
+ return date.toLocaleDateString(typeof dateFormat === 'string' ? dateFormat : userLocale, {
211
190
  timeZone,
212
191
  calendar: 'gregory',
213
192
  numberingSystem: 'latn'
@@ -223,9 +202,9 @@ const DateInput2 = exports.DateInput2 = /*#__PURE__*/(0, _react.forwardRef)(({
223
202
  };
224
203
 
225
204
  // Replace the matched number with the same number of dashes
226
- const year = `${exampleDate.getFullYear()}`;
227
- const month = `${exampleDate.getMonth() + 1}`;
228
- const day = `${exampleDate.getDate()}`;
205
+ const year = '2024';
206
+ const month = '9';
207
+ const day = '1';
229
208
  return formattedDate.replace(regex(year), match => 'Y'.repeat(match.length)).replace(regex(month), match => 'M'.repeat(match.length)).replace(regex(day), match => 'D'.repeat(match.length));
230
209
  };
231
210
  const handleInputChange = (e, newValue) => {
@@ -296,8 +275,8 @@ const DateInput2 = exports.DateInput2 = /*#__PURE__*/(0, _react.forwardRef)(({
296
275
  selectedDate: selectedDate,
297
276
  disabledDates: disabledDates,
298
277
  visibleMonth: selectedDate,
299
- locale: getLocale(),
300
- timezone: getTimezone(),
278
+ locale: userLocale,
279
+ timezone: userTimezone,
301
280
  renderNextMonthButton: (0, _jsxRuntime.jsx)(_IconButton.IconButton, {
302
281
  size: "small",
303
282
  withBackground: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/ui-date-input",
3
- "version": "10.18.2-snapshot-3",
3
+ "version": "10.18.2-snapshot-5",
4
4
  "description": "A UI component library made by Instructure Inc.",
5
5
  "author": "Instructure, Inc. Engineering and Product Design",
6
6
  "module": "./es/index.js",
@@ -23,11 +23,11 @@
23
23
  },
24
24
  "license": "MIT",
25
25
  "devDependencies": {
26
- "@instructure/ui-axe-check": "10.18.2-snapshot-3",
27
- "@instructure/ui-babel-preset": "10.18.2-snapshot-3",
28
- "@instructure/ui-buttons": "10.18.2-snapshot-3",
29
- "@instructure/ui-scripts": "10.18.2-snapshot-3",
30
- "@instructure/ui-test-utils": "10.18.2-snapshot-3",
26
+ "@instructure/ui-axe-check": "10.18.2-snapshot-5",
27
+ "@instructure/ui-babel-preset": "10.18.2-snapshot-5",
28
+ "@instructure/ui-buttons": "10.18.2-snapshot-5",
29
+ "@instructure/ui-scripts": "10.18.2-snapshot-5",
30
+ "@instructure/ui-test-utils": "10.18.2-snapshot-5",
31
31
  "@testing-library/jest-dom": "^6.6.3",
32
32
  "@testing-library/react": "^16.0.1",
33
33
  "@testing-library/user-event": "^14.5.2",
@@ -35,20 +35,20 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@babel/runtime": "^7.26.0",
38
- "@instructure/emotion": "10.18.2-snapshot-3",
39
- "@instructure/shared-types": "10.18.2-snapshot-3",
40
- "@instructure/ui-calendar": "10.18.2-snapshot-3",
41
- "@instructure/ui-form-field": "10.18.2-snapshot-3",
42
- "@instructure/ui-i18n": "10.18.2-snapshot-3",
43
- "@instructure/ui-icons": "10.18.2-snapshot-3",
44
- "@instructure/ui-popover": "10.18.2-snapshot-3",
45
- "@instructure/ui-position": "10.18.2-snapshot-3",
46
- "@instructure/ui-prop-types": "10.18.2-snapshot-3",
47
- "@instructure/ui-react-utils": "10.18.2-snapshot-3",
48
- "@instructure/ui-selectable": "10.18.2-snapshot-3",
49
- "@instructure/ui-testable": "10.18.2-snapshot-3",
50
- "@instructure/ui-text-input": "10.18.2-snapshot-3",
51
- "@instructure/ui-utils": "10.18.2-snapshot-3",
38
+ "@instructure/emotion": "10.18.2-snapshot-5",
39
+ "@instructure/shared-types": "10.18.2-snapshot-5",
40
+ "@instructure/ui-calendar": "10.18.2-snapshot-5",
41
+ "@instructure/ui-form-field": "10.18.2-snapshot-5",
42
+ "@instructure/ui-i18n": "10.18.2-snapshot-5",
43
+ "@instructure/ui-icons": "10.18.2-snapshot-5",
44
+ "@instructure/ui-popover": "10.18.2-snapshot-5",
45
+ "@instructure/ui-position": "10.18.2-snapshot-5",
46
+ "@instructure/ui-prop-types": "10.18.2-snapshot-5",
47
+ "@instructure/ui-react-utils": "10.18.2-snapshot-5",
48
+ "@instructure/ui-selectable": "10.18.2-snapshot-5",
49
+ "@instructure/ui-testable": "10.18.2-snapshot-5",
50
+ "@instructure/ui-text-input": "10.18.2-snapshot-5",
51
+ "@instructure/ui-utils": "10.18.2-snapshot-5",
52
52
  "moment-timezone": "^0.5.45",
53
53
  "prop-types": "^15.8.1"
54
54
  },
@@ -25,7 +25,6 @@
25
25
  import {
26
26
  useState,
27
27
  useEffect,
28
- useContext,
29
28
  forwardRef,
30
29
  ForwardedRef,
31
30
  ValidationMap
@@ -41,8 +40,7 @@ import {
41
40
  import { Popover } from '@instructure/ui-popover'
42
41
  import { TextInput } from '@instructure/ui-text-input'
43
42
  import { callRenderProp, passthroughProps } from '@instructure/ui-react-utils'
44
-
45
- import { ApplyLocaleContext, Locale } from '@instructure/ui-i18n'
43
+ import { getLocale, getTimezone } from '@instructure/ui-i18n'
46
44
 
47
45
  import { propTypes } from './props'
48
46
  import type { DateInput2Props } from './props'
@@ -93,11 +91,6 @@ function parseLocaleDate(
93
91
  // create utc date from year, month (zero indexed) and day
94
92
  const date = new Date(Date.UTC(year, month - 1, day))
95
93
 
96
- if (date.getMonth() !== month - 1 || date.getDate() !== day) {
97
- // Check if the Date object adjusts the values. If it does, the input is invalid.
98
- return null
99
- }
100
-
101
94
  // Format date string in the provided timezone. The locale here is irrelevant, we only care about how to time is adjusted for the timezone.
102
95
  const parts = new Intl.DateTimeFormat('en-US', {
103
96
  timeZone,
@@ -166,27 +159,8 @@ const DateInput2 = forwardRef(
166
159
  }: DateInput2Props,
167
160
  ref: ForwardedRef<TextInput>
168
161
  ) => {
169
- const localeContext = useContext(ApplyLocaleContext)
170
-
171
- const getLocale = () => {
172
- if (locale) {
173
- return locale
174
- } else if (localeContext.locale) {
175
- return localeContext.locale
176
- }
177
- // default to the system's locale
178
- return Locale.browserLocale()
179
- }
180
-
181
- const getTimezone = () => {
182
- if (timezone) {
183
- return timezone
184
- } else if (localeContext.timezone) {
185
- return localeContext.timezone
186
- }
187
- // default to the system's timezone
188
- return Intl.DateTimeFormat().resolvedOptions().timeZone
189
- }
162
+ const userLocale = locale || getLocale()
163
+ const userTimezone = timezone || getTimezone()
190
164
 
191
165
  const [inputMessages, setInputMessages] = useState<FormMessage[]>(
192
166
  messages || []
@@ -213,20 +187,20 @@ const DateInput2 = forwardRef(
213
187
  if (dateFormat) {
214
188
  if (typeof dateFormat === 'string') {
215
189
  // use dateFormat instead of the user locale
216
- date = parseLocaleDate(dateString, dateFormat, getTimezone())
190
+ date = parseLocaleDate(dateString, dateFormat, userTimezone)
217
191
  } else if (dateFormat.parser) {
218
192
  date = dateFormat.parser(dateString)
219
193
  }
220
194
  } else {
221
195
  // no dateFormat prop passed, use locale for formatting
222
- date = parseLocaleDate(dateString, getLocale(), getTimezone())
196
+ date = parseLocaleDate(dateString, userLocale, userTimezone)
223
197
  }
224
198
  return date ? [formatDate(date), date.toISOString()] : ['', '']
225
199
  }
226
200
 
227
201
  const formatDate = (
228
202
  date: Date,
229
- timeZone: string = getTimezone()
203
+ timeZone: string = userTimezone
230
204
  ): string => {
231
205
  // use formatter function if provided
232
206
  if (typeof dateFormat !== 'string' && dateFormat?.formatter) {
@@ -234,7 +208,7 @@ const DateInput2 = forwardRef(
234
208
  }
235
209
  // if dateFormat set to a locale, use that, otherwise default to the user's locale
236
210
  return date.toLocaleDateString(
237
- typeof dateFormat === 'string' ? dateFormat : getLocale(),
211
+ typeof dateFormat === 'string' ? dateFormat : userLocale,
238
212
  {
239
213
  timeZone,
240
214
  calendar: 'gregory',
@@ -253,9 +227,9 @@ const DateInput2 = forwardRef(
253
227
  }
254
228
 
255
229
  // Replace the matched number with the same number of dashes
256
- const year = `${exampleDate.getFullYear()}`
257
- const month = `${exampleDate.getMonth() + 1}`
258
- const day = `${exampleDate.getDate()}`
230
+ const year = '2024'
231
+ const month = '9'
232
+ const day = '1'
259
233
  return formattedDate
260
234
  .replace(regex(year), (match) => 'Y'.repeat(match.length))
261
235
  .replace(regex(month), (match) => 'M'.repeat(match.length))
@@ -340,8 +314,8 @@ const DateInput2 = forwardRef(
340
314
  selectedDate={selectedDate}
341
315
  disabledDates={disabledDates}
342
316
  visibleMonth={selectedDate}
343
- locale={getLocale()}
344
- timezone={getTimezone()}
317
+ locale={userLocale}
318
+ timezone={userTimezone}
345
319
  renderNextMonthButton={
346
320
  <IconButton
347
321
  size="small"