1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | import { __assign, __extends } from "tslib";
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | import classNames from "classnames";
|
24 | import * as React from "react";
|
25 | import { AbstractPureComponent2, DISPLAYNAME_PREFIX, InputGroup, Intent, Keys, Popover, refHandler, setRef, } from "@blueprintjs/core";
|
26 | import * as Classes from "./common/classes";
|
27 | import { isDateValid, isDayInRange } from "./common/dateUtils";
|
28 | import { getFormattedDateString } from "./dateFormat";
|
29 | import { DatePicker } from "./datePicker";
|
30 | import { getDefaultMaxDate, getDefaultMinDate } from "./datePickerCore";
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | var DateInput = (function (_super) {
|
38 | __extends(DateInput, _super);
|
39 | function DateInput() {
|
40 | var _this = this;
|
41 | var _a;
|
42 | _this = _super.apply(this, arguments) || this;
|
43 | _this.state = {
|
44 | isInputFocused: false,
|
45 | isOpen: false,
|
46 | value: _this.props.value !== undefined ? _this.props.value : _this.props.defaultValue,
|
47 | valueString: null,
|
48 | };
|
49 | _this.inputElement = null;
|
50 | _this.popoverContentElement = null;
|
51 | _this.handleInputRef = refHandler(_this, "inputElement", (_a = _this.props.inputProps) === null || _a === void 0 ? void 0 : _a.inputRef);
|
52 | _this.handlePopoverContentRef = refHandler(_this, "popoverContentElement");
|
53 | _this.handleClosePopover = function (e) {
|
54 | var _a;
|
55 | var _b = _this.props.popoverProps, popoverProps = _b === void 0 ? {} : _b;
|
56 | (_a = popoverProps.onClose) === null || _a === void 0 ? void 0 : _a.call(popoverProps, e);
|
57 | _this.setState({ isOpen: false });
|
58 | };
|
59 | _this.handleDateChange = function (newDate, isUserChange, didSubmitWithEnter) {
|
60 | var _a, _b;
|
61 | if (didSubmitWithEnter === void 0) { didSubmitWithEnter = false; }
|
62 | var prevDate = _this.state.value;
|
63 |
|
64 |
|
65 |
|
66 | var isOpen = !isUserChange ||
|
67 | !_this.props.closeOnSelection ||
|
68 | (prevDate != null && (_this.hasMonthChanged(prevDate, newDate) || _this.hasTimeChanged(prevDate, newDate)));
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 | var isInputFocused = didSubmitWithEnter ? true : false;
|
75 | if (_this.props.value === undefined) {
|
76 | var valueString = getFormattedDateString(newDate, _this.props);
|
77 | _this.setState({ isInputFocused: isInputFocused, isOpen: isOpen, value: newDate, valueString: valueString });
|
78 | }
|
79 | else {
|
80 | _this.setState({ isInputFocused: isInputFocused, isOpen: isOpen });
|
81 | }
|
82 | (_b = (_a = _this.props).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, newDate, isUserChange);
|
83 | };
|
84 | _this.handleInputFocus = function (e) {
|
85 | var valueString = _this.state.value == null ? "" : _this.formatDate(_this.state.value);
|
86 | _this.setState({ isInputFocused: true, isOpen: true, valueString: valueString });
|
87 | _this.safeInvokeInputProp("onFocus", e);
|
88 | };
|
89 | _this.handleInputClick = function (e) {
|
90 |
|
91 |
|
92 | e.stopPropagation();
|
93 | _this.safeInvokeInputProp("onClick", e);
|
94 | };
|
95 | _this.handleInputChange = function (e) {
|
96 | var _a, _b, _c, _d;
|
97 | var valueString = e.target.value;
|
98 | var value = _this.parseDate(valueString);
|
99 | if (isDateValid(value) && _this.isDateInRange(value)) {
|
100 | if (_this.props.value === undefined) {
|
101 | _this.setState({ value: value, valueString: valueString });
|
102 | }
|
103 | else {
|
104 | _this.setState({ valueString: valueString });
|
105 | }
|
106 | (_b = (_a = _this.props).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, value, true);
|
107 | }
|
108 | else {
|
109 | if (valueString.length === 0) {
|
110 | (_d = (_c = _this.props).onChange) === null || _d === void 0 ? void 0 : _d.call(_c, null, true);
|
111 | }
|
112 | _this.setState({ valueString: valueString });
|
113 | }
|
114 | _this.safeInvokeInputProp("onChange", e);
|
115 | };
|
116 | _this.handleInputBlur = function (e) {
|
117 | var _a, _b, _c, _d, _e, _f;
|
118 | var valueString = _this.state.valueString;
|
119 | var date = _this.parseDate(valueString);
|
120 | if (valueString.length > 0 &&
|
121 | valueString !== getFormattedDateString(_this.state.value, _this.props) &&
|
122 | (!isDateValid(date) || !_this.isDateInRange(date))) {
|
123 | if (_this.props.value === undefined) {
|
124 | _this.setState({ isInputFocused: false, value: date, valueString: null });
|
125 | }
|
126 | else {
|
127 | _this.setState({ isInputFocused: false });
|
128 | }
|
129 | if (isNaN(date.valueOf())) {
|
130 | (_b = (_a = _this.props).onError) === null || _b === void 0 ? void 0 : _b.call(_a, new Date(undefined));
|
131 | }
|
132 | else if (!_this.isDateInRange(date)) {
|
133 | (_d = (_c = _this.props).onError) === null || _d === void 0 ? void 0 : _d.call(_c, date);
|
134 | }
|
135 | else {
|
136 | (_f = (_e = _this.props).onChange) === null || _f === void 0 ? void 0 : _f.call(_e, date, true);
|
137 | }
|
138 | }
|
139 | else {
|
140 | if (valueString.length === 0) {
|
141 | _this.setState({ isInputFocused: false, value: null, valueString: null });
|
142 | }
|
143 | else {
|
144 | _this.setState({ isInputFocused: false });
|
145 | }
|
146 | }
|
147 | _this.safeInvokeInputProp("onBlur", e);
|
148 | };
|
149 | _this.handleInputKeyDown = function (e) {
|
150 | var _a, _b;
|
151 |
|
152 | if (e.which === Keys.ENTER) {
|
153 | var nextDate = _this.parseDate(_this.state.valueString);
|
154 | _this.handleDateChange(nextDate, true, true);
|
155 | }
|
156 | else if (e.which === Keys.TAB && e.shiftKey) {
|
157 |
|
158 | _this.handleClosePopover();
|
159 | }
|
160 | else if (e.which === Keys.TAB && _this.state.isOpen) {
|
161 | (_a = _this.getKeyboardFocusableElements().shift()) === null || _a === void 0 ? void 0 : _a.focus();
|
162 |
|
163 | e.preventDefault();
|
164 | }
|
165 | else if (e.which === Keys.ESCAPE) {
|
166 | _this.setState({ isOpen: false });
|
167 | (_b = _this.inputElement) === null || _b === void 0 ? void 0 : _b.blur();
|
168 | }
|
169 | _this.safeInvokeInputProp("onKeyDown", e);
|
170 | };
|
171 | _this.getKeyboardFocusableElements = function () {
|
172 | var _a;
|
173 | var elements = Array.from((_a = _this.popoverContentElement) === null || _a === void 0 ? void 0 : _a.querySelectorAll("button:not([disabled]),input,[tabindex]:not([tabindex='-1'])"));
|
174 |
|
175 | elements.pop();
|
176 | elements.shift();
|
177 | return elements;
|
178 | };
|
179 | _this.handleStartFocusBoundaryFocusIn = function (e) {
|
180 | var _a, _b;
|
181 | if (_this.popoverContentElement.contains(_this.getRelatedTarget(e))) {
|
182 |
|
183 |
|
184 | (_a = _this.inputElement) === null || _a === void 0 ? void 0 : _a.focus();
|
185 | }
|
186 | else {
|
187 | (_b = _this.getKeyboardFocusableElements().shift()) === null || _b === void 0 ? void 0 : _b.focus();
|
188 | }
|
189 | };
|
190 | _this.handleEndFocusBoundaryFocusIn = function (e) {
|
191 | var _a, _b;
|
192 | if (_this.popoverContentElement.contains(_this.getRelatedTarget(e))) {
|
193 | (_a = _this.inputElement) === null || _a === void 0 ? void 0 : _a.focus();
|
194 | _this.handleClosePopover();
|
195 | }
|
196 | else {
|
197 | (_b = _this.getKeyboardFocusableElements().pop()) === null || _b === void 0 ? void 0 : _b.focus();
|
198 | }
|
199 | };
|
200 | _this.handleShortcutChange = function (_, selectedShortcutIndex) {
|
201 | _this.setState({ selectedShortcutIndex: selectedShortcutIndex });
|
202 | };
|
203 | return _this;
|
204 | }
|
205 | DateInput.prototype.render = function () {
|
206 | var _this = this;
|
207 | var _a = this.state, value = _a.value, valueString = _a.valueString;
|
208 | var dateString = this.state.isInputFocused ? valueString : getFormattedDateString(value, this.props);
|
209 | var dateValue = isDateValid(value) ? value : null;
|
210 | var dayPickerProps = __assign(__assign({}, this.props.dayPickerProps), { onDayKeyDown: function (day, modifiers, e) {
|
211 | var _a, _b;
|
212 | (_b = (_a = _this.props.dayPickerProps).onDayKeyDown) === null || _b === void 0 ? void 0 : _b.call(_a, day, modifiers, e);
|
213 | }, onMonthChange: function (month) {
|
214 | var _a, _b;
|
215 | (_b = (_a = _this.props.dayPickerProps).onMonthChange) === null || _b === void 0 ? void 0 : _b.call(_a, month);
|
216 | } });
|
217 |
|
218 |
|
219 |
|
220 | var wrappedPopoverContent = (React.createElement("div", { ref: this.handlePopoverContentRef },
|
221 | React.createElement("div", { onFocus: this.handleStartFocusBoundaryFocusIn, tabIndex: 0 }),
|
222 | React.createElement(DatePicker, __assign({}, this.props, { dayPickerProps: dayPickerProps, onChange: this.handleDateChange, value: dateValue, onShortcutChange: this.handleShortcutChange, selectedShortcutIndex: this.state.selectedShortcutIndex })),
|
223 | React.createElement("div", { onFocus: this.handleEndFocusBoundaryFocusIn, tabIndex: 0 })));
|
224 |
|
225 | var _b = this.props, _c = _b.inputProps, inputProps = _c === void 0 ? {} : _c, _d = _b.popoverProps, popoverProps = _d === void 0 ? {} : _d;
|
226 | var isErrorState = value != null && (!isDateValid(value) || !this.isDateInRange(value));
|
227 | return (React.createElement(Popover, __assign({ isOpen: this.state.isOpen && !this.props.disabled, fill: this.props.fill }, popoverProps, { autoFocus: false, className: classNames(popoverProps.className, this.props.className), content: wrappedPopoverContent, enforceFocus: false, onClose: this.handleClosePopover, popoverClassName: classNames(Classes.DATEINPUT_POPOVER, popoverProps.popoverClassName) }),
|
228 | React.createElement(InputGroup, __assign({ autoComplete: "off", intent: isErrorState ? Intent.DANGER : 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 }))));
|
229 | };
|
230 | DateInput.prototype.componentDidUpdate = function (prevProps, prevState) {
|
231 | var _a, _b, _c, _d, _e;
|
232 | _super.prototype.componentDidUpdate.call(this, prevProps, prevState);
|
233 | if (((_a = prevProps.inputProps) === null || _a === void 0 ? void 0 : _a.inputRef) !== ((_b = this.props.inputProps) === null || _b === void 0 ? void 0 : _b.inputRef)) {
|
234 | setRef((_c = prevProps.inputProps) === null || _c === void 0 ? void 0 : _c.inputRef, null);
|
235 | this.handleInputRef = refHandler(this, "inputElement", (_d = this.props.inputProps) === null || _d === void 0 ? void 0 : _d.inputRef);
|
236 | setRef((_e = this.props.inputProps) === null || _e === void 0 ? void 0 : _e.inputRef, this.inputElement);
|
237 | }
|
238 | if (prevProps.value !== this.props.value) {
|
239 | this.setState({ value: this.props.value });
|
240 | }
|
241 | };
|
242 | DateInput.prototype.isDateInRange = function (value) {
|
243 | return isDayInRange(value, [this.props.minDate, this.props.maxDate]);
|
244 | };
|
245 | DateInput.prototype.hasMonthChanged = function (prevDate, nextDate) {
|
246 | return (prevDate == null) !== (nextDate == null) || nextDate.getMonth() !== prevDate.getMonth();
|
247 | };
|
248 | DateInput.prototype.hasTimeChanged = function (prevDate, nextDate) {
|
249 | if (this.props.timePrecision == null) {
|
250 | return false;
|
251 | }
|
252 | return ((prevDate == null) !== (nextDate == null) ||
|
253 | nextDate.getHours() !== prevDate.getHours() ||
|
254 | nextDate.getMinutes() !== prevDate.getMinutes() ||
|
255 | nextDate.getSeconds() !== prevDate.getSeconds() ||
|
256 | nextDate.getMilliseconds() !== prevDate.getMilliseconds());
|
257 | };
|
258 | DateInput.prototype.getRelatedTarget = function (e) {
|
259 | var _a;
|
260 |
|
261 | return ((_a = e.relatedTarget) !== null && _a !== void 0 ? _a : document.activeElement);
|
262 | };
|
263 |
|
264 | DateInput.prototype.safeInvokeInputProp = function (name, e) {
|
265 | var _a;
|
266 | var _b = this.props.inputProps, inputProps = _b === void 0 ? {} : _b;
|
267 | (_a = inputProps[name]) === null || _a === void 0 ? void 0 : _a.call(inputProps, e);
|
268 | };
|
269 | DateInput.prototype.parseDate = function (dateString) {
|
270 | if (dateString === this.props.outOfRangeMessage || dateString === this.props.invalidDateMessage) {
|
271 | return null;
|
272 | }
|
273 | var _a = this.props, locale = _a.locale, parseDate = _a.parseDate;
|
274 | var newDate = parseDate(dateString, locale);
|
275 | return newDate === false ? new Date(undefined) : newDate;
|
276 | };
|
277 | DateInput.prototype.formatDate = function (date) {
|
278 | if (!isDateValid(date) || !this.isDateInRange(date)) {
|
279 | return "";
|
280 | }
|
281 | var _a = this.props, locale = _a.locale, formatDate = _a.formatDate;
|
282 | return formatDate(date, locale);
|
283 | };
|
284 | DateInput.displayName = "".concat(DISPLAYNAME_PREFIX, ".DateInput");
|
285 | DateInput.defaultProps = {
|
286 | closeOnSelection: true,
|
287 | dayPickerProps: {},
|
288 | disabled: false,
|
289 | invalidDateMessage: "Invalid date",
|
290 | maxDate: getDefaultMaxDate(),
|
291 | minDate: getDefaultMinDate(),
|
292 | outOfRangeMessage: "Out of range",
|
293 | reverseMonthAndYearMenus: false,
|
294 | };
|
295 | return DateInput;
|
296 | }(AbstractPureComponent2));
|
297 | export { DateInput };
|
298 |
|
\ | No newline at end of file |