@instructure/ui-date-input 9.6.0 → 10.0.1-pr-snapshot-1723800180253

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,23 +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
- # [9.6.0](https://github.com/instructure/instructure-ui/compare/v9.5.2...v9.6.0) (2024-08-14)
7
-
8
-
9
- ### Features
10
-
11
- * **ui-calendar,ui-date-input:** improve DateInput2 onChange callback, add date formatting option, extend docs ([4e2c23c](https://github.com/instructure/instructure-ui/commit/4e2c23c3288885e49030f1f471d61b2fed29b54c))
12
-
6
+ ## [10.0.1-pr-snapshot-1723800180253](https://github.com/instructure/instructure-ui/compare/v10.0.0...v10.0.1-pr-snapshot-1723800180253) (2024-08-16)
13
7
 
8
+ **Note:** Version bump only for package @instructure/ui-date-input
14
9
 
15
10
 
16
11
 
17
- ## [9.5.2](https://github.com/instructure/instructure-ui/compare/v9.5.1...v9.5.2) (2024-08-05)
18
12
 
19
13
 
20
- ### Bug Fixes
14
+ # [10.0.0](https://github.com/instructure/instructure-ui/compare/v9.5.1...v10.0.0) (2024-07-31)
21
15
 
22
- * **ui-calendar,ui-date-input:** fix year picker for non latin based locales; return iso date string in onRequestValidateDate ([d7df0e8](https://github.com/instructure/instructure-ui/commit/d7df0e8d9fc0656e877bd243d9858dc3e5a47198))
16
+ **Note:** Version bump only for package @instructure/ui-date-input
23
17
 
24
18
 
25
19
 
@@ -26,6 +26,7 @@ var _IconCalendarMonthLin, _IconArrowOpenEndSoli, _IconArrowOpenStartSo;
26
26
 
27
27
  /** @jsx jsx */
28
28
  import { useState, useEffect, useContext } from 'react';
29
+ import moment from 'moment-timezone';
29
30
  import { Calendar } from '@instructure/ui-calendar';
30
31
  import { IconButton } from '@instructure/ui-buttons';
31
32
  import { IconCalendarMonthLine, IconArrowOpenEndSolid, IconArrowOpenStartSolid } from '@instructure/ui-icons';
@@ -35,17 +36,11 @@ import { passthroughProps } from '@instructure/ui-react-utils';
35
36
  import { ApplyLocaleContext, Locale } from '@instructure/ui-i18n';
36
37
  import { jsx } from '@instructure/emotion';
37
38
  import { propTypes } from './props';
38
- function parseDate(dateString) {
39
- const date = new Date(dateString);
40
- return isNaN(date.getTime()) ? '' : date.toISOString();
39
+ function isValidDate(dateString) {
40
+ return !isNaN(new Date(dateString).getTime());
41
41
  }
42
- function defaultDateFormatter(dateString, locale, timezone) {
43
- return new Date(dateString).toLocaleDateString(locale, {
44
- month: 'long',
45
- year: 'numeric',
46
- day: 'numeric',
47
- timeZone: timezone
48
- });
42
+ function isValidMomentDate(dateString, locale, timezone) {
43
+ return moment.tz(dateString, [moment.ISO_8601, 'llll', 'LLLL', 'lll', 'LLL', 'll', 'LL', 'l', 'L'], locale, true, timezone).isValid();
49
44
  }
50
45
 
51
46
  /**
@@ -71,8 +66,6 @@ const DateInput2 = ({
71
66
  locale,
72
67
  timezone,
73
68
  placeholder,
74
- formatDate = defaultDateFormatter,
75
- // margin, TODO enable this prop
76
69
  ...rest
77
70
  }) => {
78
71
  const _useState = useState(''),
@@ -89,45 +82,39 @@ const DateInput2 = ({
89
82
  setShowPopover = _useState6[1];
90
83
  const localeContext = useContext(ApplyLocaleContext);
91
84
  useEffect(() => {
92
- // when `value` is changed, validation removes the error message if passes
93
- // but it's NOT adding error message if validation fails for better UX
94
85
  validateInput(true);
95
86
  }, [value]);
96
87
  useEffect(() => {
97
88
  setInputMessages(messages || []);
98
89
  }, [messages]);
99
- useEffect(() => {
100
- setSelectedDate(parseDate(value || ''));
101
- }, []);
102
- const handleInputChange = (e, newValue, parsedDate = '') => {
103
- // blur event formats the input which shouldn't trigger parsing
104
- if (e.type !== 'blur') {
105
- setSelectedDate(parseDate(newValue));
106
- }
107
- onChange === null || onChange === void 0 ? void 0 : onChange(e, newValue, parsedDate);
90
+ const handleInputChange = (e, value) => {
91
+ onChange === null || onChange === void 0 ? void 0 : onChange(e, value);
108
92
  };
109
93
  const handleDateSelected = (dateString, _momentDate, e) => {
110
- const formattedDate = formatDate(dateString, getLocale(), getTimezone());
111
- const parsedDate = parseDate(dateString);
112
- setSelectedDate(parsedDate);
113
- handleInputChange(e, formattedDate, parsedDate);
94
+ const formattedDate = new Date(dateString).toLocaleDateString(getLocale(), {
95
+ month: 'long',
96
+ year: 'numeric',
97
+ day: 'numeric',
98
+ timeZone: getTimezone()
99
+ });
100
+ handleInputChange(e, formattedDate);
114
101
  setShowPopover(false);
115
- onRequestValidateDate === null || onRequestValidateDate === void 0 ? void 0 : onRequestValidateDate(dateString, true);
102
+ onRequestValidateDate === null || onRequestValidateDate === void 0 ? void 0 : onRequestValidateDate(formattedDate, true);
116
103
  };
117
-
118
- // onlyRemoveError is used to remove the error msg immediately when the user inputs a valid date (and don't wait for blur event)
119
104
  const validateInput = (onlyRemoveError = false) => {
120
- // don't validate empty input
121
- if (!value || parseDate(value) || selectedDate) {
105
+ // TODO `isValidDate` and `isValidMomentDate` basically have the same functionality but the latter is a bit more strict (e.g.: `33` is only valid in `isValidMomentDate`)
106
+ // in the future we should get rid of moment but currently Calendar is using it for validation too so we can only remove it simultaneously
107
+ // otherwise DateInput could pass invalid dates to Calendar and break it
108
+ if (isValidDate(value || '') && isValidMomentDate(value || '', getLocale(), getTimezone()) || value === '') {
109
+ setSelectedDate(value || '');
122
110
  setInputMessages(messages || []);
123
111
  return true;
124
112
  }
125
- // only show error if there is no user provided validation callback
126
- if (!onlyRemoveError && typeof invalidDateErrorMessage === 'string' && !onRequestValidateDate) {
127
- setInputMessages([{
113
+ if (!onlyRemoveError && typeof invalidDateErrorMessage === 'string') {
114
+ setInputMessages(messages => [{
128
115
  type: 'error',
129
116
  text: invalidDateErrorMessage
130
- }]);
117
+ }, ...messages]);
131
118
  }
132
119
  return false;
133
120
  };
@@ -150,15 +137,19 @@ const DateInput2 = ({
150
137
  };
151
138
  const handleBlur = e => {
152
139
  const isInputValid = validateInput(false);
153
- if (isInputValid && selectedDate) {
154
- const formattedDate = formatDate(selectedDate, getLocale(), getTimezone());
155
- handleInputChange(e, formattedDate, selectedDate);
140
+ if (isInputValid && value) {
141
+ const formattedDate = new Date(value).toLocaleDateString(getLocale(), {
142
+ month: 'long',
143
+ year: 'numeric',
144
+ day: 'numeric',
145
+ timeZone: getTimezone()
146
+ });
147
+ handleInputChange(e, formattedDate);
156
148
  }
157
149
  onRequestValidateDate === null || onRequestValidateDate === void 0 ? void 0 : onRequestValidateDate(value, isInputValid);
158
150
  onBlur === null || onBlur === void 0 ? void 0 : onBlur(e);
159
151
  };
160
152
  return jsx(TextInput, Object.assign({}, passthroughProps(rest), {
161
- // margin={'large'} TODO add this prop to TextInput
162
153
  renderLabel: renderLabel,
163
154
  onChange: handleInputChange,
164
155
  onBlur: handleBlur,
@@ -191,8 +182,8 @@ const DateInput2 = ({
191
182
  onDateSelected: handleDateSelected,
192
183
  selectedDate: selectedDate,
193
184
  visibleMonth: selectedDate,
194
- locale: getLocale(),
195
- timezone: getTimezone(),
185
+ locale: locale,
186
+ timezone: timezone,
196
187
  role: "listbox",
197
188
  renderNextMonthButton: jsx(IconButton, {
198
189
  size: "small",
@@ -44,7 +44,6 @@ const propTypes = {
44
44
  invalidDateErrorMessage: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
45
45
  locale: PropTypes.string,
46
46
  timezone: PropTypes.string,
47
- withYearPicker: PropTypes.object,
48
- formatDate: PropTypes.func
47
+ withYearPicker: PropTypes.object
49
48
  };
50
49
  export { propTypes };
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.default = exports.DateInput2 = void 0;
8
8
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
9
  var _react = require("react");
10
+ var _momentTimezone = _interopRequireDefault(require("moment-timezone"));
10
11
  var _Calendar = require("@instructure/ui-calendar/lib/Calendar");
11
12
  var _IconButton = require("@instructure/ui-buttons/lib/IconButton");
12
13
  var _IconCalendarMonthLine = require("@instructure/ui-icons/lib/IconCalendarMonthLine.js");
@@ -44,17 +45,11 @@ var _IconCalendarMonthLin, _IconArrowOpenEndSoli, _IconArrowOpenStartSo;
44
45
  * SOFTWARE.
45
46
  */
46
47
  /** @jsx jsx */
47
- function parseDate(dateString) {
48
- const date = new Date(dateString);
49
- return isNaN(date.getTime()) ? '' : date.toISOString();
48
+ function isValidDate(dateString) {
49
+ return !isNaN(new Date(dateString).getTime());
50
50
  }
51
- function defaultDateFormatter(dateString, locale, timezone) {
52
- return new Date(dateString).toLocaleDateString(locale, {
53
- month: 'long',
54
- year: 'numeric',
55
- day: 'numeric',
56
- timeZone: timezone
57
- });
51
+ function isValidMomentDate(dateString, locale, timezone) {
52
+ return _momentTimezone.default.tz(dateString, [_momentTimezone.default.ISO_8601, 'llll', 'LLLL', 'lll', 'LLL', 'll', 'LL', 'l', 'L'], locale, true, timezone).isValid();
58
53
  }
59
54
 
60
55
  /**
@@ -80,8 +75,6 @@ const DateInput2 = ({
80
75
  locale,
81
76
  timezone,
82
77
  placeholder,
83
- formatDate = defaultDateFormatter,
84
- // margin, TODO enable this prop
85
78
  ...rest
86
79
  }) => {
87
80
  const _useState = (0, _react.useState)(''),
@@ -98,45 +91,39 @@ const DateInput2 = ({
98
91
  setShowPopover = _useState6[1];
99
92
  const localeContext = (0, _react.useContext)(_ApplyLocaleContext.ApplyLocaleContext);
100
93
  (0, _react.useEffect)(() => {
101
- // when `value` is changed, validation removes the error message if passes
102
- // but it's NOT adding error message if validation fails for better UX
103
94
  validateInput(true);
104
95
  }, [value]);
105
96
  (0, _react.useEffect)(() => {
106
97
  setInputMessages(messages || []);
107
98
  }, [messages]);
108
- (0, _react.useEffect)(() => {
109
- setSelectedDate(parseDate(value || ''));
110
- }, []);
111
- const handleInputChange = (e, newValue, parsedDate = '') => {
112
- // blur event formats the input which shouldn't trigger parsing
113
- if (e.type !== 'blur') {
114
- setSelectedDate(parseDate(newValue));
115
- }
116
- onChange === null || onChange === void 0 ? void 0 : onChange(e, newValue, parsedDate);
99
+ const handleInputChange = (e, value) => {
100
+ onChange === null || onChange === void 0 ? void 0 : onChange(e, value);
117
101
  };
118
102
  const handleDateSelected = (dateString, _momentDate, e) => {
119
- const formattedDate = formatDate(dateString, getLocale(), getTimezone());
120
- const parsedDate = parseDate(dateString);
121
- setSelectedDate(parsedDate);
122
- handleInputChange(e, formattedDate, parsedDate);
103
+ const formattedDate = new Date(dateString).toLocaleDateString(getLocale(), {
104
+ month: 'long',
105
+ year: 'numeric',
106
+ day: 'numeric',
107
+ timeZone: getTimezone()
108
+ });
109
+ handleInputChange(e, formattedDate);
123
110
  setShowPopover(false);
124
- onRequestValidateDate === null || onRequestValidateDate === void 0 ? void 0 : onRequestValidateDate(dateString, true);
111
+ onRequestValidateDate === null || onRequestValidateDate === void 0 ? void 0 : onRequestValidateDate(formattedDate, true);
125
112
  };
126
-
127
- // onlyRemoveError is used to remove the error msg immediately when the user inputs a valid date (and don't wait for blur event)
128
113
  const validateInput = (onlyRemoveError = false) => {
129
- // don't validate empty input
130
- if (!value || parseDate(value) || selectedDate) {
114
+ // TODO `isValidDate` and `isValidMomentDate` basically have the same functionality but the latter is a bit more strict (e.g.: `33` is only valid in `isValidMomentDate`)
115
+ // in the future we should get rid of moment but currently Calendar is using it for validation too so we can only remove it simultaneously
116
+ // otherwise DateInput could pass invalid dates to Calendar and break it
117
+ if (isValidDate(value || '') && isValidMomentDate(value || '', getLocale(), getTimezone()) || value === '') {
118
+ setSelectedDate(value || '');
131
119
  setInputMessages(messages || []);
132
120
  return true;
133
121
  }
134
- // only show error if there is no user provided validation callback
135
- if (!onlyRemoveError && typeof invalidDateErrorMessage === 'string' && !onRequestValidateDate) {
136
- setInputMessages([{
122
+ if (!onlyRemoveError && typeof invalidDateErrorMessage === 'string') {
123
+ setInputMessages(messages => [{
137
124
  type: 'error',
138
125
  text: invalidDateErrorMessage
139
- }]);
126
+ }, ...messages]);
140
127
  }
141
128
  return false;
142
129
  };
@@ -159,15 +146,19 @@ const DateInput2 = ({
159
146
  };
160
147
  const handleBlur = e => {
161
148
  const isInputValid = validateInput(false);
162
- if (isInputValid && selectedDate) {
163
- const formattedDate = formatDate(selectedDate, getLocale(), getTimezone());
164
- handleInputChange(e, formattedDate, selectedDate);
149
+ if (isInputValid && value) {
150
+ const formattedDate = new Date(value).toLocaleDateString(getLocale(), {
151
+ month: 'long',
152
+ year: 'numeric',
153
+ day: 'numeric',
154
+ timeZone: getTimezone()
155
+ });
156
+ handleInputChange(e, formattedDate);
165
157
  }
166
158
  onRequestValidateDate === null || onRequestValidateDate === void 0 ? void 0 : onRequestValidateDate(value, isInputValid);
167
159
  onBlur === null || onBlur === void 0 ? void 0 : onBlur(e);
168
160
  };
169
161
  return (0, _emotion.jsx)(_TextInput.TextInput, Object.assign({}, (0, _passthroughProps.passthroughProps)(rest), {
170
- // margin={'large'} TODO add this prop to TextInput
171
162
  renderLabel: renderLabel,
172
163
  onChange: handleInputChange,
173
164
  onBlur: handleBlur,
@@ -200,8 +191,8 @@ const DateInput2 = ({
200
191
  onDateSelected: handleDateSelected,
201
192
  selectedDate: selectedDate,
202
193
  visibleMonth: selectedDate,
203
- locale: getLocale(),
204
- timezone: getTimezone(),
194
+ locale: locale,
195
+ timezone: timezone,
205
196
  role: "listbox",
206
197
  renderNextMonthButton: (0, _emotion.jsx)(_IconButton.IconButton, {
207
198
  size: "small",
@@ -51,6 +51,5 @@ const propTypes = exports.propTypes = {
51
51
  invalidDateErrorMessage: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.string]),
52
52
  locale: _propTypes.default.string,
53
53
  timezone: _propTypes.default.string,
54
- withYearPicker: _propTypes.default.object,
55
- formatDate: _propTypes.default.func
54
+ withYearPicker: _propTypes.default.object
56
55
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/ui-date-input",
3
- "version": "9.6.0",
3
+ "version": "10.0.1-pr-snapshot-1723800180253",
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": "9.6.0",
27
- "@instructure/ui-babel-preset": "9.6.0",
28
- "@instructure/ui-buttons": "9.6.0",
29
- "@instructure/ui-scripts": "9.6.0",
30
- "@instructure/ui-test-utils": "9.6.0",
26
+ "@instructure/ui-axe-check": "10.0.1-pr-snapshot-1723800180253",
27
+ "@instructure/ui-babel-preset": "10.0.1-pr-snapshot-1723800180253",
28
+ "@instructure/ui-buttons": "10.0.1-pr-snapshot-1723800180253",
29
+ "@instructure/ui-scripts": "10.0.1-pr-snapshot-1723800180253",
30
+ "@instructure/ui-test-utils": "10.0.1-pr-snapshot-1723800180253",
31
31
  "@testing-library/jest-dom": "^6.4.6",
32
32
  "@testing-library/react": "^15.0.7",
33
33
  "@testing-library/user-event": "^14.5.2",
@@ -35,20 +35,20 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@babel/runtime": "^7.24.5",
38
- "@instructure/emotion": "9.6.0",
39
- "@instructure/shared-types": "9.6.0",
40
- "@instructure/ui-calendar": "9.6.0",
41
- "@instructure/ui-form-field": "9.6.0",
42
- "@instructure/ui-i18n": "9.6.0",
43
- "@instructure/ui-icons": "9.6.0",
44
- "@instructure/ui-popover": "9.6.0",
45
- "@instructure/ui-position": "9.6.0",
46
- "@instructure/ui-prop-types": "9.6.0",
47
- "@instructure/ui-react-utils": "9.6.0",
48
- "@instructure/ui-selectable": "9.6.0",
49
- "@instructure/ui-testable": "9.6.0",
50
- "@instructure/ui-text-input": "9.6.0",
51
- "@instructure/ui-utils": "9.6.0",
38
+ "@instructure/emotion": "10.0.1-pr-snapshot-1723800180253",
39
+ "@instructure/shared-types": "10.0.1-pr-snapshot-1723800180253",
40
+ "@instructure/ui-calendar": "10.0.1-pr-snapshot-1723800180253",
41
+ "@instructure/ui-form-field": "10.0.1-pr-snapshot-1723800180253",
42
+ "@instructure/ui-i18n": "10.0.1-pr-snapshot-1723800180253",
43
+ "@instructure/ui-icons": "10.0.1-pr-snapshot-1723800180253",
44
+ "@instructure/ui-popover": "10.0.1-pr-snapshot-1723800180253",
45
+ "@instructure/ui-position": "10.0.1-pr-snapshot-1723800180253",
46
+ "@instructure/ui-prop-types": "10.0.1-pr-snapshot-1723800180253",
47
+ "@instructure/ui-react-utils": "10.0.1-pr-snapshot-1723800180253",
48
+ "@instructure/ui-selectable": "10.0.1-pr-snapshot-1723800180253",
49
+ "@instructure/ui-testable": "10.0.1-pr-snapshot-1723800180253",
50
+ "@instructure/ui-text-input": "10.0.1-pr-snapshot-1723800180253",
51
+ "@instructure/ui-utils": "10.0.1-pr-snapshot-1723800180253",
52
52
  "moment-timezone": "^0.5.45",
53
53
  "prop-types": "^15.8.1"
54
54
  },
@@ -113,11 +113,7 @@ This component is an updated version of [`DateInput`](/#DateInput) that's easier
113
113
  render(<Example />)
114
114
  ```
115
115
 
116
- ### Date validation
117
-
118
- By default `DateInput2` only does date validation if the `invalidDateErrorMessage` prop is provided. This uses the browser's `Date` object to try an parse the user provided date and displays the error message if it fails. Validation is only triggered on the blur event of the input field.
119
-
120
- If you want to do a more complex validation than the above (e.g. only allow a subset of dates) you can use the `onRequestValidateDate` prop to pass a validation function. This function will run on blur or on selecting the date from the picker. The result of the internal validation will be passed to this function. Then you have to set the error messages accordingly. Check the following example for more details:
116
+ ### With custom validation
121
117
 
122
118
  ```js
123
119
  ---
@@ -167,101 +163,3 @@ const Example = () => {
167
163
 
168
164
  render(<Example />)
169
165
  ```
170
-
171
- ### Date formatting
172
-
173
- The display format of the dates can be set via the `formatDate` property. It will be applied if the user clicks on a date in the date picker of after blur event from the input field.
174
- Something to pay attention to is that the date string passed back in the callback function **is in UTC timezone**.
175
-
176
- ```js
177
- ---
178
- type: example
179
- ---
180
- const Example = () => {
181
- const [value1, setValue1] = useState('')
182
- const [value2, setValue2] = useState('')
183
- const [value3, setValue3] = useState('')
184
-
185
- const shortDateFormatFn = (dateString, locale, timezone) => {
186
- return new Date(dateString).toLocaleDateString(locale, {
187
- month: 'numeric',
188
- year: 'numeric',
189
- day: 'numeric',
190
- timeZone: timezone,
191
- })
192
- }
193
-
194
- const isoDateFormatFn = (dateString, locale, timezone) => {
195
- // this is a simple way to get ISO8601 date in a specific timezone but should not be used in production
196
- // please use a proper date library instead like date-fns, luxon or dayjs
197
- const localeDate = new Date(dateString).toLocaleDateString('sv', {
198
- month: 'numeric',
199
- year: 'numeric',
200
- day: 'numeric',
201
- timeZone: timezone,
202
- })
203
-
204
- return localeDate
205
- }
206
-
207
- return (
208
- <div style={{display: 'flex', flexDirection: 'column', gap: '1.5rem'}}>
209
- <DateInput2
210
- renderLabel="Default format"
211
- screenReaderLabels={{
212
- calendarIcon: 'Calendar',
213
- nextMonthButton: 'Next month',
214
- prevMonthButton: 'Previous month'
215
- }}
216
- isInline
217
- width="20rem"
218
- value={value1}
219
- onChange={(e, value) => setValue1(value)}
220
- withYearPicker={{
221
- screenReaderLabel: 'Year picker',
222
- startYear: 1900,
223
- endYear: 2024
224
- }}
225
- />
226
- <DateInput2
227
- renderLabel="Short format in current locale"
228
- screenReaderLabels={{
229
- calendarIcon: 'Calendar',
230
- nextMonthButton: 'Next month',
231
- prevMonthButton: 'Previous month'
232
- }}
233
- isInline
234
- width="20rem"
235
- value={value2}
236
- onChange={(e, value) => setValue2(value)}
237
- formatDate={shortDateFormatFn}
238
- withYearPicker={{
239
- screenReaderLabel: 'Year picker',
240
- startYear: 1900,
241
- endYear: 2024
242
- }}
243
- />
244
- <DateInput2
245
- renderLabel="ISO8601"
246
- screenReaderLabels={{
247
- calendarIcon: 'Calendar',
248
- nextMonthButton: 'Next month',
249
- prevMonthButton: 'Previous month'
250
- }}
251
- isInline
252
- width="20rem"
253
- value={value3}
254
- onChange={(e, value) => setValue3(value)}
255
- formatDate={isoDateFormatFn}
256
- withYearPicker={{
257
- screenReaderLabel: 'Year picker',
258
- startYear: 1900,
259
- endYear: 2024
260
- }}
261
- />
262
- </div>
263
- )
264
- }
265
-
266
- render(<Example />)
267
- ```