UNPKG

17 kBJavaScriptView Raw
1"use strict";
2/*
3 * Copyright 2016 Palantir Technologies, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17Object.defineProperty(exports, "__esModule", { value: true });
18exports.DateInput = void 0;
19var tslib_1 = require("tslib");
20/**
21 * @fileoverview This component is DEPRECATED, and the code is frozen.
22 * All changes & bugfixes should be made to DateInput2 in the datetime2
23 * package instead.
24 */
25/* eslint-disable deprecation/deprecation, @blueprintjs/no-deprecated-components */
26var classnames_1 = tslib_1.__importDefault(require("classnames"));
27var React = tslib_1.__importStar(require("react"));
28var core_1 = require("@blueprintjs/core");
29var Classes = tslib_1.__importStar(require("./common/classes"));
30var dateUtils_1 = require("./common/dateUtils");
31var dateFormat_1 = require("./dateFormat");
32var datePicker_1 = require("./datePicker");
33var datePickerCore_1 = require("./datePickerCore");
34/**
35 * Date input component.
36 *
37 * @see https://blueprintjs.com/docs/#datetime/dateinput
38 * @deprecated use { DateInput2 } from "@blueprintjs/datetime2"
39 */
40var DateInput = /** @class */ (function (_super) {
41 tslib_1.__extends(DateInput, _super);
42 function DateInput() {
43 var _this = this;
44 var _a;
45 _this = _super.apply(this, arguments) || this;
46 _this.state = {
47 isInputFocused: false,
48 isOpen: false,
49 value: _this.props.value !== undefined ? _this.props.value : _this.props.defaultValue,
50 valueString: null,
51 };
52 _this.inputElement = null;
53 _this.popoverContentElement = null;
54 _this.handleInputRef = (0, core_1.refHandler)(_this, "inputElement", (_a = _this.props.inputProps) === null || _a === void 0 ? void 0 : _a.inputRef);
55 _this.handlePopoverContentRef = (0, core_1.refHandler)(_this, "popoverContentElement");
56 _this.handleClosePopover = function (e) {
57 var _a;
58 var _b = _this.props.popoverProps, popoverProps = _b === void 0 ? {} : _b;
59 (_a = popoverProps.onClose) === null || _a === void 0 ? void 0 : _a.call(popoverProps, e);
60 _this.setState({ isOpen: false });
61 };
62 _this.handleDateChange = function (newDate, isUserChange, didSubmitWithEnter) {
63 var _a, _b;
64 if (didSubmitWithEnter === void 0) { didSubmitWithEnter = false; }
65 var prevDate = _this.state.value;
66 // this change handler was triggered by a change in month, day, or (if
67 // enabled) time. for UX purposes, we want to close the popover only if
68 // the user explicitly clicked a day within the current month.
69 var isOpen = !isUserChange ||
70 !_this.props.closeOnSelection ||
71 (prevDate != null && (_this.hasMonthChanged(prevDate, newDate) || _this.hasTimeChanged(prevDate, newDate)));
72 // if selecting a date via click or Tab, the input will already be
73 // blurred by now, so sync isInputFocused to false. if selecting via
74 // Enter, setting isInputFocused to false won't do anything by itself,
75 // plus we want the field to retain focus anyway.
76 // (note: spelling out the ternary explicitly reads more clearly.)
77 var isInputFocused = didSubmitWithEnter ? true : false;
78 if (_this.props.value === undefined) {
79 var valueString = (0, dateFormat_1.getFormattedDateString)(newDate, _this.props);
80 _this.setState({ isInputFocused: isInputFocused, isOpen: isOpen, value: newDate, valueString: valueString });
81 }
82 else {
83 _this.setState({ isInputFocused: isInputFocused, isOpen: isOpen });
84 }
85 (_b = (_a = _this.props).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, newDate, isUserChange);
86 };
87 _this.handleInputFocus = function (e) {
88 var valueString = _this.state.value == null ? "" : _this.formatDate(_this.state.value);
89 _this.setState({ isInputFocused: true, isOpen: true, valueString: valueString });
90 _this.safeInvokeInputProp("onFocus", e);
91 };
92 _this.handleInputClick = function (e) {
93 // stop propagation to the Popover's internal handleTargetClick handler;
94 // otherwise, the popover will flicker closed as soon as it opens.
95 e.stopPropagation();
96 _this.safeInvokeInputProp("onClick", e);
97 };
98 _this.handleInputChange = function (e) {
99 var _a, _b, _c, _d;
100 var valueString = e.target.value;
101 var value = _this.parseDate(valueString);
102 if ((0, dateUtils_1.isDateValid)(value) && _this.isDateInRange(value)) {
103 if (_this.props.value === undefined) {
104 _this.setState({ value: value, valueString: valueString });
105 }
106 else {
107 _this.setState({ valueString: valueString });
108 }
109 (_b = (_a = _this.props).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, value, true);
110 }
111 else {
112 if (valueString.length === 0) {
113 (_d = (_c = _this.props).onChange) === null || _d === void 0 ? void 0 : _d.call(_c, null, true);
114 }
115 _this.setState({ valueString: valueString });
116 }
117 _this.safeInvokeInputProp("onChange", e);
118 };
119 _this.handleInputBlur = function (e) {
120 var _a, _b, _c, _d, _e, _f;
121 var valueString = _this.state.valueString;
122 var date = _this.parseDate(valueString);
123 if (valueString.length > 0 &&
124 valueString !== (0, dateFormat_1.getFormattedDateString)(_this.state.value, _this.props) &&
125 (!(0, dateUtils_1.isDateValid)(date) || !_this.isDateInRange(date))) {
126 if (_this.props.value === undefined) {
127 _this.setState({ isInputFocused: false, value: date, valueString: null });
128 }
129 else {
130 _this.setState({ isInputFocused: false });
131 }
132 if (isNaN(date.valueOf())) {
133 (_b = (_a = _this.props).onError) === null || _b === void 0 ? void 0 : _b.call(_a, new Date(undefined));
134 }
135 else if (!_this.isDateInRange(date)) {
136 (_d = (_c = _this.props).onError) === null || _d === void 0 ? void 0 : _d.call(_c, date);
137 }
138 else {
139 (_f = (_e = _this.props).onChange) === null || _f === void 0 ? void 0 : _f.call(_e, date, true);
140 }
141 }
142 else {
143 if (valueString.length === 0) {
144 _this.setState({ isInputFocused: false, value: null, valueString: null });
145 }
146 else {
147 _this.setState({ isInputFocused: false });
148 }
149 }
150 _this.safeInvokeInputProp("onBlur", e);
151 };
152 _this.handleInputKeyDown = function (e) {
153 var _a, _b;
154 // HACKHACK: https://github.com/palantir/blueprint/issues/4165
155 if (e.which === core_1.Keys.ENTER) {
156 var nextDate = _this.parseDate(_this.state.valueString);
157 _this.handleDateChange(nextDate, true, true);
158 }
159 else if (e.which === core_1.Keys.TAB && e.shiftKey) {
160 // close popover on SHIFT+TAB key press
161 _this.handleClosePopover();
162 }
163 else if (e.which === core_1.Keys.TAB && _this.state.isOpen) {
164 (_a = _this.getKeyboardFocusableElements().shift()) === null || _a === void 0 ? void 0 : _a.focus();
165 // necessary to prevent focusing the second focusable element
166 e.preventDefault();
167 }
168 else if (e.which === core_1.Keys.ESCAPE) {
169 _this.setState({ isOpen: false });
170 (_b = _this.inputElement) === null || _b === void 0 ? void 0 : _b.blur();
171 }
172 _this.safeInvokeInputProp("onKeyDown", e);
173 };
174 _this.getKeyboardFocusableElements = function () {
175 var _a;
176 var elements = Array.from((_a = _this.popoverContentElement) === null || _a === void 0 ? void 0 : _a.querySelectorAll("button:not([disabled]),input,[tabindex]:not([tabindex='-1'])"));
177 // Remove focus boundary div elements
178 elements.pop();
179 elements.shift();
180 return elements;
181 };
182 _this.handleStartFocusBoundaryFocusIn = function (e) {
183 var _a, _b;
184 if (_this.popoverContentElement.contains(_this.getRelatedTarget(e))) {
185 // Not closing Popover to allow user to freely switch between manually entering a date
186 // string in the input and selecting one via the Popover
187 (_a = _this.inputElement) === null || _a === void 0 ? void 0 : _a.focus();
188 }
189 else {
190 (_b = _this.getKeyboardFocusableElements().shift()) === null || _b === void 0 ? void 0 : _b.focus();
191 }
192 };
193 _this.handleEndFocusBoundaryFocusIn = function (e) {
194 var _a, _b;
195 if (_this.popoverContentElement.contains(_this.getRelatedTarget(e))) {
196 (_a = _this.inputElement) === null || _a === void 0 ? void 0 : _a.focus();
197 _this.handleClosePopover();
198 }
199 else {
200 (_b = _this.getKeyboardFocusableElements().pop()) === null || _b === void 0 ? void 0 : _b.focus();
201 }
202 };
203 _this.handleShortcutChange = function (_, selectedShortcutIndex) {
204 _this.setState({ selectedShortcutIndex: selectedShortcutIndex });
205 };
206 return _this;
207 }
208 DateInput.prototype.render = function () {
209 var _this = this;
210 var _a = this.state, value = _a.value, valueString = _a.valueString;
211 var dateString = this.state.isInputFocused ? valueString : (0, dateFormat_1.getFormattedDateString)(value, this.props);
212 var dateValue = (0, dateUtils_1.isDateValid)(value) ? value : null;
213 var dayPickerProps = tslib_1.__assign(tslib_1.__assign({}, this.props.dayPickerProps), { onDayKeyDown: function (day, modifiers, e) {
214 var _a, _b;
215 (_b = (_a = _this.props.dayPickerProps).onDayKeyDown) === null || _b === void 0 ? void 0 : _b.call(_a, day, modifiers, e);
216 }, onMonthChange: function (month) {
217 var _a, _b;
218 (_b = (_a = _this.props.dayPickerProps).onMonthChange) === null || _b === void 0 ? void 0 : _b.call(_a, month);
219 } });
220 // React's onFocus prop listens to the focusin browser event under the hood, so it's safe to
221 // provide it the focusIn event handlers instead of using a ref and manually adding the
222 // event listeners ourselves.
223 var wrappedPopoverContent = (React.createElement("div", { ref: this.handlePopoverContentRef },
224 React.createElement("div", { onFocus: this.handleStartFocusBoundaryFocusIn, tabIndex: 0 }),
225 React.createElement(datePicker_1.DatePicker, tslib_1.__assign({}, this.props, { dayPickerProps: dayPickerProps, onChange: this.handleDateChange, value: dateValue, onShortcutChange: this.handleShortcutChange, selectedShortcutIndex: this.state.selectedShortcutIndex })),
226 React.createElement("div", { onFocus: this.handleEndFocusBoundaryFocusIn, tabIndex: 0 })));
227 // assign default empty object here to prevent mutation
228 var _b = this.props, _c = _b.inputProps, inputProps = _c === void 0 ? {} : _c, _d = _b.popoverProps, popoverProps = _d === void 0 ? {} : _d;
229 var isErrorState = value != null && (!(0, dateUtils_1.isDateValid)(value) || !this.isDateInRange(value));
230 return (React.createElement(core_1.Popover, tslib_1.__assign({ isOpen: this.state.isOpen && !this.props.disabled, fill: this.props.fill }, popoverProps, { autoFocus: false, className: (0, classnames_1.default)(popoverProps.className, this.props.className), content: wrappedPopoverContent, enforceFocus: false, onClose: this.handleClosePopover, popoverClassName: (0, classnames_1.default)(Classes.DATEINPUT_POPOVER, popoverProps.popoverClassName) }),
231 React.createElement(core_1.InputGroup, tslib_1.__assign({ autoComplete: "off", intent: isErrorState ? core_1.Intent.DANGER : core_1.Intent.NONE, placeholder: this.props.placeholder, rightElement: this.props.rightElement, type: "text" }, inputProps, { disabled: this.props.disabled, inputRef: this.handleInputRef, onBlur: this.handleInputBlur, onChange: this.handleInputChange, onClick: this.handleInputClick, onFocus: this.handleInputFocus, onKeyDown: this.handleInputKeyDown, value: dateString }))));
232 };
233 DateInput.prototype.componentDidUpdate = function (prevProps, prevState) {
234 var _a, _b, _c, _d, _e;
235 _super.prototype.componentDidUpdate.call(this, prevProps, prevState);
236 if (((_a = prevProps.inputProps) === null || _a === void 0 ? void 0 : _a.inputRef) !== ((_b = this.props.inputProps) === null || _b === void 0 ? void 0 : _b.inputRef)) {
237 (0, core_1.setRef)((_c = prevProps.inputProps) === null || _c === void 0 ? void 0 : _c.inputRef, null);
238 this.handleInputRef = (0, core_1.refHandler)(this, "inputElement", (_d = this.props.inputProps) === null || _d === void 0 ? void 0 : _d.inputRef);
239 (0, core_1.setRef)((_e = this.props.inputProps) === null || _e === void 0 ? void 0 : _e.inputRef, this.inputElement);
240 }
241 if (prevProps.value !== this.props.value) {
242 this.setState({ value: this.props.value });
243 }
244 };
245 DateInput.prototype.isDateInRange = function (value) {
246 return (0, dateUtils_1.isDayInRange)(value, [this.props.minDate, this.props.maxDate]);
247 };
248 DateInput.prototype.hasMonthChanged = function (prevDate, nextDate) {
249 return (prevDate == null) !== (nextDate == null) || nextDate.getMonth() !== prevDate.getMonth();
250 };
251 DateInput.prototype.hasTimeChanged = function (prevDate, nextDate) {
252 if (this.props.timePrecision == null) {
253 return false;
254 }
255 return ((prevDate == null) !== (nextDate == null) ||
256 nextDate.getHours() !== prevDate.getHours() ||
257 nextDate.getMinutes() !== prevDate.getMinutes() ||
258 nextDate.getSeconds() !== prevDate.getSeconds() ||
259 nextDate.getMilliseconds() !== prevDate.getMilliseconds());
260 };
261 DateInput.prototype.getRelatedTarget = function (e) {
262 var _a;
263 // Support IE11 (#2924)
264 return ((_a = e.relatedTarget) !== null && _a !== void 0 ? _a : document.activeElement);
265 };
266 /** safe wrapper around invoking input props event handler (prop defaults to undefined) */
267 DateInput.prototype.safeInvokeInputProp = function (name, e) {
268 var _a;
269 var _b = this.props.inputProps, inputProps = _b === void 0 ? {} : _b;
270 (_a = inputProps[name]) === null || _a === void 0 ? void 0 : _a.call(inputProps, e);
271 };
272 DateInput.prototype.parseDate = function (dateString) {
273 if (dateString === this.props.outOfRangeMessage || dateString === this.props.invalidDateMessage) {
274 return null;
275 }
276 var _a = this.props, locale = _a.locale, parseDate = _a.parseDate;
277 var newDate = parseDate(dateString, locale);
278 return newDate === false ? new Date(undefined) : newDate;
279 };
280 DateInput.prototype.formatDate = function (date) {
281 if (!(0, dateUtils_1.isDateValid)(date) || !this.isDateInRange(date)) {
282 return "";
283 }
284 var _a = this.props, locale = _a.locale, formatDate = _a.formatDate;
285 return formatDate(date, locale);
286 };
287 DateInput.displayName = "".concat(core_1.DISPLAYNAME_PREFIX, ".DateInput");
288 DateInput.defaultProps = {
289 closeOnSelection: true,
290 dayPickerProps: {},
291 disabled: false,
292 invalidDateMessage: "Invalid date",
293 maxDate: (0, datePickerCore_1.getDefaultMaxDate)(),
294 minDate: (0, datePickerCore_1.getDefaultMinDate)(),
295 outOfRangeMessage: "Out of range",
296 reverseMonthAndYearMenus: false,
297 };
298 return DateInput;
299}(core_1.AbstractPureComponent2));
300exports.DateInput = DateInput;
301//# sourceMappingURL=dateInput.js.map
\No newline at end of file