UNPKG

16.7 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.TimePicker = exports.TimePrecision = void 0;
19var tslib_1 = require("tslib");
20var classnames_1 = tslib_1.__importDefault(require("classnames"));
21var React = tslib_1.__importStar(require("react"));
22var core_1 = require("@blueprintjs/core");
23var Classes = tslib_1.__importStar(require("./common/classes"));
24var DateUtils = tslib_1.__importStar(require("./common/dateUtils"));
25var timeUnit_1 = require("./common/timeUnit");
26var Utils = tslib_1.__importStar(require("./common/utils"));
27exports.TimePrecision = {
28 MILLISECOND: "millisecond",
29 MINUTE: "minute",
30 SECOND: "second",
31};
32/**
33 * Time picker component.
34 *
35 * @see https://blueprintjs.com/docs/#datetime/timepicker
36 */
37var TimePicker = /** @class */ (function (_super) {
38 tslib_1.__extends(TimePicker, _super);
39 function TimePicker(props, context) {
40 var _a;
41 var _this = _super.call(this, props, context) || this;
42 _this.timeInputIds = (_a = {},
43 _a[timeUnit_1.TimeUnit.HOUR_24] = core_1.Utils.uniqueId(timeUnit_1.TimeUnit.HOUR_24 + "-input"),
44 _a[timeUnit_1.TimeUnit.HOUR_12] = core_1.Utils.uniqueId(timeUnit_1.TimeUnit.HOUR_12 + "-input"),
45 _a[timeUnit_1.TimeUnit.MINUTE] = core_1.Utils.uniqueId(timeUnit_1.TimeUnit.MINUTE + "-input"),
46 _a[timeUnit_1.TimeUnit.SECOND] = core_1.Utils.uniqueId(timeUnit_1.TimeUnit.SECOND + "-input"),
47 _a[timeUnit_1.TimeUnit.MS] = core_1.Utils.uniqueId(timeUnit_1.TimeUnit.MS + "-input"),
48 _a);
49 // begin method definitions: event handlers
50 _this.getInputChangeHandler = function (unit) { return function (e) {
51 var text = getStringValueFromInputEvent(e);
52 switch (unit) {
53 case timeUnit_1.TimeUnit.HOUR_12:
54 case timeUnit_1.TimeUnit.HOUR_24:
55 _this.setState({ hourText: text });
56 break;
57 case timeUnit_1.TimeUnit.MINUTE:
58 _this.setState({ minuteText: text });
59 break;
60 case timeUnit_1.TimeUnit.SECOND:
61 _this.setState({ secondText: text });
62 break;
63 case timeUnit_1.TimeUnit.MS:
64 _this.setState({ millisecondText: text });
65 break;
66 }
67 }; };
68 _this.getInputBlurHandler = function (unit) { return function (e) {
69 var _a, _b;
70 var text = getStringValueFromInputEvent(e);
71 _this.updateTime(parseInt(text, 10), unit);
72 (_b = (_a = _this.props).onBlur) === null || _b === void 0 ? void 0 : _b.call(_a, e, unit);
73 }; };
74 _this.getInputFocusHandler = function (unit) { return function (e) {
75 var _a, _b;
76 if (_this.props.selectAllOnFocus) {
77 e.currentTarget.select();
78 }
79 (_b = (_a = _this.props).onFocus) === null || _b === void 0 ? void 0 : _b.call(_a, e, unit);
80 }; };
81 _this.getInputKeyDownHandler = function (unit) { return function (e) {
82 var _a;
83 var _b, _c;
84 handleKeyEvent(e, (_a = {},
85 _a[core_1.Keys.ARROW_UP] = function () { return _this.incrementTime(unit); },
86 _a[core_1.Keys.ARROW_DOWN] = function () { return _this.decrementTime(unit); },
87 _a[core_1.Keys.ENTER] = function () {
88 e.currentTarget.blur();
89 },
90 _a));
91 (_c = (_b = _this.props).onKeyDown) === null || _c === void 0 ? void 0 : _c.call(_b, e, unit);
92 }; };
93 _this.getInputKeyUpHandler = function (unit) { return function (e) {
94 var _a, _b;
95 (_b = (_a = _this.props).onKeyUp) === null || _b === void 0 ? void 0 : _b.call(_a, e, unit);
96 }; };
97 _this.handleAmPmChange = function (e) {
98 var isNextPm = e.currentTarget.value === "pm";
99 if (isNextPm !== _this.state.isPm) {
100 var hour_1 = DateUtils.convert24HourMeridiem(_this.state.value.getHours(), isNextPm);
101 _this.setState({ isPm: isNextPm }, function () { return _this.updateTime(hour_1, timeUnit_1.TimeUnit.HOUR_24); });
102 }
103 };
104 _this.incrementTime = function (unit) { return _this.shiftTime(unit, 1); };
105 _this.decrementTime = function (unit) { return _this.shiftTime(unit, -1); };
106 _this.state = _this.getFullStateFromValue(_this.getInitialValue(), props.useAmPm);
107 return _this;
108 }
109 TimePicker.prototype.render = function () {
110 var _a;
111 var shouldRenderMilliseconds = this.props.precision === exports.TimePrecision.MILLISECOND;
112 var shouldRenderSeconds = shouldRenderMilliseconds || this.props.precision === exports.TimePrecision.SECOND;
113 var hourUnit = this.props.useAmPm ? timeUnit_1.TimeUnit.HOUR_12 : timeUnit_1.TimeUnit.HOUR_24;
114 var classes = (0, classnames_1.default)(Classes.TIMEPICKER, this.props.className, (_a = {},
115 _a[core_1.Classes.DISABLED] = this.props.disabled,
116 _a));
117 return (React.createElement("div", { className: classes },
118 React.createElement("div", { className: Classes.TIMEPICKER_ARROW_ROW },
119 this.maybeRenderArrowButton(true, hourUnit),
120 this.maybeRenderArrowButton(true, timeUnit_1.TimeUnit.MINUTE),
121 shouldRenderSeconds && this.maybeRenderArrowButton(true, timeUnit_1.TimeUnit.SECOND),
122 shouldRenderMilliseconds && this.maybeRenderArrowButton(true, timeUnit_1.TimeUnit.MS)),
123 React.createElement("div", { className: Classes.TIMEPICKER_INPUT_ROW },
124 this.renderInput(Classes.TIMEPICKER_HOUR, hourUnit, this.state.hourText),
125 this.renderDivider(),
126 this.renderInput(Classes.TIMEPICKER_MINUTE, timeUnit_1.TimeUnit.MINUTE, this.state.minuteText),
127 shouldRenderSeconds && this.renderDivider(),
128 shouldRenderSeconds &&
129 this.renderInput(Classes.TIMEPICKER_SECOND, timeUnit_1.TimeUnit.SECOND, this.state.secondText),
130 shouldRenderMilliseconds && this.renderDivider("."),
131 shouldRenderMilliseconds &&
132 this.renderInput(Classes.TIMEPICKER_MILLISECOND, timeUnit_1.TimeUnit.MS, this.state.millisecondText)),
133 this.maybeRenderAmPm(),
134 React.createElement("div", { className: Classes.TIMEPICKER_ARROW_ROW },
135 this.maybeRenderArrowButton(false, hourUnit),
136 this.maybeRenderArrowButton(false, timeUnit_1.TimeUnit.MINUTE),
137 shouldRenderSeconds && this.maybeRenderArrowButton(false, timeUnit_1.TimeUnit.SECOND),
138 shouldRenderMilliseconds && this.maybeRenderArrowButton(false, timeUnit_1.TimeUnit.MS))));
139 };
140 TimePicker.prototype.componentDidUpdate = function (prevProps) {
141 var didMinTimeChange = prevProps.minTime !== this.props.minTime;
142 var didMaxTimeChange = prevProps.maxTime !== this.props.maxTime;
143 var didBoundsChange = didMinTimeChange || didMaxTimeChange;
144 var didPropValueChange = prevProps.value !== this.props.value;
145 var shouldStateUpdate = didBoundsChange || didPropValueChange;
146 var value = this.state.value;
147 if (this.props.value == null) {
148 value = this.getInitialValue();
149 }
150 if (didBoundsChange) {
151 value = DateUtils.getTimeInRange(this.state.value, this.props.minTime, this.props.maxTime);
152 }
153 if (this.props.value != null && !DateUtils.areSameTime(this.props.value, prevProps.value)) {
154 value = this.props.value;
155 }
156 if (shouldStateUpdate) {
157 this.setState(this.getFullStateFromValue(value, this.props.useAmPm));
158 }
159 };
160 // begin method definitions: rendering
161 TimePicker.prototype.maybeRenderArrowButton = function (isDirectionUp, timeUnit) {
162 var _this = this;
163 if (!this.props.showArrowButtons) {
164 return null;
165 }
166 var classes = (0, classnames_1.default)(Classes.TIMEPICKER_ARROW_BUTTON, (0, timeUnit_1.getTimeUnitClassName)(timeUnit));
167 var onClick = function () { return (isDirectionUp ? _this.incrementTime : _this.decrementTime)(timeUnit); };
168 var label = "".concat(isDirectionUp ? "Increase" : "Decrease", " ").concat((0, timeUnit_1.getTimeUnitPrintStr)(timeUnit));
169 // set tabIndex=-1 to ensure a valid FocusEvent relatedTarget when focused
170 return (React.createElement("span", { "aria-controls": this.timeInputIds[timeUnit], "aria-label": label, tabIndex: -1, className: classes, onClick: onClick },
171 React.createElement(core_1.Icon, { icon: isDirectionUp ? "chevron-up" : "chevron-down", title: label })));
172 };
173 TimePicker.prototype.renderDivider = function (text) {
174 if (text === void 0) { text = ":"; }
175 return React.createElement("span", { className: Classes.TIMEPICKER_DIVIDER_TEXT }, text);
176 };
177 TimePicker.prototype.renderInput = function (className, unit, value) {
178 var _a;
179 var valueNumber = parseInt(value, 10);
180 var isValid = (0, timeUnit_1.isTimeUnitValid)(unit, valueNumber);
181 var isHour = unit === timeUnit_1.TimeUnit.HOUR_12 || unit === timeUnit_1.TimeUnit.HOUR_24;
182 return (React.createElement("input", { "aria-label": (0, timeUnit_1.getTimeUnitPrintStr)(unit), "aria-valuemin": 0, "aria-valuenow": valueNumber, "aria-valuemax": (0, timeUnit_1.getTimeUnitMax)(unit), className: (0, classnames_1.default)(Classes.TIMEPICKER_INPUT, (_a = {}, _a[core_1.Classes.intentClass(core_1.Intent.DANGER)] = !isValid, _a), className), id: this.timeInputIds[unit], onBlur: this.getInputBlurHandler(unit), onChange: this.getInputChangeHandler(unit), onFocus: this.getInputFocusHandler(unit), onKeyDown: this.getInputKeyDownHandler(unit), onKeyUp: this.getInputKeyUpHandler(unit), role: this.props.showArrowButtons ? "spinbutton" : undefined, value: value, disabled: this.props.disabled, autoFocus: isHour && this.props.autoFocus }));
183 };
184 TimePicker.prototype.maybeRenderAmPm = function () {
185 if (!this.props.useAmPm) {
186 return null;
187 }
188 return (React.createElement(core_1.HTMLSelect, { className: Classes.TIMEPICKER_AMPM_SELECT, disabled: this.props.disabled, onChange: this.handleAmPmChange, value: this.state.isPm ? "pm" : "am" },
189 React.createElement("option", { value: "am" }, "AM"),
190 React.createElement("option", { value: "pm" }, "PM")));
191 };
192 // begin method definitions: state modification
193 /**
194 * Generates a full ITimePickerState object with all text fields set to formatted strings based on value
195 */
196 TimePicker.prototype.getFullStateFromValue = function (value, useAmPm) {
197 var timeInRange = DateUtils.getTimeInRange(value, this.props.minTime, this.props.maxTime);
198 var hourUnit = useAmPm ? timeUnit_1.TimeUnit.HOUR_12 : timeUnit_1.TimeUnit.HOUR_24;
199 /* tslint:disable:object-literal-sort-keys */
200 return {
201 hourText: formatTime(timeInRange.getHours(), hourUnit),
202 minuteText: formatTime(timeInRange.getMinutes(), timeUnit_1.TimeUnit.MINUTE),
203 secondText: formatTime(timeInRange.getSeconds(), timeUnit_1.TimeUnit.SECOND),
204 millisecondText: formatTime(timeInRange.getMilliseconds(), timeUnit_1.TimeUnit.MS),
205 value: timeInRange,
206 isPm: DateUtils.getIsPmFrom24Hour(timeInRange.getHours()),
207 };
208 /* tslint:enable:object-literal-sort-keys */
209 };
210 TimePicker.prototype.shiftTime = function (unit, amount) {
211 if (this.props.disabled) {
212 return;
213 }
214 var newTime = (0, timeUnit_1.getTimeUnit)(unit, this.state.value) + amount;
215 this.updateTime((0, timeUnit_1.wrapTimeAtUnit)(unit, newTime), unit);
216 };
217 TimePicker.prototype.updateTime = function (time, unit) {
218 var newValue = DateUtils.clone(this.state.value);
219 if ((0, timeUnit_1.isTimeUnitValid)(unit, time)) {
220 (0, timeUnit_1.setTimeUnit)(unit, time, newValue, this.state.isPm);
221 if (DateUtils.isTimeInRange(newValue, this.props.minTime, this.props.maxTime)) {
222 this.updateState({ value: newValue });
223 }
224 else {
225 this.updateState(this.getFullStateFromValue(this.state.value, this.props.useAmPm));
226 }
227 }
228 else {
229 this.updateState(this.getFullStateFromValue(this.state.value, this.props.useAmPm));
230 }
231 };
232 TimePicker.prototype.updateState = function (state) {
233 var _a, _b;
234 var newState = state;
235 var hasNewValue = newState.value != null && !DateUtils.areSameTime(newState.value, this.state.value);
236 if (this.props.value == null) {
237 // component is uncontrolled
238 if (hasNewValue) {
239 newState = this.getFullStateFromValue(newState.value, this.props.useAmPm);
240 }
241 this.setState(newState);
242 }
243 else {
244 // component is controlled, and there's a new value
245 // so set inputs' text based off of _old_ value and later fire onChange with new value
246 if (hasNewValue) {
247 this.setState(this.getFullStateFromValue(this.state.value, this.props.useAmPm));
248 }
249 else {
250 // no new value, this means only text has changed (from user typing)
251 // we want inputs to change, so update state with new text for the inputs
252 // but don't change actual value
253 this.setState(tslib_1.__assign(tslib_1.__assign({}, newState), { value: DateUtils.clone(this.state.value) }));
254 }
255 }
256 if (hasNewValue) {
257 (_b = (_a = this.props).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, newState.value);
258 }
259 };
260 TimePicker.prototype.getInitialValue = function () {
261 var value = this.props.minTime;
262 if (this.props.value != null) {
263 value = this.props.value;
264 }
265 else if (this.props.defaultValue != null) {
266 value = this.props.defaultValue;
267 }
268 return value;
269 };
270 TimePicker.defaultProps = {
271 autoFocus: false,
272 disabled: false,
273 maxTime: (0, timeUnit_1.getDefaultMaxTime)(),
274 minTime: (0, timeUnit_1.getDefaultMinTime)(),
275 precision: exports.TimePrecision.MINUTE,
276 selectAllOnFocus: false,
277 showArrowButtons: false,
278 useAmPm: false,
279 };
280 TimePicker.displayName = "".concat(core_1.DISPLAYNAME_PREFIX, ".TimePicker");
281 return TimePicker;
282}(React.Component));
283exports.TimePicker = TimePicker;
284function formatTime(time, unit) {
285 switch (unit) {
286 case timeUnit_1.TimeUnit.HOUR_24:
287 return time.toString();
288 case timeUnit_1.TimeUnit.HOUR_12:
289 return DateUtils.get12HourFrom24Hour(time).toString();
290 case timeUnit_1.TimeUnit.MINUTE:
291 case timeUnit_1.TimeUnit.SECOND:
292 return Utils.padWithZeroes(time.toString(), 2);
293 case timeUnit_1.TimeUnit.MS:
294 return Utils.padWithZeroes(time.toString(), 3);
295 default:
296 throw Error("Invalid TimeUnit");
297 }
298}
299function getStringValueFromInputEvent(e) {
300 return e.target.value;
301}
302function handleKeyEvent(e, actions, preventDefault) {
303 if (preventDefault === void 0) { preventDefault = true; }
304 for (var _i = 0, _a = Object.keys(actions); _i < _a.length; _i++) {
305 var k = _a[_i];
306 var key = Number(k);
307 // HACKHACK: https://github.com/palantir/blueprint/issues/4165
308 // eslint-disable-next-line deprecation/deprecation
309 if (e.which === key) {
310 if (preventDefault) {
311 e.preventDefault();
312 }
313 actions[key]();
314 }
315 }
316}
317//# sourceMappingURL=timePicker.js.map
\No newline at end of file