UNPKG

16.6 kBJavaScriptView Raw
1"use strict";
2/*
3 * Copyright 2015 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.DatePicker = void 0;
19var tslib_1 = require("tslib");
20var classnames_1 = tslib_1.__importDefault(require("classnames"));
21var React = tslib_1.__importStar(require("react"));
22var react_day_picker_1 = tslib_1.__importDefault(require("react-day-picker"));
23var core_1 = require("@blueprintjs/core");
24var Classes = tslib_1.__importStar(require("./common/classes"));
25var DateUtils = tslib_1.__importStar(require("./common/dateUtils"));
26var Errors = tslib_1.__importStar(require("./common/errors"));
27var datePickerCaption_1 = require("./datePickerCaption");
28var datePickerCore_1 = require("./datePickerCore");
29var datePickerNavbar_1 = require("./datePickerNavbar");
30var shortcuts_1 = require("./shortcuts");
31var timePicker_1 = require("./timePicker");
32var DatePicker = /** @class */ (function (_super) {
33 tslib_1.__extends(DatePicker, _super);
34 function DatePicker(props, context) {
35 var _this = _super.call(this, props, context) || this;
36 _this.ignoreNextMonthChange = false;
37 _this.shouldHighlightCurrentDay = function (date) {
38 var highlightCurrentDay = _this.props.highlightCurrentDay;
39 return highlightCurrentDay && DateUtils.isToday(date);
40 };
41 _this.getDatePickerModifiers = function () {
42 var modifiers = _this.props.modifiers;
43 return tslib_1.__assign({ isToday: _this.shouldHighlightCurrentDay }, modifiers);
44 };
45 _this.renderDay = function (day) {
46 var date = day.getDate();
47 return React.createElement("div", { className: Classes.DATEPICKER_DAY_WRAPPER }, date);
48 };
49 _this.disabledDays = function (day) { return !DateUtils.isDayInRange(day, [_this.props.minDate, _this.props.maxDate]); };
50 _this.getDisabledDaysModifier = function () {
51 var disabledDays = _this.props.dayPickerProps.disabledDays;
52 return Array.isArray(disabledDays) ? tslib_1.__spreadArray([_this.disabledDays], disabledDays, true) : [_this.disabledDays, disabledDays];
53 };
54 _this.renderCaption = function (props) { return (React.createElement(datePickerCaption_1.DatePickerCaption, tslib_1.__assign({}, props, { maxDate: _this.props.maxDate, minDate: _this.props.minDate, onDateChange: _this.handleMonthChange, reverseMonthAndYearMenus: _this.props.reverseMonthAndYearMenus }))); };
55 _this.renderNavbar = function (props) { return (React.createElement(datePickerNavbar_1.DatePickerNavbar, tslib_1.__assign({}, props, { maxDate: _this.props.maxDate, minDate: _this.props.minDate }))); };
56 _this.handleDayClick = function (day, modifiers, e) {
57 var _a, _b;
58 (_b = (_a = _this.props.dayPickerProps).onDayClick) === null || _b === void 0 ? void 0 : _b.call(_a, day, modifiers, e);
59 if (modifiers.disabled) {
60 return;
61 }
62 _this.updateDay(day);
63 // allow toggling selected date by clicking it again (if prop enabled)
64 var newValue = _this.props.canClearSelection && modifiers.selected ? null : DateUtils.getDateTime(day, _this.state.value);
65 _this.updateValue(newValue, true);
66 };
67 _this.handleShortcutClick = function (shortcut, selectedShortcutIndex) {
68 var _a = _this.props, onShortcutChange = _a.onShortcutChange, currentShortcutIndex = _a.selectedShortcutIndex;
69 var dateRange = shortcut.dateRange, includeTime = shortcut.includeTime;
70 var newDate = dateRange[0];
71 var newValue = includeTime ? newDate : DateUtils.getDateTime(newDate, _this.state.value);
72 _this.updateDay(newDate);
73 _this.updateValue(newValue, true);
74 if (currentShortcutIndex === undefined) {
75 _this.setState({ selectedShortcutIndex: selectedShortcutIndex });
76 }
77 var datePickerShortcut = tslib_1.__assign(tslib_1.__assign({}, shortcut), { date: shortcut.dateRange[0] });
78 onShortcutChange === null || onShortcutChange === void 0 ? void 0 : onShortcutChange(datePickerShortcut, selectedShortcutIndex);
79 };
80 _this.updateDay = function (day) {
81 if (_this.props.value === undefined) {
82 // set now if uncontrolled, otherwise they'll be updated in `componentDidUpdate`
83 _this.setState({
84 displayMonth: day.getMonth(),
85 displayYear: day.getFullYear(),
86 selectedDay: day.getDate(),
87 });
88 }
89 if (_this.state.value != null && _this.state.value.getMonth() !== day.getMonth()) {
90 _this.ignoreNextMonthChange = true;
91 }
92 };
93 _this.handleClearClick = function () { return _this.updateValue(null, true); };
94 _this.handleMonthChange = function (newDate) {
95 var _a, _b;
96 var date = _this.computeValidDateInSpecifiedMonthYear(newDate.getFullYear(), newDate.getMonth());
97 _this.setState({ displayMonth: date.getMonth(), displayYear: date.getFullYear() });
98 if (_this.state.value !== null) {
99 // if handleDayClick just got run (so this flag is set), then the
100 // user selected a date in a new month, so don't invoke onChange a
101 // second time
102 _this.updateValue(date, false, _this.ignoreNextMonthChange);
103 _this.ignoreNextMonthChange = false;
104 }
105 (_b = (_a = _this.props.dayPickerProps).onMonthChange) === null || _b === void 0 ? void 0 : _b.call(_a, date);
106 };
107 _this.handleTodayClick = function () {
108 var value = new Date();
109 var displayMonth = value.getMonth();
110 var displayYear = value.getFullYear();
111 var selectedDay = value.getDate();
112 _this.setState({ displayMonth: displayMonth, displayYear: displayYear, selectedDay: selectedDay });
113 _this.updateValue(value, true);
114 };
115 _this.handleTimeChange = function (time) {
116 var _a, _b;
117 (_b = (_a = _this.props.timePickerProps) === null || _a === void 0 ? void 0 : _a.onChange) === null || _b === void 0 ? void 0 : _b.call(_a, time);
118 var value = _this.state.value;
119 var newValue = DateUtils.getDateTime(value != null ? value : new Date(), time);
120 _this.updateValue(newValue, true);
121 };
122 var value = getInitialValue(props);
123 var initialMonth = getInitialMonth(props, value);
124 _this.state = {
125 displayMonth: initialMonth.getMonth(),
126 displayYear: initialMonth.getFullYear(),
127 selectedDay: value == null ? null : value.getDate(),
128 selectedShortcutIndex: _this.props.selectedShortcutIndex !== undefined ? _this.props.selectedShortcutIndex : -1,
129 value: value,
130 };
131 return _this;
132 }
133 DatePicker.prototype.render = function () {
134 var _a;
135 var _b = this.props, className = _b.className, dayPickerProps = _b.dayPickerProps, locale = _b.locale, localeUtils = _b.localeUtils, maxDate = _b.maxDate, minDate = _b.minDate, showActionsBar = _b.showActionsBar;
136 var _c = this.state, displayMonth = _c.displayMonth, displayYear = _c.displayYear;
137 return (React.createElement("div", { className: (0, classnames_1.default)(Classes.DATEPICKER, className) },
138 this.maybeRenderShortcuts(),
139 React.createElement("div", null,
140 React.createElement(react_day_picker_1.default, tslib_1.__assign({ showOutsideDays: true, locale: locale, localeUtils: localeUtils, modifiers: this.getDatePickerModifiers() }, dayPickerProps, { canChangeMonth: true, captionElement: this.renderCaption, navbarElement: this.renderNavbar, disabledDays: this.getDisabledDaysModifier(), fromMonth: minDate, month: new Date(displayYear, displayMonth), onDayClick: this.handleDayClick, onMonthChange: this.handleMonthChange, selectedDays: this.state.value, toMonth: maxDate, renderDay: (_a = dayPickerProps === null || dayPickerProps === void 0 ? void 0 : dayPickerProps.renderDay) !== null && _a !== void 0 ? _a : this.renderDay })),
141 this.maybeRenderTimePicker(),
142 showActionsBar && this.renderOptionsBar())));
143 };
144 DatePicker.prototype.componentDidUpdate = function (prevProps, prevState) {
145 _super.prototype.componentDidUpdate.call(this, prevProps, prevState);
146 var value = this.props.value;
147 if (value === prevProps.value) {
148 // no action needed
149 return;
150 }
151 else if (value == null) {
152 // clear the value
153 this.setState({ value: value });
154 }
155 else {
156 this.setState({
157 displayMonth: value.getMonth(),
158 displayYear: value.getFullYear(),
159 selectedDay: value.getDate(),
160 value: value,
161 });
162 }
163 if (this.props.selectedShortcutIndex !== prevProps.selectedShortcutIndex) {
164 this.setState({ selectedShortcutIndex: this.props.selectedShortcutIndex });
165 }
166 };
167 DatePicker.prototype.validateProps = function (props) {
168 var defaultValue = props.defaultValue, initialMonth = props.initialMonth, maxDate = props.maxDate, minDate = props.minDate, value = props.value;
169 if (defaultValue != null && !DateUtils.isDayInRange(defaultValue, [minDate, maxDate])) {
170 console.error(Errors.DATEPICKER_DEFAULT_VALUE_INVALID);
171 }
172 if (initialMonth != null && !DateUtils.isMonthInRange(initialMonth, [minDate, maxDate])) {
173 console.error(Errors.DATEPICKER_INITIAL_MONTH_INVALID);
174 }
175 if (maxDate != null && minDate != null && maxDate < minDate && !DateUtils.areSameDay(maxDate, minDate)) {
176 console.error(Errors.DATEPICKER_MAX_DATE_INVALID);
177 }
178 if (value != null && !DateUtils.isDayInRange(value, [minDate, maxDate])) {
179 console.error(Errors.DATEPICKER_VALUE_INVALID);
180 }
181 };
182 DatePicker.prototype.renderOptionsBar = function () {
183 var _a = this.props, clearButtonText = _a.clearButtonText, todayButtonText = _a.todayButtonText, minDate = _a.minDate, maxDate = _a.maxDate, canClearSelection = _a.canClearSelection;
184 var todayEnabled = isTodayEnabled(minDate, maxDate);
185 return [
186 React.createElement(core_1.Divider, { key: "div" }),
187 React.createElement("div", { className: Classes.DATEPICKER_FOOTER, key: "footer" },
188 React.createElement(core_1.Button, { minimal: true, disabled: !todayEnabled, onClick: this.handleTodayClick, text: todayButtonText }),
189 React.createElement(core_1.Button, { disabled: !canClearSelection, minimal: true, onClick: this.handleClearClick, text: clearButtonText })),
190 ];
191 };
192 DatePicker.prototype.maybeRenderTimePicker = function () {
193 var _a = this.props, timePrecision = _a.timePrecision, timePickerProps = _a.timePickerProps, minDate = _a.minDate, maxDate = _a.maxDate;
194 if (timePrecision == null && timePickerProps === undefined) {
195 return null;
196 }
197 var applyMin = DateUtils.areSameDay(this.state.value, minDate);
198 var applyMax = DateUtils.areSameDay(this.state.value, maxDate);
199 return (React.createElement("div", { className: Classes.DATEPICKER_TIMEPICKER_WRAPPER },
200 React.createElement(timePicker_1.TimePicker, tslib_1.__assign({ precision: timePrecision, minTime: applyMin ? minDate : undefined, maxTime: applyMax ? maxDate : undefined }, timePickerProps, { onChange: this.handleTimeChange, value: this.state.value }))));
201 };
202 DatePicker.prototype.maybeRenderShortcuts = function () {
203 var shortcuts = this.props.shortcuts;
204 if (shortcuts == null || shortcuts === false) {
205 return null;
206 }
207 var selectedShortcutIndex = this.state.selectedShortcutIndex;
208 var _a = this.props, maxDate = _a.maxDate, minDate = _a.minDate, timePrecision = _a.timePrecision;
209 // Reuse the existing date range shortcuts and only care about start date
210 var dateRangeShortcuts = shortcuts === true
211 ? true
212 : shortcuts.map(function (shortcut) { return (tslib_1.__assign(tslib_1.__assign({}, shortcut), { dateRange: [shortcut.date, undefined] })); });
213 return [
214 React.createElement(shortcuts_1.Shortcuts, tslib_1.__assign({ key: "shortcuts" }, {
215 allowSingleDayRange: true,
216 maxDate: maxDate,
217 minDate: minDate,
218 selectedShortcutIndex: selectedShortcutIndex,
219 shortcuts: dateRangeShortcuts,
220 timePrecision: timePrecision,
221 }, { onShortcutClick: this.handleShortcutClick, useSingleDateShortcuts: true })),
222 React.createElement(core_1.Divider, { key: "div" }),
223 ];
224 };
225 DatePicker.prototype.computeValidDateInSpecifiedMonthYear = function (displayYear, displayMonth) {
226 var _a = this.props, minDate = _a.minDate, maxDate = _a.maxDate;
227 var selectedDay = this.state.selectedDay;
228 // month is 0-based, date is 1-based. date 0 is last day of previous month.
229 var maxDaysInMonth = new Date(displayYear, displayMonth + 1, 0).getDate();
230 var displayDate = selectedDay == null ? 1 : Math.min(selectedDay, maxDaysInMonth);
231 // 12:00 matches the underlying react-day-picker timestamp behavior
232 var value = DateUtils.getDateTime(new Date(displayYear, displayMonth, displayDate, 12), this.state.value);
233 // clamp between min and max dates
234 if (value < minDate) {
235 return minDate;
236 }
237 else if (value > maxDate) {
238 return maxDate;
239 }
240 return value;
241 };
242 /**
243 * Update `value` by invoking `onChange` (always) and setting state (if uncontrolled).
244 */
245 DatePicker.prototype.updateValue = function (value, isUserChange, skipOnChange) {
246 var _a, _b;
247 if (skipOnChange === void 0) { skipOnChange = false; }
248 if (!skipOnChange) {
249 (_b = (_a = this.props).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, value, isUserChange);
250 }
251 if (this.props.value === undefined) {
252 this.setState({ value: value });
253 }
254 };
255 DatePicker.defaultProps = {
256 canClearSelection: true,
257 clearButtonText: "Clear",
258 dayPickerProps: {},
259 highlightCurrentDay: false,
260 maxDate: (0, datePickerCore_1.getDefaultMaxDate)(),
261 minDate: (0, datePickerCore_1.getDefaultMinDate)(),
262 reverseMonthAndYearMenus: false,
263 shortcuts: false,
264 showActionsBar: false,
265 todayButtonText: "Today",
266 };
267 DatePicker.displayName = "".concat(core_1.DISPLAYNAME_PREFIX, ".DatePicker");
268 return DatePicker;
269}(core_1.AbstractPureComponent2));
270exports.DatePicker = DatePicker;
271function getInitialValue(props) {
272 // !== because `null` is a valid value (no date)
273 if (props.value !== undefined) {
274 return props.value;
275 }
276 if (props.defaultValue !== undefined) {
277 return props.defaultValue;
278 }
279 return null;
280}
281function getInitialMonth(props, value) {
282 var today = new Date();
283 // != because we must have a real `Date` to begin the calendar on.
284 if (props.initialMonth != null) {
285 return props.initialMonth;
286 }
287 else if (value != null) {
288 return value;
289 }
290 else if (DateUtils.isDayInRange(today, [props.minDate, props.maxDate])) {
291 return today;
292 }
293 else {
294 return DateUtils.getDateBetween([props.minDate, props.maxDate]);
295 }
296}
297function isTodayEnabled(minDate, maxDate) {
298 var today = new Date();
299 return DateUtils.isDayInRange(today, [minDate, maxDate]);
300}
301//# sourceMappingURL=datePicker.js.map
\No newline at end of file