UNPKG

@blueprintjs/datetime

Version:

Components for interacting with dates and times

705 lines 38 kB
/* * Copyright 2017 Palantir Technologies, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { __assign, __extends } from "tslib"; /** * @fileoverview This component is DEPRECATED, and the code is frozen. * All changes & bugfixes should be made to DateRangeInput2 in the datetime2 * package instead. */ /* eslint-disable deprecation/deprecation, @blueprintjs/no-deprecated-components */ import classNames from "classnames"; import * as React from "react"; import DayPicker from "react-day-picker"; import { AbstractPureComponent2, Boundary, Classes, DISPLAYNAME_PREFIX, InputGroup, Intent, Keys, Popover, Position, refHandler, setRef, } from "@blueprintjs/core"; import { areSameTime, isDateValid, isDayInRange } from "./common/dateUtils"; import * as Errors from "./common/errors"; import { getFormattedDateString } from "./dateFormat"; import { getDefaultMaxDate, getDefaultMinDate } from "./datePickerCore"; import { DateRangePicker } from "./dateRangePicker"; /** * Date range input component. * * @see https://blueprintjs.com/docs/#datetime/daterangeinput * @deprecated use { DateRangeInput2 } from "@blueprintjs/datetime2" */ var DateRangeInput = /** @class */ (function (_super) { __extends(DateRangeInput, _super); function DateRangeInput(props) { var _this = this; var _a, _b; _this = _super.call(this, props) || this; _this.startInputElement = null; _this.endInputElement = null; _this.handleStartInputRef = refHandler(_this, "startInputElement", (_a = _this.props.startInputProps) === null || _a === void 0 ? void 0 : _a.inputRef); _this.handleEndInputRef = refHandler(_this, "endInputElement", (_b = _this.props.endInputProps) === null || _b === void 0 ? void 0 : _b.inputRef); _this.renderInputGroup = function (boundary) { var inputProps = _this.getInputProps(boundary); var handleInputEvent = boundary === Boundary.START ? _this.handleStartInputEvent : _this.handleEndInputEvent; return (React.createElement(InputGroup, __assign({ autoComplete: "off", disabled: inputProps.disabled || _this.props.disabled }, inputProps, { intent: _this.isInputInErrorState(boundary) ? Intent.DANGER : inputProps.intent, inputRef: _this.getInputRef(boundary), onBlur: handleInputEvent, onChange: handleInputEvent, onClick: handleInputEvent, onFocus: handleInputEvent, onKeyDown: handleInputEvent, onMouseDown: handleInputEvent, placeholder: _this.getInputPlaceholderString(boundary), value: _this.getInputDisplayString(boundary) }))); }; // Callbacks - DateRangePicker // =========================== _this.handleDateRangePickerChange = function (selectedRange, didSubmitWithEnter) { var _a, _b; if (didSubmitWithEnter === void 0) { didSubmitWithEnter = false; } // ignore mouse events in the date-range picker if the popover is animating closed. if (!_this.state.isOpen) { return; } var selectedStart = selectedRange[0], selectedEnd = selectedRange[1]; var isOpen = true; var isStartInputFocused; var isEndInputFocused; var startHoverString; var endHoverString; var boundaryToModify; if (selectedStart == null) { // focus the start field by default or if only an end date is specified if (_this.props.timePrecision == null) { isStartInputFocused = true; isEndInputFocused = false; } else { isStartInputFocused = false; isEndInputFocused = false; boundaryToModify = Boundary.START; } // for clarity, hide the hover string until the mouse moves over a different date startHoverString = null; } else if (selectedEnd == null) { // focus the end field if a start date is specified if (_this.props.timePrecision == null) { isStartInputFocused = false; isEndInputFocused = true; } else { isStartInputFocused = false; isEndInputFocused = false; boundaryToModify = Boundary.END; } endHoverString = null; } else if (_this.props.closeOnSelection) { isOpen = _this.getIsOpenValueWhenDateChanges(selectedStart, selectedEnd); isStartInputFocused = false; if (_this.props.timePrecision == null && didSubmitWithEnter) { // if we submit via click or Tab, the focus will have moved already. // it we submit with Enter, the focus won't have moved, and setting // the flag to false won't have an effect anyway, so leave it true. isEndInputFocused = true; } else { isEndInputFocused = false; boundaryToModify = Boundary.END; } } else if (_this.state.lastFocusedField === Boundary.START) { // keep the start field focused if (_this.props.timePrecision == null) { isStartInputFocused = true; isEndInputFocused = false; } else { isStartInputFocused = false; isEndInputFocused = false; boundaryToModify = Boundary.START; } } else if (_this.props.timePrecision == null) { // keep the end field focused isStartInputFocused = false; isEndInputFocused = true; } else { isStartInputFocused = false; isEndInputFocused = false; boundaryToModify = Boundary.END; } var baseStateChange = { boundaryToModify: boundaryToModify, endHoverString: endHoverString, endInputString: _this.formatDate(selectedEnd), isEndInputFocused: isEndInputFocused, isOpen: isOpen, isStartInputFocused: isStartInputFocused, startHoverString: startHoverString, startInputString: _this.formatDate(selectedStart), wasLastFocusChangeDueToHover: false, }; if (_this.isControlled()) { _this.setState(baseStateChange); } else { _this.setState(__assign(__assign({}, baseStateChange), { selectedEnd: selectedEnd, selectedStart: selectedStart })); } (_b = (_a = _this.props).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, selectedRange); }; _this.handleShortcutChange = function (_, selectedShortcutIndex) { _this.setState({ selectedShortcutIndex: selectedShortcutIndex }); }; _this.handleDateRangePickerHoverChange = function (hoveredRange, _hoveredDay, hoveredBoundary) { // ignore mouse events in the date-range picker if the popover is animating closed. if (!_this.state.isOpen) { return; } if (hoveredRange == null) { // undo whatever focus changes we made while hovering over various calendar dates var isEndInputFocused = _this.state.boundaryToModify === Boundary.END; _this.setState({ endHoverString: null, isEndInputFocused: isEndInputFocused, isStartInputFocused: !isEndInputFocused, lastFocusedField: _this.state.boundaryToModify, startHoverString: null, }); } else { var hoveredStart = hoveredRange[0], hoveredEnd = hoveredRange[1]; var isStartInputFocused = hoveredBoundary != null ? hoveredBoundary === Boundary.START : _this.state.isStartInputFocused; var isEndInputFocused = hoveredBoundary != null ? hoveredBoundary === Boundary.END : _this.state.isEndInputFocused; _this.setState({ endHoverString: _this.formatDate(hoveredEnd), isEndInputFocused: isEndInputFocused, isStartInputFocused: isStartInputFocused, lastFocusedField: isStartInputFocused ? Boundary.START : Boundary.END, shouldSelectAfterUpdate: _this.props.selectAllOnFocus, startHoverString: _this.formatDate(hoveredStart), wasLastFocusChangeDueToHover: true, }); } }; // Callbacks - Input // ================= // instantiate these two functions once so we don't have to for each callback on each render. _this.handleStartInputEvent = function (e) { _this.handleInputEvent(e, Boundary.START); }; _this.handleEndInputEvent = function (e) { _this.handleInputEvent(e, Boundary.END); }; _this.handleInputEvent = function (e, boundary) { var _a, _b, _c, _d, _f, _g; var inputProps = _this.getInputProps(boundary); switch (e.type) { case "blur": _this.handleInputBlur(e, boundary); (_a = inputProps.onBlur) === null || _a === void 0 ? void 0 : _a.call(inputProps, e); break; case "change": _this.handleInputChange(e, boundary); (_b = inputProps.onChange) === null || _b === void 0 ? void 0 : _b.call(inputProps, e); break; case "click": e = e; _this.handleInputClick(e); (_c = inputProps.onClick) === null || _c === void 0 ? void 0 : _c.call(inputProps, e); break; case "focus": _this.handleInputFocus(e, boundary); (_d = inputProps.onFocus) === null || _d === void 0 ? void 0 : _d.call(inputProps, e); break; case "keydown": e = e; _this.handleInputKeyDown(e); (_f = inputProps.onKeyDown) === null || _f === void 0 ? void 0 : _f.call(inputProps, e); break; case "mousedown": e = e; _this.handleInputMouseDown(); (_g = inputProps.onMouseDown) === null || _g === void 0 ? void 0 : _g.call(inputProps, e); break; default: break; } }; // add a keydown listener to persistently change focus when tabbing: // - if focused in start field, Tab moves focus to end field // - if focused in end field, Shift+Tab moves focus to start field _this.handleInputKeyDown = function (e) { // HACKHACK: https://github.com/palantir/blueprint/issues/4165 var isTabPressed = e.which === Keys.TAB; var isEnterPressed = e.which === Keys.ENTER; var isShiftPressed = e.shiftKey; var _a = _this.state, selectedStart = _a.selectedStart, selectedEnd = _a.selectedEnd; // order of JS events is our enemy here. when tabbing between fields, // this handler will fire in the middle of a focus exchange when no // field is currently focused. we work around this by referring to the // most recently focused field, rather than the currently focused field. var wasStartFieldFocused = _this.state.lastFocusedField === Boundary.START; var wasEndFieldFocused = _this.state.lastFocusedField === Boundary.END; // move focus to the other field if (isTabPressed) { var isEndInputFocused = void 0; var isStartInputFocused = void 0; var isOpen = true; if (wasStartFieldFocused && !isShiftPressed) { isStartInputFocused = false; isEndInputFocused = true; // prevent the default focus-change behavior to avoid race conditions; // we'll handle the focus change ourselves in componentDidUpdate. e.preventDefault(); } else if (wasEndFieldFocused && isShiftPressed) { isStartInputFocused = true; isEndInputFocused = false; e.preventDefault(); } else { // don't prevent default here, otherwise Tab won't do anything. isStartInputFocused = false; isEndInputFocused = false; isOpen = false; } _this.setState({ isEndInputFocused: isEndInputFocused, isOpen: isOpen, isStartInputFocused: isStartInputFocused, wasLastFocusChangeDueToHover: false, }); } else if (wasStartFieldFocused && isEnterPressed) { var nextStartDate = _this.parseDate(_this.state.startInputString); _this.handleDateRangePickerChange([nextStartDate, selectedEnd], true); } else if (wasEndFieldFocused && isEnterPressed) { var nextEndDate = _this.parseDate(_this.state.endInputString); _this.handleDateRangePickerChange([selectedStart, nextEndDate], true); } else { // let the default keystroke happen without side effects return; } }; _this.handleInputMouseDown = function () { // clicking in the field constitutes an explicit focus change. we update // the flag on "mousedown" instead of on "click", because it needs to be // set before onFocus is called ("click" triggers after "focus"). _this.setState({ wasLastFocusChangeDueToHover: false }); }; _this.handleInputClick = function (e) { // unless we stop propagation on this event, a click within an input // will close the popover almost as soon as it opens. e.stopPropagation(); }; _this.handleInputFocus = function (_e, boundary) { var _a; var _b = _this.getStateKeysAndValuesForBoundary(boundary), keys = _b.keys, values = _b.values; var inputString = getFormattedDateString(values.selectedValue, _this.props, true); // change the boundary only if the user explicitly focused in the field. // focus changes from hovering don't count; they're just temporary. var boundaryToModify = _this.state.wasLastFocusChangeDueToHover ? _this.state.boundaryToModify : boundary; _this.setState((_a = {}, _a[keys.inputString] = inputString, _a[keys.isInputFocused] = true, _a.boundaryToModify = boundaryToModify, _a.isOpen = true, _a.lastFocusedField = boundary, _a.shouldSelectAfterUpdate = _this.props.selectAllOnFocus, _a.wasLastFocusChangeDueToHover = false, _a)); }; _this.handleInputBlur = function (_e, boundary) { var _a, _b, _c, _d; var _f, _g; var _h = _this.getStateKeysAndValuesForBoundary(boundary), keys = _h.keys, values = _h.values; var maybeNextDate = _this.parseDate(values.inputString); var isValueControlled = _this.isControlled(); var nextState = (_a = {}, _a[keys.isInputFocused] = false, _a.shouldSelectAfterUpdate = false, _a); if (_this.isInputEmpty(values.inputString)) { if (isValueControlled) { nextState = __assign(__assign({}, nextState), (_b = {}, _b[keys.inputString] = getFormattedDateString(values.controlledValue, _this.props), _b)); } else { nextState = __assign(__assign({}, nextState), (_c = {}, _c[keys.inputString] = null, _c[keys.selectedValue] = null, _c)); } } else if (!_this.isNextDateRangeValid(maybeNextDate, boundary)) { if (!isValueControlled) { nextState = __assign(__assign({}, nextState), (_d = {}, _d[keys.inputString] = null, _d[keys.selectedValue] = maybeNextDate, _d)); } (_g = (_f = _this.props).onError) === null || _g === void 0 ? void 0 : _g.call(_f, _this.getDateRangeForCallback(maybeNextDate, boundary)); } _this.setState(nextState); }; _this.handleInputChange = function (e, boundary) { var _a, _b, _c, _d, _f; var _g, _h, _j, _k; var inputString = e.target.value; var keys = _this.getStateKeysAndValuesForBoundary(boundary).keys; var maybeNextDate = _this.parseDate(inputString); var isValueControlled = _this.isControlled(); var nextState = { shouldSelectAfterUpdate: false }; if (inputString.length === 0) { // this case will be relevant when we start showing the hovered range in the input // fields. goal is to show an empty field for clarity until the mouse moves over a // different date. var baseState = __assign(__assign({}, nextState), (_a = {}, _a[keys.inputString] = "", _a)); if (isValueControlled) { nextState = baseState; } else { nextState = __assign(__assign({}, baseState), (_b = {}, _b[keys.selectedValue] = null, _b)); } (_h = (_g = _this.props).onChange) === null || _h === void 0 ? void 0 : _h.call(_g, _this.getDateRangeForCallback(null, boundary)); } else if (_this.isDateValidAndInRange(maybeNextDate)) { // note that error cases that depend on both fields (e.g. overlapping dates) should fall // through into this block so that the UI can update immediately, possibly with an error // message on the other field. // also, clear the hover string to ensure the most recent keystroke appears. var baseState = __assign(__assign({}, nextState), (_c = {}, _c[keys.hoverString] = null, _c[keys.inputString] = inputString, _c)); if (isValueControlled) { nextState = baseState; } else { nextState = __assign(__assign({}, baseState), (_d = {}, _d[keys.selectedValue] = maybeNextDate, _d)); } if (_this.isNextDateRangeValid(maybeNextDate, boundary)) { (_k = (_j = _this.props).onChange) === null || _k === void 0 ? void 0 : _k.call(_j, _this.getDateRangeForCallback(maybeNextDate, boundary)); } } else { // again, clear the hover string to ensure the most recent keystroke appears nextState = __assign(__assign({}, nextState), (_f = {}, _f[keys.inputString] = inputString, _f[keys.hoverString] = null, _f)); } _this.setState(nextState); }; // Callbacks - Popover // =================== _this.handlePopoverClose = function (event) { var _a, _b; _this.setState({ isOpen: false }); (_b = (_a = _this.props.popoverProps).onClose) === null || _b === void 0 ? void 0 : _b.call(_a, event); }; _this.getIsOpenValueWhenDateChanges = function (nextSelectedStart, nextSelectedEnd) { if (_this.props.closeOnSelection) { // trivial case when TimePicker is not shown if (_this.props.timePrecision == null) { return false; } var fallbackDate = new Date(new Date().setHours(0, 0, 0, 0)); var _a = _this.getSelectedRange([fallbackDate, fallbackDate]), selectedStart = _a[0], selectedEnd = _a[1]; // case to check if the user has changed TimePicker values if (areSameTime(selectedStart, nextSelectedStart) === true && areSameTime(selectedEnd, nextSelectedEnd) === true) { return false; } return true; } return true; }; _this.getInitialRange = function (props) { if (props === void 0) { props = _this.props; } var defaultValue = props.defaultValue, value = props.value; if (value != null) { return value; } else if (defaultValue != null) { return defaultValue; } else { return [null, null]; } }; _this.getSelectedRange = function (fallbackRange) { var _a; var selectedStart; var selectedEnd; if (_this.isControlled()) { _a = _this.props.value, selectedStart = _a[0], selectedEnd = _a[1]; } else { selectedStart = _this.state.selectedStart; selectedEnd = _this.state.selectedEnd; } // this helper function checks if the provided boundary date *would* overlap the selected // other boundary date. providing the already-selected start date simply tells us if we're // currently in an overlapping state. var doBoundaryDatesOverlap = _this.doBoundaryDatesOverlap(selectedStart, Boundary.START); var dateRange = [selectedStart, doBoundaryDatesOverlap ? undefined : selectedEnd]; return dateRange.map(function (selectedBound, index) { var fallbackDate = fallbackRange != null ? fallbackRange[index] : undefined; return _this.isDateValidAndInRange(selectedBound) ? selectedBound : fallbackDate; }); }; _this.getInputDisplayString = function (boundary) { var values = _this.getStateKeysAndValuesForBoundary(boundary).values; var isInputFocused = values.isInputFocused, inputString = values.inputString, selectedValue = values.selectedValue, hoverString = values.hoverString; if (hoverString != null) { return hoverString; } else if (isInputFocused) { return inputString == null ? "" : inputString; } else if (selectedValue == null) { return ""; } else if (_this.doesEndBoundaryOverlapStartBoundary(selectedValue, boundary)) { return _this.props.overlappingDatesMessage; } else { return getFormattedDateString(selectedValue, _this.props); } }; _this.getInputPlaceholderString = function (boundary) { var isStartBoundary = boundary === Boundary.START; var isEndBoundary = boundary === Boundary.END; var inputProps = _this.getInputProps(boundary); var isInputFocused = _this.getStateKeysAndValuesForBoundary(boundary).values.isInputFocused; // use the custom placeholder text for the input, if providied if (inputProps.placeholder != null) { return inputProps.placeholder; } else if (isStartBoundary) { return isInputFocused ? _this.state.formattedMinDateString : "Start date"; } else if (isEndBoundary) { return isInputFocused ? _this.state.formattedMaxDateString : "End date"; } else { return ""; } }; _this.getInputProps = function (boundary) { return boundary === Boundary.START ? _this.props.startInputProps : _this.props.endInputProps; }; _this.getInputRef = function (boundary) { return boundary === Boundary.START ? _this.handleStartInputRef : _this.handleEndInputRef; }; _this.getStateKeysAndValuesForBoundary = function (boundary) { var controlledRange = _this.props.value; if (boundary === Boundary.START) { return { keys: { hoverString: "startHoverString", inputString: "startInputString", isInputFocused: "isStartInputFocused", selectedValue: "selectedStart", }, values: { controlledValue: controlledRange != null ? controlledRange[0] : undefined, hoverString: _this.state.startHoverString, inputString: _this.state.startInputString, isInputFocused: _this.state.isStartInputFocused, selectedValue: _this.state.selectedStart, }, }; } else { return { keys: { hoverString: "endHoverString", inputString: "endInputString", isInputFocused: "isEndInputFocused", selectedValue: "selectedEnd", }, values: { controlledValue: controlledRange != null ? controlledRange[1] : undefined, hoverString: _this.state.endHoverString, inputString: _this.state.endInputString, isInputFocused: _this.state.isEndInputFocused, selectedValue: _this.state.selectedEnd, }, }; } }; _this.getDateRangeForCallback = function (currDate, currBoundary) { var otherBoundary = _this.getOtherBoundary(currBoundary); var otherDate = _this.getStateKeysAndValuesForBoundary(otherBoundary).values.selectedValue; return currBoundary === Boundary.START ? [currDate, otherDate] : [otherDate, currDate]; }; _this.getOtherBoundary = function (boundary) { return boundary === Boundary.START ? Boundary.END : Boundary.START; }; _this.doBoundaryDatesOverlap = function (date, boundary) { var allowSingleDayRange = _this.props.allowSingleDayRange; var otherBoundary = _this.getOtherBoundary(boundary); var otherBoundaryDate = _this.getStateKeysAndValuesForBoundary(otherBoundary).values.selectedValue; if (date == null || otherBoundaryDate == null) { return false; } if (boundary === Boundary.START) { var isAfter = date > otherBoundaryDate; return isAfter || (!allowSingleDayRange && DayPicker.DateUtils.isSameDay(date, otherBoundaryDate)); } else { var isBefore = date < otherBoundaryDate; return isBefore || (!allowSingleDayRange && DayPicker.DateUtils.isSameDay(date, otherBoundaryDate)); } }; /** * Returns true if the provided boundary is an END boundary overlapping the * selected start date. (If the boundaries overlap, we consider the END * boundary to be erroneous.) */ _this.doesEndBoundaryOverlapStartBoundary = function (boundaryDate, boundary) { return boundary === Boundary.START ? false : _this.doBoundaryDatesOverlap(boundaryDate, boundary); }; _this.isControlled = function () { return _this.props.value !== undefined; }; _this.isInputEmpty = function (inputString) { return inputString == null || inputString.length === 0; }; _this.isInputInErrorState = function (boundary) { var values = _this.getStateKeysAndValuesForBoundary(boundary).values; var isInputFocused = values.isInputFocused, hoverString = values.hoverString, inputString = values.inputString, selectedValue = values.selectedValue; if (hoverString != null || _this.isInputEmpty(inputString)) { // don't show an error state while we're hovering over a valid date. return false; } var boundaryValue = isInputFocused ? _this.parseDate(inputString) : selectedValue; return (boundaryValue != null && (!_this.isDateValidAndInRange(boundaryValue) || _this.doesEndBoundaryOverlapStartBoundary(boundaryValue, boundary))); }; _this.isDateValidAndInRange = function (date) { return isDateValid(date) && isDayInRange(date, [_this.props.minDate, _this.props.maxDate]); }; _this.reset(props); return _this; } /** * Public method intended for unit testing only. Do not use in feature work! */ DateRangeInput.prototype.reset = function (props) { if (props === void 0) { props = this.props; } var _a = this.getInitialRange(), selectedStart = _a[0], selectedEnd = _a[1]; this.state = { formattedMaxDateString: this.getFormattedMinMaxDateString(props, "maxDate"), formattedMinDateString: this.getFormattedMinMaxDateString(props, "minDate"), isOpen: false, selectedEnd: selectedEnd, selectedShortcutIndex: -1, selectedStart: selectedStart, }; }; DateRangeInput.prototype.componentDidUpdate = function (prevProps, prevState) { var _a, _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; _super.prototype.componentDidUpdate.call(this, prevProps, prevState); var _r = this.state, isStartInputFocused = _r.isStartInputFocused, isEndInputFocused = _r.isEndInputFocused, shouldSelectAfterUpdate = _r.shouldSelectAfterUpdate; if (((_a = prevProps.startInputProps) === null || _a === void 0 ? void 0 : _a.inputRef) !== ((_b = this.props.startInputProps) === null || _b === void 0 ? void 0 : _b.inputRef)) { setRef((_c = prevProps.startInputProps) === null || _c === void 0 ? void 0 : _c.inputRef, null); this.handleStartInputRef = refHandler(this, "startInputElement", (_d = this.props.startInputProps) === null || _d === void 0 ? void 0 : _d.inputRef); setRef((_f = this.props.startInputProps) === null || _f === void 0 ? void 0 : _f.inputRef, this.startInputElement); } if (((_g = prevProps.endInputProps) === null || _g === void 0 ? void 0 : _g.inputRef) !== ((_h = this.props.endInputProps) === null || _h === void 0 ? void 0 : _h.inputRef)) { setRef((_j = prevProps.endInputProps) === null || _j === void 0 ? void 0 : _j.inputRef, null); this.handleEndInputRef = refHandler(this, "endInputElement", (_k = this.props.endInputProps) === null || _k === void 0 ? void 0 : _k.inputRef); setRef((_l = this.props.endInputProps) === null || _l === void 0 ? void 0 : _l.inputRef, this.endInputElement); } var shouldFocusStartInput = this.shouldFocusInputRef(isStartInputFocused, this.startInputElement); var shouldFocusEndInput = this.shouldFocusInputRef(isEndInputFocused, this.endInputElement); if (shouldFocusStartInput) { (_m = this.startInputElement) === null || _m === void 0 ? void 0 : _m.focus(); } else if (shouldFocusEndInput) { (_o = this.endInputElement) === null || _o === void 0 ? void 0 : _o.focus(); } if (isStartInputFocused && shouldSelectAfterUpdate) { (_p = this.startInputElement) === null || _p === void 0 ? void 0 : _p.select(); } else if (isEndInputFocused && shouldSelectAfterUpdate) { (_q = this.endInputElement) === null || _q === void 0 ? void 0 : _q.select(); } var nextState = {}; if (this.props.value !== prevProps.value) { var _s = this.getInitialRange(this.props), selectedStart = _s[0], selectedEnd = _s[1]; nextState = __assign(__assign({}, nextState), { selectedStart: selectedStart, selectedEnd: selectedEnd }); } // cache the formatted date strings to avoid computing on each render. if (this.props.minDate !== prevProps.minDate) { var formattedMinDateString = this.getFormattedMinMaxDateString(this.props, "minDate"); nextState = __assign(__assign({}, nextState), { formattedMinDateString: formattedMinDateString }); } if (this.props.maxDate !== prevProps.maxDate) { var formattedMaxDateString = this.getFormattedMinMaxDateString(this.props, "maxDate"); nextState = __assign(__assign({}, nextState), { formattedMaxDateString: formattedMaxDateString }); } this.setState(nextState); }; DateRangeInput.prototype.render = function () { var selectedShortcutIndex = this.state.selectedShortcutIndex; var _a = this.props.popoverProps, popoverProps = _a === void 0 ? {} : _a; var popoverContent = (React.createElement(DateRangePicker, __assign({}, this.props, { selectedShortcutIndex: selectedShortcutIndex, boundaryToModify: this.state.boundaryToModify, onChange: this.handleDateRangePickerChange, onShortcutChange: this.handleShortcutChange, onHoverChange: this.handleDateRangePickerHoverChange, value: this.getSelectedRange() }))); var popoverClassName = classNames(popoverProps.className, this.props.className); // allow custom props for the popover and each input group, but pass them in an order that // guarantees only some props are overridable. return (React.createElement(Popover, __assign({ isOpen: this.state.isOpen, position: Position.BOTTOM_LEFT }, this.props.popoverProps, { autoFocus: false, className: popoverClassName, content: popoverContent, enforceFocus: false, onClose: this.handlePopoverClose }), React.createElement("div", { className: Classes.CONTROL_GROUP }, this.renderInputGroup(Boundary.START), this.renderInputGroup(Boundary.END)))); }; DateRangeInput.prototype.validateProps = function (props) { if (props.value === null) { throw new Error(Errors.DATERANGEINPUT_NULL_VALUE); } }; // Helpers // ======= DateRangeInput.prototype.shouldFocusInputRef = function (isFocused, inputRef) { return isFocused && inputRef !== undefined && document.activeElement !== inputRef; }; DateRangeInput.prototype.isNextDateRangeValid = function (nextDate, boundary) { return this.isDateValidAndInRange(nextDate) && !this.doBoundaryDatesOverlap(nextDate, boundary); }; // this is a slightly kludgy function, but it saves us a good amount of repeated code between // the constructor and componentDidUpdate. DateRangeInput.prototype.getFormattedMinMaxDateString = function (props, propName) { var date = props[propName]; var defaultDate = DateRangeInput.defaultProps[propName]; // default values are applied only if a prop is strictly `undefined` // See: https://facebook.github.io/react/docs/react-component.html#defaultprops return getFormattedDateString(date === undefined ? defaultDate : date, this.props); }; DateRangeInput.prototype.parseDate = function (dateString) { if (dateString === this.props.outOfRangeMessage || dateString === this.props.invalidDateMessage) { return null; } var _a = this.props, locale = _a.locale, parseDate = _a.parseDate; var newDate = parseDate(dateString, locale); return newDate === false ? new Date(undefined) : newDate; }; DateRangeInput.prototype.formatDate = function (date) { if (!this.isDateValidAndInRange(date)) { return ""; } var _a = this.props, locale = _a.locale, formatDate = _a.formatDate; return formatDate(date, locale); }; DateRangeInput.defaultProps = { allowSingleDayRange: false, closeOnSelection: true, contiguousCalendarMonths: true, dayPickerProps: {}, disabled: false, endInputProps: {}, invalidDateMessage: "Invalid date", maxDate: getDefaultMaxDate(), minDate: getDefaultMinDate(), outOfRangeMessage: "Out of range", overlappingDatesMessage: "Overlapping dates", popoverProps: {}, selectAllOnFocus: false, shortcuts: true, singleMonthOnly: false, startInputProps: {}, }; DateRangeInput.displayName = "".concat(DISPLAYNAME_PREFIX, ".DateRangeInput"); return DateRangeInput; }(AbstractPureComponent2)); export { DateRangeInput }; //# sourceMappingURL=dateRangeInput.js.map