UNPKG

24.4 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = exports.DEFAULT_DATE_FORMAT = void 0;
7
8var React = _interopRequireWildcard(require("react"));
9
10var _index = require("../input/index.js");
11
12var _index2 = require("../popover/index.js");
13
14var _calendar = _interopRequireDefault(require("./calendar.js"));
15
16var _overrides = require("../helpers/overrides.js");
17
18var _i18nInterpolation = _interopRequireDefault(require("../helpers/i18n-interpolation.js"));
19
20var _index3 = require("../locale/index.js");
21
22var _styledComponents = require("./styled-components.js");
23
24var _dateHelpers = _interopRequireDefault(require("./utils/date-helpers.js"));
25
26var _dateFnsAdapter = _interopRequireDefault(require("./utils/date-fns-adapter.js"));
27
28function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29
30function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
31
32function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
33
34function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
35
36function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
37
38function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
39
40function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
41
42function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
43
44function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
45
46function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
47
48function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
49
50function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
51
52function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
53
54function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
55
56function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
57
58function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
59
60function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
61
62function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
63
64function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
65
66function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
67
68function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
69
70function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
71
72function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
73
74function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
75
76var DEFAULT_DATE_FORMAT = 'yyyy/MM/dd';
77exports.DEFAULT_DATE_FORMAT = DEFAULT_DATE_FORMAT;
78
79var Datepicker =
80/*#__PURE__*/
81function (_React$Component) {
82 _inherits(Datepicker, _React$Component);
83
84 function Datepicker(props) {
85 var _this;
86
87 _classCallCheck(this, Datepicker);
88
89 _this = _possibleConstructorReturn(this, _getPrototypeOf(Datepicker).call(this, props));
90
91 _defineProperty(_assertThisInitialized(_this), "calendar", void 0);
92
93 _defineProperty(_assertThisInitialized(_this), "dateHelpers", void 0);
94
95 _defineProperty(_assertThisInitialized(_this), "onChange", function (data) {
96 var date = data.date;
97 var isOpen = false;
98 var isPseudoFocused = false;
99 var calendarFocused = false;
100
101 if (Array.isArray(date) && _this.props.range && date.length < 2) {
102 isOpen = true;
103 isPseudoFocused = true;
104 calendarFocused = null;
105 } else if (_this.state.lastActiveElm) {
106 _this.state.lastActiveElm.focus();
107 } // Time selectors previously caused the calendar popover to close.
108 // The check below refrains from closing the popover if only times changed.
109
110
111 var onlyTimeChanged = function onlyTimeChanged(prev, next) {
112 if (!prev || !next) return false;
113
114 var p = _this.dateHelpers.format(prev, 'keyboardDate');
115
116 var n = _this.dateHelpers.format(next, 'keyboardDate');
117
118 if (p === n) {
119 return _this.dateHelpers.getHours(prev) !== _this.dateHelpers.getHours(next) || _this.dateHelpers.getMinutes(prev) !== _this.dateHelpers.getMinutes(next);
120 }
121
122 return false;
123 };
124
125 var prevValue = _this.props.value;
126
127 if (Array.isArray(date) && Array.isArray(prevValue)) {
128 if (date.some(function (d, i) {
129 return onlyTimeChanged(prevValue[i], d);
130 })) {
131 isOpen = true;
132 }
133 } else if (!Array.isArray(date) && !Array.isArray(prevValue)) {
134 if (onlyTimeChanged(prevValue, date)) {
135 isOpen = true;
136 }
137 }
138
139 _this.setState(_objectSpread({
140 isOpen: isOpen,
141 isPseudoFocused: isPseudoFocused
142 }, calendarFocused === null ? {} : {
143 calendarFocused: calendarFocused
144 }, {
145 inputValue: _this.formatDisplayValue(date)
146 }));
147
148 _this.props.onChange && _this.props.onChange(data);
149 });
150
151 _defineProperty(_assertThisInitialized(_this), "formatDisplayValue", function (date) {
152 var _this$props = _this.props,
153 displayValueAtRangeIndex = _this$props.displayValueAtRangeIndex,
154 formatDisplayValue = _this$props.formatDisplayValue,
155 formatString = _this$props.formatString,
156 range = _this$props.range;
157
158 if (typeof displayValueAtRangeIndex === 'number') {
159 if (process.env.NODE_ENV !== "production") {
160 if (!range) {
161 console.error('displayValueAtRangeIndex only applies if range');
162 }
163
164 if (range && displayValueAtRangeIndex > 1) {
165 console.error('displayValueAtRangeIndex value must be 0 or 1');
166 }
167 }
168
169 if (date && Array.isArray(date)) {
170 var value = date[displayValueAtRangeIndex];
171
172 if (formatDisplayValue) {
173 return formatDisplayValue(value, formatString);
174 }
175
176 return _this.formatDate(value, formatString);
177 }
178 }
179
180 if (formatDisplayValue) {
181 return formatDisplayValue(date, formatString);
182 }
183
184 return _this.formatDate(date, formatString);
185 });
186
187 _defineProperty(_assertThisInitialized(_this), "open", function () {
188 _this.setState({
189 isOpen: true,
190 isPseudoFocused: true,
191 calendarFocused: false
192 });
193 });
194
195 _defineProperty(_assertThisInitialized(_this), "close", function () {
196 var isPseudoFocused = false;
197
198 _this.setState({
199 isOpen: false,
200 isPseudoFocused: isPseudoFocused,
201 calendarFocused: false
202 }, _this.props.onClose);
203 });
204
205 _defineProperty(_assertThisInitialized(_this), "handleEsc", function () {
206 if (_this.state.lastActiveElm) {
207 _this.state.lastActiveElm.focus();
208 }
209
210 _this.close();
211 });
212
213 _defineProperty(_assertThisInitialized(_this), "handleInputBlur", function () {
214 if (!_this.state.isPseudoFocused) {
215 _this.close();
216 }
217 });
218
219 _defineProperty(_assertThisInitialized(_this), "getMask", function () {
220 var formatString = _this.props.formatString;
221 var mask = '';
222
223 if (_this.props.mask !== null) {
224 mask = // using the mask provided through the top-level API
225 _this.props.mask || ( // to make sure it's not a breaking change, we try calculating the input mask
226 // from the formatString, if used by the developer
227 // 1. mask generation from the formatstring if it's a range input
228 formatString && _this.props.range ? "".concat(formatString, " \u2013 ").concat(formatString).replace(/[a-z]/gi, '9') : null) || ( // 2. mask generation from the formatstring if it is NOT a range input
229 formatString ? formatString.replace(/[a-z]/gi, '9') : null) || ( // falling back to the default masks
230 _this.props.range ? '9999/99/99 – 9999/99/99' : '9999/99/99');
231 }
232
233 return mask;
234 });
235
236 _defineProperty(_assertThisInitialized(_this), "handleInputChange", function (event) {
237 var inputValue = event.currentTarget.value;
238
239 if (inputValue === _this.getMask().replace(/9/g, ' ') || inputValue.length === 0) {
240 if (_this.props.range) {
241 _this.props.onChange && _this.props.onChange({
242 date: []
243 });
244 } else {
245 _this.props.onChange && _this.props.onChange({
246 date: null
247 });
248 }
249 }
250
251 _this.setState({
252 inputValue: inputValue
253 });
254
255 var parseDateString = function parseDateString(dateString) {
256 var formatString = _this.normalizeDashes(_this.props.formatString);
257
258 if (formatString === DEFAULT_DATE_FORMAT) {
259 return _this.dateHelpers.parse(dateString, 'slashDate', _this.props.locale);
260 }
261
262 return _this.dateHelpers.parseString(dateString, formatString, _this.props.locale);
263 };
264
265 if (_this.props.range && typeof _this.props.displayValueAtRangeIndex !== 'number') {
266 var _this$normalizeDashes = _this.normalizeDashes(inputValue).split(' – '),
267 _this$normalizeDashes2 = _slicedToArray(_this$normalizeDashes, 2),
268 left = _this$normalizeDashes2[0],
269 right = _this$normalizeDashes2[1];
270
271 var startDate = _this.dateHelpers.date(left);
272
273 var endDate = _this.dateHelpers.date(right);
274
275 var formatString = _this.props.formatString;
276
277 if (formatString) {
278 startDate = parseDateString(left);
279 endDate = parseDateString(right);
280 }
281
282 var onChange = _this.props.onChange;
283
284 if (onChange) {
285 var datesValid = _this.dateHelpers.isValid(startDate) && _this.dateHelpers.isValid(endDate); // added equal case so that times within the same day can be expressed
286
287
288 var rangeValid = _this.dateHelpers.isAfter(endDate, startDate) || _this.dateHelpers.isEqual(startDate, endDate);
289
290 if (datesValid && rangeValid) {
291 onChange({
292 date: [startDate, endDate]
293 });
294 }
295 }
296 } else {
297 var dateString = _this.normalizeDashes(inputValue);
298
299 var date = _this.dateHelpers.date(dateString);
300
301 var _formatString = _this.props.formatString; // Prevent early parsing of value.
302 // Eg 25.12.2 will be transformed to 25.12.0002 formatted from date to string
303
304 if (dateString.replace(/(\s)*/g, '').length < _formatString.replace(/(\s)*/g, '').length) {
305 date = null;
306 } else {
307 date = parseDateString(dateString);
308 }
309
310 var _this$props2 = _this.props,
311 displayValueAtRangeIndex = _this$props2.displayValueAtRangeIndex,
312 _onChange = _this$props2.onChange,
313 range = _this$props2.range,
314 value = _this$props2.value;
315
316 if (date && _this.dateHelpers.isValid(date) && _onChange) {
317 if (range && Array.isArray(value) && typeof displayValueAtRangeIndex === 'number') {
318 var _value = _slicedToArray(value, 2),
319 _left = _value[0],
320 _right = _value[1];
321
322 if (displayValueAtRangeIndex === 0) {
323 _left = date;
324
325 if (!_right) {
326 _onChange({
327 date: [_left]
328 });
329 } else {
330 if (_this.dateHelpers.isAfter(_right, _left) || _this.dateHelpers.isEqual(_left, _right)) {
331 _onChange({
332 date: [_left, _right]
333 });
334 } else {
335 // Is resetting back to previous value appropriate? Invalid range is not
336 // communicated to the user, but if it was not reset the text value would
337 // show one value and date value another. This seems a bit better but clearly
338 // has a downside.
339 _onChange({
340 date: _toConsumableArray(value)
341 });
342 }
343 }
344 } else if (displayValueAtRangeIndex === 1) {
345 _right = date;
346
347 if (!_left) {
348 // If start value is not defined, set start/end to the same day.
349 _onChange({
350 date: [_right, _right]
351 });
352 } else {
353 if (_this.dateHelpers.isAfter(_right, _left) || _this.dateHelpers.isEqual(_left, _right)) {
354 _onChange({
355 date: [_left, _right]
356 });
357 } else {
358 // See comment above about resetting dates on invalid range
359 _onChange({
360 date: _toConsumableArray(value)
361 });
362 }
363 }
364 }
365 } else {
366 _onChange({
367 date: date
368 });
369 }
370 }
371 }
372 });
373
374 _defineProperty(_assertThisInitialized(_this), "handleKeyDown", function (event) {
375 if (!_this.state.isOpen && event.keyCode === 40) {
376 _this.open();
377 } else if (_this.state.isOpen && event.key === 'ArrowDown') {
378 // next line prevents the page jump on the initial arrowDown
379 event.preventDefault();
380
381 _this.focusCalendar();
382 } else if (_this.state.isOpen && event.keyCode === 9) {
383 _this.close();
384 }
385 });
386
387 _defineProperty(_assertThisInitialized(_this), "focusCalendar", function () {
388 if (typeof document !== 'undefined') {
389 var lastActiveElm = document.activeElement;
390
391 _this.setState({
392 calendarFocused: true,
393 lastActiveElm: lastActiveElm
394 });
395 }
396 });
397
398 _defineProperty(_assertThisInitialized(_this), "normalizeDashes", function (inputValue) {
399 // replacing both hyphens and em-dashes with en-dashes
400 return inputValue.replace(/-/g, '–').replace(/—/g, '–');
401 });
402
403 _this.dateHelpers = new _dateHelpers.default(props.adapter);
404 _this.state = {
405 calendarFocused: false,
406 isOpen: false,
407 isPseudoFocused: false,
408 lastActiveElm: null,
409 inputValue: _this.formatDisplayValue(props.value) || ''
410 };
411 return _this;
412 }
413
414 _createClass(Datepicker, [{
415 key: "formatDate",
416 value: function formatDate(date, formatString) {
417 var _this2 = this;
418
419 var format = function format(date) {
420 if (formatString === DEFAULT_DATE_FORMAT) {
421 return _this2.dateHelpers.format(date, 'slashDate', _this2.props.locale);
422 }
423
424 return _this2.dateHelpers.formatDate(date, formatString, _this2.props.locale);
425 };
426
427 if (!date) {
428 return '';
429 } else if (Array.isArray(date) && !date[0] && !date[1]) {
430 return '';
431 } else if (Array.isArray(date)) {
432 return date.map(function (day) {
433 return format(day);
434 }).join(' – ');
435 } else {
436 return format(date);
437 }
438 }
439 }, {
440 key: "componentDidUpdate",
441 value: function componentDidUpdate(prevProps) {
442 if (prevProps.value !== this.props.value) {
443 this.setState({
444 inputValue: this.formatDisplayValue(this.props.value)
445 });
446 }
447 }
448 }, {
449 key: "render",
450 value: function render() {
451 var _this3 = this;
452
453 var _this$props$overrides = this.props.overrides,
454 overrides = _this$props$overrides === void 0 ? {} : _this$props$overrides;
455
456 var _getOverrides = (0, _overrides.getOverrides)(overrides.Input, _index.MaskedInput),
457 _getOverrides2 = _slicedToArray(_getOverrides, 2),
458 InputComponent = _getOverrides2[0],
459 inputProps = _getOverrides2[1];
460
461 var _getOverrides3 = (0, _overrides.getOverrides)(overrides.Popover, _index2.Popover),
462 _getOverrides4 = _slicedToArray(_getOverrides3, 2),
463 PopoverComponent = _getOverrides4[0],
464 popoverProps = _getOverrides4[1];
465
466 var _getOverrides5 = (0, _overrides.getOverrides)(overrides.InputWrapper, _styledComponents.StyledInputWrapper),
467 _getOverrides6 = _slicedToArray(_getOverrides5, 2),
468 InputWrapper = _getOverrides6[0],
469 inputWrapperProps = _getOverrides6[1];
470
471 var placeholder = this.props.placeholder || (this.props.range ? 'YYYY/MM/DD – YYYY/MM/DD' : 'YYYY/MM/DD');
472 return React.createElement(_index3.LocaleContext.Consumer, null, function (locale) {
473 return React.createElement(React.Fragment, null, React.createElement(PopoverComponent, _extends({
474 focusLock: false,
475 mountNode: _this3.props.mountNode,
476 placement: _index2.PLACEMENT.bottom,
477 isOpen: _this3.state.isOpen,
478 onClickOutside: _this3.close,
479 onEsc: _this3.handleEsc,
480 content: React.createElement(_calendar.default, _extends({
481 adapter: _this3.props.adapter,
482 autoFocusCalendar: _this3.state.calendarFocused,
483 trapTabbing: true,
484 value: _this3.props.value
485 }, _this3.props, {
486 onChange: _this3.onChange
487 }))
488 }, popoverProps), React.createElement(InputWrapper, inputWrapperProps, React.createElement(InputComponent, _extends({
489 "aria-disabled": _this3.props.disabled,
490 "aria-label": _this3.props['aria-label'] || (_this3.props.range ? locale.datepicker.ariaLabelRange : locale.datepicker.ariaLabel),
491 error: _this3.props.error,
492 positive: _this3.props.positive,
493 "aria-describedby": _this3.props['aria-describedby'],
494 "aria-labelledby": _this3.props['aria-labelledby'],
495 "aria-required": _this3.props.required || null,
496 disabled: _this3.props.disabled,
497 size: _this3.props.size,
498 value: _this3.state.inputValue,
499 onFocus: _this3.open,
500 onBlur: _this3.handleInputBlur,
501 onKeyDown: _this3.handleKeyDown,
502 onChange: _this3.handleInputChange,
503 placeholder: placeholder,
504 mask: _this3.getMask(),
505 required: _this3.props.required,
506 clearable: _this3.props.clearable
507 }, inputProps)))), React.createElement("p", {
508 id: _this3.props['aria-describedby'],
509 style: {
510 position: 'fixed',
511 width: '0px',
512 height: '0px',
513 borderLeftWidth: 0,
514 borderRightWidth: 0,
515 borderTopWidth: 0,
516 borderBottomWidth: 0,
517 padding: 0,
518 overflow: 'hidden',
519 clip: 'rect(0, 0, 0, 0)',
520 clipPath: 'inset(100%)'
521 }
522 }, locale.datepicker.screenReaderMessageInput), React.createElement("p", {
523 "aria-live": "assertive",
524 style: {
525 position: 'fixed',
526 width: '0px',
527 height: '0px',
528 borderLeftWidth: 0,
529 borderRightWidth: 0,
530 borderTopWidth: 0,
531 borderBottomWidth: 0,
532 padding: 0,
533 overflow: 'hidden',
534 clip: 'rect(0, 0, 0, 0)',
535 clipPath: 'inset(100%)'
536 }
537 }, // No date selected
538 !_this3.props.value || Array.isArray(_this3.props.value) && !_this3.props.value.length ? '' : // Date selected in a non-range picker
539 !Array.isArray(_this3.props.value) ? (0, _i18nInterpolation.default)(locale.datepicker.selectedDate, {
540 date: _this3.state.inputValue || ''
541 }) : // Start and end dates are selected in a range picker
542 _this3.props.value.length > 1 ? (0, _i18nInterpolation.default)(locale.datepicker.selectedDateRange, {
543 startDate: _this3.formatDisplayValue(_this3.props.value[0]),
544 endDate: _this3.formatDisplayValue( // $FlowFixMe
545 _this3.props.value[1])
546 }) : // A single date selected in a range picker
547 "".concat((0, _i18nInterpolation.default)(locale.datepicker.selectedDate, {
548 date: _this3.formatDisplayValue(_this3.props.value[0])
549 }), " ").concat(locale.datepicker.selectSecondDatePrompt)));
550 });
551 }
552 }]);
553
554 return Datepicker;
555}(React.Component);
556
557exports.default = Datepicker;
558
559_defineProperty(Datepicker, "defaultProps", {
560 'aria-describedby': 'datepicker--screenreader--message--input',
561 value: null,
562 formatString: DEFAULT_DATE_FORMAT,
563 adapter: _dateFnsAdapter.default
564});
\No newline at end of file