UNPKG

ngx-bootstrap-ci

Version:
1,008 lines (993 loc) 93.1 kB
import { Injectable, ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, forwardRef, Input, Output, ViewEncapsulation, NgModule } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { MiniStore, MiniState } from 'ngx-bootstrap/mini-ngrx'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { CommonModule } from '@angular/common'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class TimepickerActions { /** * @param {?} value * @return {?} */ writeValue(value) { return { type: TimepickerActions.WRITE_VALUE, payload: value }; } /** * @param {?} event * @return {?} */ changeHours(event) { return { type: TimepickerActions.CHANGE_HOURS, payload: event }; } /** * @param {?} event * @return {?} */ changeMinutes(event) { return { type: TimepickerActions.CHANGE_MINUTES, payload: event }; } /** * @param {?} event * @return {?} */ changeSeconds(event) { return { type: TimepickerActions.CHANGE_SECONDS, payload: event }; } /** * @param {?} value * @return {?} */ setTime(value) { return { type: TimepickerActions.SET_TIME_UNIT, payload: value }; } /** * @param {?} value * @return {?} */ updateControls(value) { return { type: TimepickerActions.UPDATE_CONTROLS, payload: value }; } } TimepickerActions.WRITE_VALUE = '[timepicker] write value from ng model'; TimepickerActions.CHANGE_HOURS = '[timepicker] change hours'; TimepickerActions.CHANGE_MINUTES = '[timepicker] change minutes'; TimepickerActions.CHANGE_SECONDS = '[timepicker] change seconds'; TimepickerActions.SET_TIME_UNIT = '[timepicker] set time unit'; TimepickerActions.UPDATE_CONTROLS = '[timepicker] update controls'; TimepickerActions.decorators = [ { type: Injectable } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ dex = 10; const /** @type {?} */ hoursPerDay = 24; const /** @type {?} */ hoursPerDayHalf = 12; const /** @type {?} */ minutesPerHour = 60; const /** @type {?} */ secondsPerMinute = 60; /** * @param {?=} value * @return {?} */ function isValidDate(value) { if (!value) { return false; } if (value instanceof Date && isNaN(value.getHours())) { return false; } if (typeof value === 'string') { return isValidDate(new Date(value)); } return true; } /** * @param {?} controls * @param {?} newDate * @return {?} */ function isValidLimit(controls, newDate) { if (controls.min && newDate < controls.min) { return false; } if (controls.max && newDate > controls.max) { return false; } return true; } /** * @param {?} value * @return {?} */ function toNumber(value) { if (typeof value === 'number') { return value; } return parseInt(value, dex); } /** * @param {?} value * @param {?=} isPM * @return {?} */ function parseHours(value, isPM = false) { const /** @type {?} */ hour = toNumber(value); if (isNaN(hour) || hour < 0 || hour > (isPM ? hoursPerDayHalf : hoursPerDay)) { return NaN; } return hour; } /** * @param {?} value * @return {?} */ function parseMinutes(value) { const /** @type {?} */ minute = toNumber(value); if (isNaN(minute) || minute < 0 || minute > minutesPerHour) { return NaN; } return minute; } /** * @param {?} value * @return {?} */ function parseSeconds(value) { const /** @type {?} */ seconds = toNumber(value); if (isNaN(seconds) || seconds < 0 || seconds > secondsPerMinute) { return NaN; } return seconds; } /** * @param {?} value * @return {?} */ function parseTime(value) { if (typeof value === 'string') { return new Date(value); } return value; } /** * @param {?} value * @param {?} diff * @return {?} */ function changeTime(value, diff) { if (!value) { return changeTime(createDate(new Date(), 0, 0, 0), diff); } let /** @type {?} */ hour = value.getHours(); let /** @type {?} */ minutes = value.getMinutes(); let /** @type {?} */ seconds = value.getSeconds(); if (diff.hour) { hour = (hour + toNumber(diff.hour)) % hoursPerDay; if (hour < 0) { hour += hoursPerDay; } } if (diff.minute) { minutes = minutes + toNumber(diff.minute); } if (diff.seconds) { seconds = seconds + toNumber(diff.seconds); } return createDate(value, hour, minutes, seconds); } /** * @param {?} value * @param {?} opts * @return {?} */ function setTime(value, opts) { let /** @type {?} */ hour = parseHours(opts.hour); const /** @type {?} */ minute = parseMinutes(opts.minute); const /** @type {?} */ seconds = parseSeconds(opts.seconds) || 0; if (opts.isPM) { hour += hoursPerDayHalf; } if (!value) { if (!isNaN(hour) && !isNaN(minute)) { return createDate(new Date(), hour, minute, seconds); } return value; } if (isNaN(hour) || isNaN(minute)) { return value; } return createDate(value, hour, minute, seconds); } /** * @param {?} value * @param {?} hours * @param {?} minutes * @param {?} seconds * @return {?} */ function createDate(value, hours, minutes, seconds) { return new Date(value.getFullYear(), value.getMonth(), value.getDate(), hours, minutes, seconds, value.getMilliseconds()); } /** * @param {?} value * @return {?} */ function padNumber(value) { const /** @type {?} */ _value = value.toString(); if (_value.length > 1) { return _value; } return `0${_value}`; } /** * @param {?} hours * @param {?} isPM * @return {?} */ function isHourInputValid(hours, isPM) { return !isNaN(parseHours(hours, isPM)); } /** * @param {?} minutes * @return {?} */ function isMinuteInputValid(minutes) { return !isNaN(parseMinutes(minutes)); } /** * @param {?} seconds * @return {?} */ function isSecondInputValid(seconds) { return !isNaN(parseSeconds(seconds)); } /** * @param {?} diff * @param {?} max * @param {?} min * @return {?} */ function isInputLimitValid(diff, max, min) { const /** @type {?} */ newDate = changeTime(new Date(), diff); if (max && newDate > max) { return false; } if (min && newDate < min) { return false; } return true; } /** * @param {?} hours * @param {?=} minutes * @param {?=} seconds * @param {?=} isPM * @return {?} */ function isInputValid(hours, minutes = '0', seconds = '0', isPM) { return isHourInputValid(hours, isPM) && isMinuteInputValid(minutes) && isSecondInputValid(seconds); } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} state * @param {?=} event * @return {?} */ function canChangeValue(state, event) { if (state.readonlyInput || state.disabled) { return false; } if (event) { if (event.source === 'wheel' && !state.mousewheel) { return false; } if (event.source === 'key' && !state.arrowkeys) { return false; } } return true; } /** * @param {?} event * @param {?} controls * @return {?} */ function canChangeHours(event, controls) { if (!event.step) { return false; } if (event.step > 0 && !controls.canIncrementHours) { return false; } if (event.step < 0 && !controls.canDecrementHours) { return false; } return true; } /** * @param {?} event * @param {?} controls * @return {?} */ function canChangeMinutes(event, controls) { if (!event.step) { return false; } if (event.step > 0 && !controls.canIncrementMinutes) { return false; } if (event.step < 0 && !controls.canDecrementMinutes) { return false; } return true; } /** * @param {?} event * @param {?} controls * @return {?} */ function canChangeSeconds(event, controls) { if (!event.step) { return false; } if (event.step > 0 && !controls.canIncrementSeconds) { return false; } if (event.step < 0 && !controls.canDecrementSeconds) { return false; } return true; } /** * @param {?} state * @return {?} */ function getControlsValue(state) { const { hourStep, minuteStep, secondsStep, readonlyInput, disabled, mousewheel, arrowkeys, showSpinners, showMeridian, showSeconds, meridians, min, max } = state; return { hourStep, minuteStep, secondsStep, readonlyInput, disabled, mousewheel, arrowkeys, showSpinners, showMeridian, showSeconds, meridians, min, max }; } /** * @param {?} value * @param {?} state * @return {?} */ function timepickerControls(value, state) { const /** @type {?} */ hoursPerDayHalf = 12; const { min, max, hourStep, minuteStep, secondsStep, showSeconds } = state; const /** @type {?} */ res = { canIncrementHours: true, canIncrementMinutes: true, canIncrementSeconds: true, canDecrementHours: true, canDecrementMinutes: true, canDecrementSeconds: true, canToggleMeridian: true }; if (!value) { return res; } // compare dates if (max) { const /** @type {?} */ _newHour = changeTime(value, { hour: hourStep }); res.canIncrementHours = max > _newHour; if (!res.canIncrementHours) { const /** @type {?} */ _newMinutes = changeTime(value, { minute: minuteStep }); res.canIncrementMinutes = showSeconds ? max > _newMinutes : max >= _newMinutes; } if (!res.canIncrementMinutes) { const /** @type {?} */ _newSeconds = changeTime(value, { seconds: secondsStep }); res.canIncrementSeconds = max >= _newSeconds; } if (value.getHours() < hoursPerDayHalf) { res.canToggleMeridian = changeTime(value, { hour: hoursPerDayHalf }) < max; } } if (min) { const /** @type {?} */ _newHour = changeTime(value, { hour: -hourStep }); res.canDecrementHours = min < _newHour; if (!res.canDecrementHours) { const /** @type {?} */ _newMinutes = changeTime(value, { minute: -minuteStep }); res.canDecrementMinutes = showSeconds ? min < _newMinutes : min <= _newMinutes; } if (!res.canDecrementMinutes) { const /** @type {?} */ _newSeconds = changeTime(value, { seconds: -secondsStep }); res.canDecrementSeconds = min <= _newSeconds; } if (value.getHours() >= hoursPerDayHalf) { res.canToggleMeridian = changeTime(value, { hour: -hoursPerDayHalf }) > min; } } return res; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * Provides default configuration values for timepicker */ class TimepickerConfig { constructor() { /** * hours change step */ this.hourStep = 1; /** * hours change step */ this.minuteStep = 5; /** * seconds changes step */ this.secondsStep = 10; /** * if true works in 12H mode and displays AM/PM. If false works in 24H mode and hides AM/PM */ this.showMeridian = true; /** * meridian labels based on locale */ this.meridians = ['AM', 'PM']; /** * if true hours and minutes fields will be readonly */ this.readonlyInput = false; /** * if true hours and minutes fields will be disabled */ this.disabled = false; /** * if true scroll inside hours and minutes inputs will change time */ this.mousewheel = true; /** * if true the values of hours and minutes can be changed using the up/down arrow keys on the keyboard */ this.arrowkeys = true; /** * if true spinner arrows above and below the inputs will be shown */ this.showSpinners = true; /** * show seconds in timepicker */ this.showSeconds = false; /** * show minutes in timepicker */ this.showMinutes = true; } } TimepickerConfig.decorators = [ { type: Injectable } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ initialState = { value: null, config: new TimepickerConfig(), controls: { canIncrementHours: true, canIncrementMinutes: true, canIncrementSeconds: true, canDecrementHours: true, canDecrementMinutes: true, canDecrementSeconds: true, canToggleMeridian: true } }; /** * @param {?=} state * @param {?=} action * @return {?} */ function timepickerReducer(state = initialState, action) { switch (action.type) { case TimepickerActions.WRITE_VALUE: { return Object.assign({}, state, { value: action.payload }); } case TimepickerActions.CHANGE_HOURS: { if (!canChangeValue(state.config, action.payload) || !canChangeHours(action.payload, state.controls)) { return state; } const /** @type {?} */ _newTime = changeTime(state.value, { hour: action.payload.step }); if ((state.config.max || state.config.min) && !isValidLimit(state.config, _newTime)) { return state; } return Object.assign({}, state, { value: _newTime }); } case TimepickerActions.CHANGE_MINUTES: { if (!canChangeValue(state.config, action.payload) || !canChangeMinutes(action.payload, state.controls)) { return state; } const /** @type {?} */ _newTime = changeTime(state.value, { minute: action.payload.step }); if ((state.config.max || state.config.min) && !isValidLimit(state.config, _newTime)) { return state; } return Object.assign({}, state, { value: _newTime }); } case TimepickerActions.CHANGE_SECONDS: { if (!canChangeValue(state.config, action.payload) || !canChangeSeconds(action.payload, state.controls)) { return state; } const /** @type {?} */ _newTime = changeTime(state.value, { seconds: action.payload.step }); if ((state.config.max || state.config.min) && !isValidLimit(state.config, _newTime)) { return state; } return Object.assign({}, state, { value: _newTime }); } case TimepickerActions.SET_TIME_UNIT: { if (!canChangeValue(state.config)) { return state; } const /** @type {?} */ _newTime = setTime(state.value, action.payload); return Object.assign({}, state, { value: _newTime }); } case TimepickerActions.UPDATE_CONTROLS: { const /** @type {?} */ _newControlsState = timepickerControls(state.value, action.payload); const /** @type {?} */ _newState = { value: state.value, config: action.payload, controls: _newControlsState }; if (state.config.showMeridian !== _newState.config.showMeridian) { if (state.value) { _newState.value = new Date(state.value); } } return Object.assign({}, state, _newState); } default: return state; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class TimepickerStore extends MiniStore { constructor() { const /** @type {?} */ _dispatcher = new BehaviorSubject({ type: '[mini-ngrx] dispatcher init' }); const /** @type {?} */ state = new MiniState(initialState, _dispatcher, timepickerReducer); super(_dispatcher, timepickerReducer, state); } } TimepickerStore.decorators = [ { type: Injectable } ]; /** @nocollapse */ TimepickerStore.ctorParameters = () => []; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ TIMEPICKER_CONTROL_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, /* tslint:disable-next-line: no-use-before-declare */ useExisting: forwardRef(() => TimepickerComponent), multi: true }; class TimepickerComponent { /** * @param {?} _config * @param {?} _cd * @param {?} _store * @param {?} _timepickerActions */ constructor(_config, _cd, _store, _timepickerActions) { this._cd = _cd; this._store = _store; this._timepickerActions = _timepickerActions; /** * emits true if value is a valid date */ this.isValid = new EventEmitter(); // min\max validation for input fields this.invalidHours = false; this.invalidMinutes = false; this.invalidSeconds = false; // control value accessor methods // tslint:disable-next-line:no-any this.onChange = Function.prototype; // tslint:disable-next-line:no-any this.onTouched = Function.prototype; Object.assign(this, _config); this.timepickerSub = _store .select(state => state.value) .subscribe((value) => { // update UI values if date changed this._renderTime(value); this.onChange(value); this._store.dispatch(this._timepickerActions.updateControls(getControlsValue(this))); }); _store .select(state => state.controls) .subscribe((controlsState) => { this.isValid.emit(isInputValid(this.hours, this.minutes, this.seconds, this.isPM())); Object.assign(this, controlsState); _cd.markForCheck(); }); } /** * @deprecated - please use `isEditable` instead * @return {?} */ get isSpinnersVisible() { return this.showSpinners && !this.readonlyInput; } /** * @return {?} */ get isEditable() { return !(this.readonlyInput || this.disabled); } /** * @return {?} */ resetValidation() { this.invalidHours = false; this.invalidMinutes = false; this.invalidSeconds = false; } /** * @return {?} */ isPM() { return this.showMeridian && this.meridian === this.meridians[1]; } /** * @param {?} $event * @return {?} */ prevDef($event) { $event.preventDefault(); } /** * @param {?} $event * @return {?} */ wheelSign($event) { return Math.sign($event.deltaY) * -1; } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { this._store.dispatch(this._timepickerActions.updateControls(getControlsValue(this))); } /** * @param {?} step * @param {?=} source * @return {?} */ changeHours(step, source = '') { this.resetValidation(); this._store.dispatch(this._timepickerActions.changeHours({ step, source })); } /** * @param {?} step * @param {?=} source * @return {?} */ changeMinutes(step, source = '') { this.resetValidation(); this._store.dispatch(this._timepickerActions.changeMinutes({ step, source })); } /** * @param {?} step * @param {?=} source * @return {?} */ changeSeconds(step, source = '') { this.resetValidation(); this._store.dispatch(this._timepickerActions.changeSeconds({ step, source })); } /** * @param {?} hours * @return {?} */ updateHours(hours) { this.resetValidation(); this.hours = hours; const /** @type {?} */ isValid = isHourInputValid(this.hours, this.isPM()) && this.isValidLimit(); if (!isValid) { this.invalidHours = true; this.isValid.emit(false); this.onChange(null); return; } this._updateTime(); } /** * @param {?} minutes * @return {?} */ updateMinutes(minutes) { this.resetValidation(); this.minutes = minutes; const /** @type {?} */ isValid = isMinuteInputValid(this.minutes) && this.isValidLimit(); if (!isValid) { this.invalidMinutes = true; this.isValid.emit(false); this.onChange(null); return; } this._updateTime(); } /** * @param {?} seconds * @return {?} */ updateSeconds(seconds) { this.resetValidation(); this.seconds = seconds; const /** @type {?} */ isValid = isSecondInputValid(this.seconds) && this.isValidLimit(); if (!isValid) { this.invalidSeconds = true; this.isValid.emit(false); this.onChange(null); return; } this._updateTime(); } /** * @return {?} */ isValidLimit() { return isInputLimitValid({ hour: this.hours, minute: this.minutes, seconds: this.seconds, isPM: this.isPM() }, this.max, this.min); } /** * @return {?} */ _updateTime() { const /** @type {?} */ _seconds = this.showSeconds ? this.seconds : void 0; const /** @type {?} */ _minutes = this.showMinutes ? this.minutes : void 0; if (!isInputValid(this.hours, _minutes, _seconds, this.isPM())) { this.isValid.emit(false); this.onChange(null); return; } this._store.dispatch(this._timepickerActions.setTime({ hour: this.hours, minute: this.minutes, seconds: this.seconds, isPM: this.isPM() })); } /** * @return {?} */ toggleMeridian() { if (!this.showMeridian || !this.isEditable) { return; } const /** @type {?} */ _hoursPerDayHalf = 12; this._store.dispatch(this._timepickerActions.changeHours({ step: _hoursPerDayHalf, source: '' })); } /** * Write a new value to the element. * @param {?} obj * @return {?} */ writeValue(obj) { if (isValidDate(obj)) { this._store.dispatch(this._timepickerActions.writeValue(parseTime(obj))); } else if (obj == null) { this._store.dispatch(this._timepickerActions.writeValue(null)); } } /** * Set the function to be called when the control receives a change event. * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChange = fn; } /** * Set the function to be called when the control receives a touch event. * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } /** * This function is called when the control status changes to or from "disabled". * Depending on the value, it will enable or disable the appropriate DOM element. * * @param {?} isDisabled * @return {?} */ setDisabledState(isDisabled) { this.disabled = isDisabled; this._cd.markForCheck(); } /** * @return {?} */ ngOnDestroy() { this.timepickerSub.unsubscribe(); } /** * @param {?} value * @return {?} */ _renderTime(value) { if (!isValidDate(value)) { this.hours = ''; this.minutes = ''; this.seconds = ''; this.meridian = this.meridians[0]; return; } const /** @type {?} */ _value = parseTime(value); const /** @type {?} */ _hoursPerDayHalf = 12; let /** @type {?} */ _hours = _value.getHours(); if (this.showMeridian) { this.meridian = this.meridians[_hours >= _hoursPerDayHalf ? 1 : 0]; _hours = _hours % _hoursPerDayHalf; // should be 12 PM, not 00 PM if (_hours === 0) { _hours = _hoursPerDayHalf; } } this.hours = padNumber(_hours); this.minutes = padNumber(_value.getMinutes()); this.seconds = padNumber(_value.getUTCSeconds()); } } TimepickerComponent.decorators = [ { type: Component, args: [{ selector: 'timepicker', changeDetection: ChangeDetectionStrategy.OnPush, providers: [TIMEPICKER_CONTROL_VALUE_ACCESSOR, TimepickerStore], template: "<table>\n <tbody>\n <tr class=\"text-center\" [hidden]=\"!showSpinners\">\n <!-- increment hours button-->\n <td>\n <a class=\"btn btn-link\" [class.disabled]=\"!canIncrementHours || !isEditable\"\n (click)=\"changeHours(hourStep)\"\n ><span class=\"bs-chevron bs-chevron-up\"></span></a>\n </td>\n <!-- divider -->\n <td *ngIf=\"showMinutes\">&nbsp;&nbsp;&nbsp;</td>\n <!-- increment minutes button -->\n <td *ngIf=\"showMinutes\">\n <a class=\"btn btn-link\" [class.disabled]=\"!canIncrementMinutes || !isEditable\"\n (click)=\"changeMinutes(minuteStep)\"\n ><span class=\"bs-chevron bs-chevron-up\"></span></a>\n </td>\n <!-- divider -->\n <td *ngIf=\"showSeconds\">&nbsp;</td>\n <!-- increment seconds button -->\n <td *ngIf=\"showSeconds\">\n <a class=\"btn btn-link\" [class.disabled]=\"!canIncrementSeconds || !isEditable\"\n (click)=\"changeSeconds(secondsStep)\">\n <span class=\"bs-chevron bs-chevron-up\"></span>\n </a>\n </td>\n <!-- space between -->\n <td *ngIf=\"showMeridian\">&nbsp;&nbsp;&nbsp;</td>\n <!-- meridian placeholder-->\n <td *ngIf=\"showMeridian\"></td>\n </tr>\n <tr>\n <!-- hours -->\n <td class=\"form-group\" [class.has-error]=\"invalidHours\">\n <input type=\"text\" [class.is-invalid]=\"invalidHours\"\n class=\"form-control text-center bs-timepicker-field\"\n placeholder=\"HH\"\n maxlength=\"2\"\n [readonly]=\"readonlyInput\"\n [disabled]=\"disabled\"\n [value]=\"hours\"\n (wheel)=\"prevDef($event);changeHours(hourStep * wheelSign($event), 'wheel')\"\n (keydown.ArrowUp)=\"changeHours(hourStep, 'key')\"\n (keydown.ArrowDown)=\"changeHours(-hourStep, 'key')\"\n (change)=\"updateHours($event.target.value)\"></td>\n <!-- divider -->\n <td *ngIf=\"showMinutes\">&nbsp;:&nbsp;</td>\n <!-- minutes -->\n <td class=\"form-group\" *ngIf=\"showMinutes\" [class.has-error]=\"invalidMinutes\">\n <input type=\"text\" [class.is-invalid]=\"invalidMinutes\"\n class=\"form-control text-center bs-timepicker-field\"\n placeholder=\"MM\"\n maxlength=\"2\"\n [readonly]=\"readonlyInput\"\n [disabled]=\"disabled\"\n [value]=\"minutes\"\n (wheel)=\"prevDef($event);changeMinutes(minuteStep * wheelSign($event), 'wheel')\"\n (keydown.ArrowUp)=\"changeMinutes(minuteStep, 'key')\"\n (keydown.ArrowDown)=\"changeMinutes(-minuteStep, 'key')\"\n (change)=\"updateMinutes($event.target.value)\">\n </td>\n <!-- divider -->\n <td *ngIf=\"showSeconds\">&nbsp;:&nbsp;</td>\n <!-- seconds -->\n <td class=\"form-group\" *ngIf=\"showSeconds\" [class.has-error]=\"invalidSeconds\">\n <input type=\"text\" [class.is-invalid]=\"invalidSeconds\"\n class=\"form-control text-center bs-timepicker-field\"\n placeholder=\"SS\"\n maxlength=\"2\"\n [readonly]=\"readonlyInput\"\n [disabled]=\"disabled\"\n [value]=\"seconds\"\n (wheel)=\"prevDef($event);changeSeconds(secondsStep * wheelSign($event), 'wheel')\"\n (keydown.ArrowUp)=\"changeSeconds(secondsStep, 'key')\"\n (keydown.ArrowDown)=\"changeSeconds(-secondsStep, 'key')\"\n (change)=\"updateSeconds($event.target.value)\">\n </td>\n <!-- space between -->\n <td *ngIf=\"showMeridian\">&nbsp;&nbsp;&nbsp;</td>\n <!-- meridian -->\n <td *ngIf=\"showMeridian\">\n <button type=\"button\" class=\"btn btn-default text-center\"\n [disabled]=\"!isEditable || !canToggleMeridian\"\n [class.disabled]=\"!isEditable || !canToggleMeridian\"\n (click)=\"toggleMeridian()\"\n >{{ meridian }}\n </button>\n </td>\n </tr>\n <tr class=\"text-center\" [hidden]=\"!showSpinners\">\n <!-- decrement hours button-->\n <td>\n <a class=\"btn btn-link\" [class.disabled]=\"!canDecrementHours || !isEditable\"\n (click)=\"changeHours(-hourStep)\">\n <span class=\"bs-chevron bs-chevron-down\"></span>\n </a>\n </td>\n <!-- divider -->\n <td *ngIf=\"showMinutes\">&nbsp;&nbsp;&nbsp;</td>\n <!-- decrement minutes button-->\n <td *ngIf=\"showMinutes\">\n <a class=\"btn btn-link\" [class.disabled]=\"!canDecrementMinutes || !isEditable\"\n (click)=\"changeMinutes(-minuteStep)\">\n <span class=\"bs-chevron bs-chevron-down\"></span>\n </a>\n </td>\n <!-- divider -->\n <td *ngIf=\"showSeconds\">&nbsp;</td>\n <!-- decrement seconds button-->\n <td *ngIf=\"showSeconds\">\n <a class=\"btn btn-link\" [class.disabled]=\"!canDecrementSeconds || !isEditable\"\n (click)=\"changeSeconds(-secondsStep)\">\n <span class=\"bs-chevron bs-chevron-down\"></span>\n </a>\n </td>\n <!-- space between -->\n <td *ngIf=\"showMeridian\">&nbsp;&nbsp;&nbsp;</td>\n <!-- meridian placeholder-->\n <td *ngIf=\"showMeridian\"></td>\n </tr>\n </tbody>\n</table>\n", encapsulation: ViewEncapsulation.None, styles: [` .bs-chevron { border-style: solid; display: block; width: 9px; height: 9px; position: relative; border-width: 3px 0px 0 3px; } .bs-chevron-up { -webkit-transform: rotate(45deg); transform: rotate(45deg); top: 2px; } .bs-chevron-down { -webkit-transform: rotate(-135deg); transform: rotate(-135deg); top: -2px; } .bs-timepicker-field { width: 50px; } `] }] } ]; /** @nocollapse */ TimepickerComponent.ctorParameters = () => [ { type: TimepickerConfig, }, { type: ChangeDetectorRef, }, { type: TimepickerStore, }, { type: TimepickerActions, }, ]; TimepickerComponent.propDecorators = { "hourStep": [{ type: Input },], "minuteStep": [{ type: Input },], "secondsStep": [{ type: Input },], "readonlyInput": [{ type: Input },], "disabled": [{ type: Input },], "mousewheel": [{ type: Input },], "arrowkeys": [{ type: Input },], "showSpinners": [{ type: Input },], "showMeridian": [{ type: Input },], "showMinutes": [{ type: Input },], "showSeconds": [{ type: Input },], "meridians": [{ type: Input },], "min": [{ type: Input },], "max": [{ type: Input },], "isValid": [{ type: Output },], }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class TimepickerModule { /** * @return {?} */ static forRoot() { return { ngModule: TimepickerModule, providers: [TimepickerConfig, TimepickerActions, TimepickerStore] }; } } TimepickerModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule], declarations: [TimepickerComponent], exports: [TimepickerComponent] },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ export { TimepickerComponent, TimepickerActions, TimepickerStore, TimepickerConfig, TimepickerModule, TIMEPICKER_CONTROL_VALUE_ACCESSOR as ɵa }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWJvb3RzdHJhcC10aW1lcGlja2VyLmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9uZ3gtYm9vdHN0cmFwL3RpbWVwaWNrZXIvcmVkdWNlci90aW1lcGlja2VyLmFjdGlvbnMudHMiLCJuZzovL25neC1ib290c3RyYXAvdGltZXBpY2tlci90aW1lcGlja2VyLnV0aWxzLnRzIiwibmc6Ly9uZ3gtYm9vdHN0cmFwL3RpbWVwaWNrZXIvdGltZXBpY2tlci1jb250cm9scy51dGlsLnRzIiwibmc6Ly9uZ3gtYm9vdHN0cmFwL3RpbWVwaWNrZXIvdGltZXBpY2tlci5jb25maWcudHMiLCJuZzovL25neC1ib290c3RyYXAvdGltZXBpY2tlci9yZWR1Y2VyL3RpbWVwaWNrZXIucmVkdWNlci50cyIsIm5nOi8vbmd4LWJvb3RzdHJhcC90aW1lcGlja2VyL3JlZHVjZXIvdGltZXBpY2tlci5zdG9yZS50cyIsIm5nOi8vbmd4LWJvb3RzdHJhcC90aW1lcGlja2VyL3RpbWVwaWNrZXIuY29tcG9uZW50LnRzIiwibmc6Ly9uZ3gtYm9vdHN0cmFwL3RpbWVwaWNrZXIvdGltZXBpY2tlci5tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aW9uIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9taW5pLW5ncngnO1xuaW1wb3J0IHtcbiAgVGltZUNoYW5nZUV2ZW50LFxuICBUaW1lcGlja2VyQ29tcG9uZW50U3RhdGUsXG4gIFRpbWVcbn0gZnJvbSAnLi4vdGltZXBpY2tlci5tb2RlbHMnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgVGltZXBpY2tlckFjdGlvbnMge1xuICBzdGF0aWMgcmVhZG9ubHkgV1JJVEVfVkFMVUUgPSAnW3RpbWVwaWNrZXJdIHdyaXRlIHZhbHVlIGZyb20gbmcgbW9kZWwnO1xuICBzdGF0aWMgcmVhZG9ubHkgQ0hBTkdFX0hPVVJTID0gJ1t0aW1lcGlja2VyXSBjaGFuZ2UgaG91cnMnO1xuICBzdGF0aWMgcmVhZG9ubHkgQ0hBTkdFX01JTlVURVMgPSAnW3RpbWVwaWNrZXJdIGNoYW5nZSBtaW51dGVzJztcbiAgc3RhdGljIHJlYWRvbmx5IENIQU5HRV9TRUNPTkRTID0gJ1t0aW1lcGlja2VyXSBjaGFuZ2Ugc2Vjb25kcyc7XG4gIHN0YXRpYyByZWFkb25seSBTRVRfVElNRV9VTklUID0gJ1t0aW1lcGlja2VyXSBzZXQgdGltZSB1bml0JztcbiAgc3RhdGljIHJlYWRvbmx5IFVQREFURV9DT05UUk9MUyA9ICdbdGltZXBpY2tlcl0gdXBkYXRlIGNvbnRyb2xzJztcblxuICB3cml0ZVZhbHVlKHZhbHVlOiBEYXRlIHwgc3RyaW5nKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IFRpbWVwaWNrZXJBY3Rpb25zLldSSVRFX1ZBTFVFLFxuICAgICAgcGF5bG9hZDogdmFsdWVcbiAgICB9O1xuICB9XG5cbiAgY2hhbmdlSG91cnMoZXZlbnQ6IFRpbWVDaGFuZ2VFdmVudCkge1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBUaW1lcGlja2VyQWN0aW9ucy5DSEFOR0VfSE9VUlMsXG4gICAgICBwYXlsb2FkOiBldmVudFxuICAgIH07XG4gIH1cblxuICBjaGFuZ2VNaW51dGVzKGV2ZW50OiBUaW1lQ2hhbmdlRXZlbnQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogVGltZXBpY2tlckFjdGlvbnMuQ0hBTkdFX01JTlVURVMsXG4gICAgICBwYXlsb2FkOiBldmVudFxuICAgIH07XG4gIH1cblxuICBjaGFuZ2VTZWNvbmRzKGV2ZW50OiBUaW1lQ2hhbmdlRXZlbnQpOiBBY3Rpb24ge1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBUaW1lcGlja2VyQWN0aW9ucy5DSEFOR0VfU0VDT05EUyxcbiAgICAgIHBheWxvYWQ6IGV2ZW50XG4gICAgfTtcbiAgfVxuXG4gIHNldFRpbWUodmFsdWU6IFRpbWUpOiBBY3Rpb24ge1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBUaW1lcGlja2VyQWN0aW9ucy5TRVRfVElNRV9VTklULFxuICAgICAgcGF5bG9hZDogdmFsdWVcbiAgICB9O1xuICB9XG5cbiAgdXBkYXRlQ29udHJvbHModmFsdWU6IFRpbWVwaWNrZXJDb21wb25lbnRTdGF0ZSk6IEFjdGlvbiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IFRpbWVwaWNrZXJBY3Rpb25zLlVQREFURV9DT05UUk9MUyxcbiAgICAgIHBheWxvYWQ6IHZhbHVlXG4gICAgfTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgVGltZSwgVGltZXBpY2tlckNvbXBvbmVudFN0YXRlIH0gZnJvbSAnLi90aW1lcGlja2VyLm1vZGVscyc7XG5cbmNvbnN0IGRleCA9IDEwO1xuY29uc3QgaG91cnNQZXJEYXkgPSAyNDtcbmNvbnN0IGhvdXJzUGVyRGF5SGFsZiA9IDEyO1xuY29uc3QgbWludXRlc1BlckhvdXIgPSA2MDtcbmNvbnN0IHNlY29uZHNQZXJNaW51dGUgPSA2MDtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWREYXRlKHZhbHVlPzogc3RyaW5nIHwgRGF0ZSk6IGJvb2xlYW4ge1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSAmJiBpc05hTih2YWx1ZS5nZXRIb3VycygpKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGlzVmFsaWREYXRlKG5ldyBEYXRlKHZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRMaW1pdChjb250cm9sczogVGltZXBpY2tlckNvbXBvbmVudFN0YXRlLCBuZXdEYXRlOiBEYXRlKTogYm9vbGVhbiB7XG4gIGlmIChjb250cm9scy5taW4gJiYgbmV3RGF0ZSA8IGNvbnRyb2xzLm1pbikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChjb250cm9scy5tYXggJiYgbmV3RGF0ZSA+IGNvbnRyb2xzLm1heCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9OdW1iZXIodmFsdWU6IHN0cmluZyB8IG51bWJlcik6IG51bWJlciB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlSW50KHZhbHVlLCBkZXgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNOdW1iZXIodmFsdWU6IHN0cmluZyB8IG51bWJlcik6IHZhbHVlIGlzIG51bWJlciB7XG4gIHJldHVybiAhaXNOYU4odG9OdW1iZXIodmFsdWUpKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlSG91cnMoXG4gIHZhbHVlOiBzdHJpbmcgfCBudW1iZXIsXG4gIGlzUE0gPSBmYWxzZVxuKTogbnVtYmVyIHtcbiAgY29uc3QgaG91ciA9IHRvTnVtYmVyKHZhbHVlKTtcbiAgaWYgKFxuICAgIGlzTmFOKGhvdXIpIHx8XG4gICAgaG91ciA8IDAgfHxcbiAgICBob3VyID4gKGlzUE0gPyBob3Vyc1BlckRheUhhbGYgOiBob3Vyc1BlckRheSlcbiAgKSB7XG4gICAgcmV0dXJuIE5hTjtcbiAgfVxuXG4gIHJldHVybiBob3VyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VNaW51dGVzKHZhbHVlOiBzdHJpbmcgfCBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBtaW51dGUgPSB0b051bWJlcih2YWx1ZSk7XG4gIGlmIChpc05hTihtaW51dGUpIHx8IG1pbnV0ZSA8IDAgfHwgbWludXRlID4gbWludXRlc1BlckhvdXIpIHtcbiAgICByZXR1cm4gTmFOO1xuICB9XG5cbiAgcmV0dXJuIG1pbnV0ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlU2Vjb25kcyh2YWx1ZTogc3RyaW5nIHwgbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3Qgc2Vjb25kcyA9IHRvTnVtYmVyKHZhbHVlKTtcbiAgaWYgKGlzTmFOKHNlY29uZHMpIHx8IHNlY29uZHMgPCAwIHx8IHNlY29uZHMgPiBzZWNvbmRzUGVyTWludXRlKSB7XG4gICAgcmV0dXJuIE5hTjtcbiAgfVxuXG4gIHJldHVybiBzZWNvbmRzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VUaW1lKHZhbHVlOiBzdHJpbmcgfCBEYXRlKTogRGF0ZSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKHZhbHVlKTtcbiAgfVxuXG4gIHJldHVybiB2YWx1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNoYW5nZVRpbWUodmFsdWU6IERhdGUsIGRpZmY6IFRpbWUpOiBEYXRlIHtcbiAgaWYgKCF2YWx1ZSkge1xuICAgIHJldHVybiBjaGFuZ2VUaW1lKGNyZWF0ZURhdGUobmV3IERhdGUoKSwgMCwgMCwgMCksIGRpZmYpO1xuICB9XG5cbiAgbGV0IGhvdXIgPSB2YWx1ZS5nZXRIb3VycygpO1xuICBsZXQgbWludXRlcyA9IHZhbHVlLmdldE1pbnV0ZXMoKTtcbiAgbGV0IHNlY29uZHMgPSB2YWx1ZS5nZXRTZWNvbmRzKCk7XG5cbiAgaWYgKGRpZmYuaG91cikge1xuICAgIGhvdXIgPSAoaG91ciArIHRvTnVtYmVyKGRpZmYuaG91cikpICUgaG91cnNQZXJEYXk7XG4gICAgaWYgKGhvdXIgPCAwKSB7XG4gICAgICBob3VyICs9IGhvdXJzUGVyRGF5O1xuICAgIH1cbiAgfVxuXG4gIGlmIChkaWZmLm1pbnV0ZSkge1xuICAgIG1pbnV0ZXMgPSBtaW51dGVzICsgdG9OdW1iZXIoZGlmZi5taW51dGUpO1xuICB9XG5cbiAgaWYgKGRpZmYuc2Vjb25kcykge1xuICAgIHNlY29uZHMgPSBzZWNvbmRzICsgdG9OdW1iZXIoZGlmZi5zZWNvbmRzKTtcbiAgfVxuXG4gIHJldHVybiBjcmVhdGVEYXRlKHZhbHVlLCBob3VyLCBtaW51dGVzLCBzZWNvbmRzKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldFRpbWUodmFsdWU6IERhdGUsIG9wdHM6IFRpbWUpOiBEYXRlIHtcbiAgbGV0IGhvdXIgPSBwYXJzZUhvdXJzKG9wdHMuaG91cik7XG4gIGNvbnN0IG1pbnV0ZSA9IHBhcnNlTWludXRlcyhvcHRzLm1pbnV0ZSk7XG4gIGNvbnN0IHNlY29uZHMgPSBwYXJzZVNlY29uZHMob3B0cy5zZWNvbmRzKSB8fCAwO1xuXG4gIGlmIChvcHRzLmlzUE0pIHtcbiAgICBob3VyICs9IGhvdXJzUGVyRGF5SGFsZjtcbiAgfVxuXG4gIGlmICghdmFsdWUpIHtcbiAgICBpZiAoIWlzTmFOKGhvdXIpICYmICFpc05hTihtaW51dGUpKSB7XG4gICAgICByZXR1cm4gY3JlYXRlRGF0ZShuZXcgRGF0ZSgpLCBob3VyLCBtaW51dGUsIHNlY29uZHMpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIGlmIChpc05hTihob3VyKSB8fCBpc05hTihtaW51dGUpKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcmV0dXJuIGNyZWF0ZURhdGUodmFsdWUsIGhvdXIsIG1pbnV0ZSwgc2Vjb25kcyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVEYXRlKFxuICB2YWx1ZTogRGF0ZSxcbiAgaG91cnM6IG51bWJlcixcbiAgbWludXRlczogbnVtYmVyLFxuICBzZWNvbmRzOiBudW1iZXJcbik6IERhdGUge1xuICByZXR1cm4gbmV3IERhdGUoXG4gICAgdmFsdWUuZ2V0RnVsbFllYXIoKSxcbiAgICB2YWx1ZS5nZXRNb250aCgpLFxuICAgIHZhbHVlLmdldERhdGUoKSxcbiAgICBob3VycyxcbiAgICBtaW51dGVzLFxuICAgIHNlY29uZHMsXG4gICAgdmFsdWUuZ2V0TWlsbGlzZWNvbmRzKClcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhZE51bWJlcih2YWx1ZTogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgX3ZhbHVlID0gdmFsdWUudG9TdHJpbmcoKTtcbiAgaWYgKF92YWx1ZS5sZW5ndGggPiAxKSB7XG4gICAgcmV0dXJuIF92YWx1ZTtcbiAgfVxuXG4gIHJldHVybiBgMCR7X3ZhbHVlfWA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0hvdXJJbnB1dFZhbGlkKGhvdXJzOiBzdHJpbmcsIGlzUE06IGJvb2xlYW4pOiBib29sZWFuIHtcbiAgcmV0dXJuICFpc05hTihwYXJzZUhvdXJzKGhvdXJzLCBpc1BNKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc01pbnV0ZUlucHV0VmFsaWQobWludXRlczogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiAhaXNOYU4ocGFyc2VNaW51dGVzKG1pbnV0ZXMpKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzU2Vjb25kSW5wdXRWYWxpZChzZWNvbmRzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuICFpc05hTihwYXJzZVNlY29uZHMoc2Vjb25kcykpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNJbnB1dExpbWl0VmFsaWQoZGlmZjogVGltZSwgbWF4OiBEYXRlLCBtaW46IERhdGUpOiBib29sZWFuIHtcbiAgY29uc3QgbmV3RGF0ZSA9IGNoYW5nZVRpbWUobmV3IERhdGUoKSwgZGlmZik7XG5cbiAgaWYgKG1heCAmJiBuZXdEYXRlID4gbWF4KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKG1pbiAmJiBuZXdEYXRlIDwgbWluKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0lucHV0VmFsaWQoXG4gIGhvdXJzOiBzdHJpbmcsXG4gIG1pbnV0ZXMgPSAnMCcsXG4gIHNlY29uZHMgPSAnMCcsXG4gIGlzUE06IGJvb2xlYW5cbik6IGJvb2xlYW4ge1xuICByZXR1cm4gaXNIb3VySW5wdXRWYWxpZChob3VycywgaXNQTSlcbiAgICAmJiBpc01pbnV0ZUlucHV0VmFsaWQobWludXRlcylcbiAgICAmJiBpc1NlY29uZElucHV0VmFsaWQoc2Vjb25kcyk7XG59XG4iLCJpbXBvcnQgeyBjaGFuZ2VUaW1lIH0gZnJvbSAnLi90aW1lcGlja2VyLnV0aWxzJztcbmltcG9ydCB7XG4gIFRpbWVDaGFuZ2VFdmVudCxcbiAgVGltZXBpY2tlckNvbXBvbmVudFN0YXRlLFxuICBUaW1lcGlja2VyQ29udHJvbHNcbn0gZnJvbSAnLi90aW1lcGlja2VyLm1vZGVscyc7XG5cbmV4cG9ydCBmdW5jdGlvbiBjYW5DaGFuZ2VWYWx1ZShcbiAgc3RhdGU6IFRpbWVwaWNrZXJDb21wb25lbnRTdGF0ZSxcbiAgZXZlbnQ/OiBUaW1lQ2hhbmdlRXZlbnRcbik6IGJvb2xlYW4ge1xuICBpZiAoc3RhdGUucmVhZG9ubHlJbnB1dCB8fCBzdGF0ZS5kaXNhYmxlZCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChldmVudCkge1xuICAgIGlmIChldmVudC5zb3VyY2UgPT09ICd3aGVlbCcgJiYgIXN0YXRlLm1vdXNld2hlZWwpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoZXZlbnQuc291cmNlID09PSAna2V5JyAmJiAhc3RhdGUuYXJyb3drZXlzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjYW5DaGFuZ2VIb3VycyhcbiAgZXZlbnQ6IFRpbWVDaGFuZ2VFdmVudCxcbiAgY29udHJvbHM6IFRpbWVwaWNrZXJDb250cm9sc1xuKTogYm9vbGVhbiB7XG4gIGlmICghZXZlbnQuc3RlcCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChldmVudC5zdGVwID4gMCAmJiAhY29udHJvbHMuY2FuSW5jcmVtZW50SG91cnMpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoZXZlbnQuc3RlcCA8IDAgJiYgIWNvbnRyb2xzLmNhbkRlY3JlbWVudEhvdXJzKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjYW5DaGFuZ2VNaW51dGVzKFxuICBldmVudDogVGltZUNoYW5nZUV2ZW50LFxuICBjb250cm9sczogVGltZXBpY2tlckNvbnRyb2xzXG4pOiBib29sZWFuIHtcbiAgaWYgKCFldmVudC5zdGVwKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmIChldmVudC5zdGVwID4gMCAmJiAhY29udHJvbHMuY2FuSW5jcmVtZW50TWludXRlcykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoZXZlbnQuc3RlcCA8IDAgJiYgIWNvbnRyb2xzLmNhbkRlY3JlbWVudE1pbnV0ZXMpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbkNoYW5nZVNlY29uZHMoXG4gIGV2ZW50OiBUaW1lQ2hhbmdlRXZlbnQsXG4gIGNvbnRyb2xzOiBUaW1lcGlja2VyQ29udHJvbHNcbik6IGJvb2xlYW4ge1xuICBpZiAoIWV2ZW50LnN0ZXApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGV2ZW50LnN0ZXAgPiAwICYmICFjb250cm9scy5jYW5JbmNyZW1lbnRTZWNvbmRzKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmIChldmVudC5zdGVwIDwgMCAmJiAhY29udHJvbHMuY2FuRGVjcmVtZW50U2Vjb25kcykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q29udHJvbHNWYWx1ZShcbiAgc3RhdGU6IFRpbWVwaWNrZXJDb21wb25lbnRTdGF0ZVxuKTogVGltZXBpY2tlckNvbXBvbmVudFN0YXRlIHtcbiAgY29uc3Qge1xuICAgIGhvdXJTdGVwLFxuICAgIG1pbnV0ZVN0ZXAsXG4gICAgc2Vjb25kc1N0ZXAsXG4gICAgcmVhZG9ubHlJbnB1dCxcbiAgICBkaXNhYmxlZCxcbiAgICBtb3VzZXdoZWVsLFxuICAgIGFycm93a2V5cyxcbiAgICBzaG93U3Bpbm5lcnMsXG4gICAgc2hvd01lcmlkaWFuLFxuICAgIHNob3dTZWNvbmRzLFxuICAgIG1lcmlkaWFucyxcbiAgICBtaW4sXG4gICAgbWF4XG4gIH0gPSBzdGF0ZTtcblxuICByZXR1cm4ge1xuICAgIGhvdXJTdGVwLFxuICAgIG1pbnV0ZVN0ZXAsXG4gICAgc2Vjb25kc1N0ZXAsXG4gICAgcmVhZG9ubHlJbnB1dCxcbiAgICBkaXNhYmxlZCxcbiAgICBtb3VzZXdoZWVsLFxuICAgIGFycm93a2V5cyxcbiAgICBzaG93U3Bpbm5lcnMsXG4gICAgc2hvd01lcmlkaWFuLFxuICAgIHNob3dTZWNvbmRzLFxuICAgIG1lcmlkaWFucyxcbiAgICBtaW4sXG4gICAgbWF4XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0aW1lcGlja2VyQ29udHJvbHMoXG4gIHZhbHVlOiBEYXRlLFxuICBzdGF0ZTogVGltZXBpY2tlckNvbXBvbmVudFN0YXRlXG4pOiBUaW1lcGlja2VyQ29udHJvbHMge1xuICBjb25zdCBob3Vyc1BlckRheUhhbGYgPSAxMjtcbiAgY29uc3QgeyBtaW4sIG1heCwgaG91clN0ZXAsIG1pbnV0ZVN0ZXAsIHNlY29uZHNTdGVwLCBzaG93U2Vjb25kcyB9ID0gc3RhdGU7XG4gIGNvbnN0IHJlczogVGltZXBpY2tlckNvbnRyb2xzID0ge1xuICAgIGNhbkluY3JlbWVudEhvdXJzOiB0cnVlLFxuICAgIGNhbkluY3JlbWVudE1pbnV0ZXM6IHRydWUsXG4gICAgY2FuSW5jcmVtZW50U2Vjb25kczogdHJ1ZSxcblxuICAgIGNhbkRlY3JlbWVudEhvdXJzOiB0cnVlLFxuICAgIGNhbkRlY3JlbWVudE1pbnV0ZXM6IHRydWUsXG4gICAgY2FuRGVjcmVtZW50U2Vjb25kczogdHJ1ZSxcblxuICAgIGNhblRvZ2dsZU1lcmlkaWFuOiB0cnVlXG4gIH07XG5cbiAgaWYgKCF2YWx1ZSkge1xuICAgIHJldHVybiByZXM7XG4gIH1cblxuICAvLyBjb21wYXJlIGRhdGVzXG4gIGlmIChtYXgpIHtcbiAgICBjb25zdCBfbmV3SG91ciA9IGNoYW5nZVRpbWUodmFsdWUsIHsgaG91cjogaG91clN0ZXAgfSk7XG4gICAgcmVzLmNhbkluY3JlbWVudEhvdXJzID0gbWF4ID4gX25ld0hvdXI7XG5cbiAgICBpZiAoIXJlcy5jYW5JbmNyZW1lbnRIb3Vycykge1xuICAgICAgY29uc3QgX25ld01pbnV0ZXMgPSBjaGFuZ2VUaW1lKHZhbHVlLCB7IG1pbnV0ZTogbWludXRlU3RlcCB9KTtcbiAgICAgIHJlcy5jYW5JbmNyZW1lbnRNaW51dGVzID0gc2hvd1NlY29uZHNcbiAgICAgICAgPyBtYXggPiBfbmV3TWludXRlc1xuICAgICAgICA6IG1heCA+PSBfbmV3TWludXRlcztcbiAgICB9XG5cbiAgICBpZiAoIXJlcy5jYW5JbmNyZW1lbnRNaW51dGVzKSB7XG4gICAgICBjb25zdCBfbmV3U2Vjb25kcyA9IGNoYW5nZVRpbWUodmFsdWUsIHsgc2Vjb25kczogc2Vjb25kc1N0ZXAgfSk7XG4gICAgICByZXMuY2FuSW5jcmVtZW50U2Vjb25kcyA9IG1heCA+PSBfbmV3U2Vjb25kcztcbiAgICB9XG5cbiAgICBpZiAodmFsdWUuZ2V0SG91cnMoKSA8IGhvdXJzUGVyRGF5SGFsZikge1xuICAgICAgcmVzLmNhblRvZ2dsZU1lcmlkaWFuID0gY2hhbmdlVGltZSh2YWx1ZSwgeyBob3VyOiBob3Vyc1BlckRheUhhbGYgfSkgPCBtYXg7XG4gICAgfVxuICB9XG5cbiAgaWYgKG1pbikge1xuICAgIGNvbnN0IF9uZXdIb3VyID0gY2hhbmdlVGltZSh2YWx1ZSwgeyBob3VyOiAtaG91clN0ZXAgfSk7XG4gICAgcmVzLmNhbkRlY3JlbWVudEhvdXJzID0gbWluIDwgX25ld0hvdXI7XG5cbiAgICBpZiAoIXJlcy5jYW5EZWNyZW1lbnRIb3Vycykge1xuICAgICAgY29uc3QgX25ld01pbnV0ZXMgPSBjaGFuZ2VUaW1lKHZhbHVlLCB7IG1pbnV0ZTogLW1pbnV0ZVN0ZXAgfSk7XG4gICAgICByZXMuY2FuRGVjcmVtZW50TWludXRlcyA9IHNob3dTZWNvbmRzXG4gICAgICAgID8gbWluIDwgX25ld01pbnV0ZXNcbiAgICAgICAgOiBtaW4gPD0gX25ld01pbnV0ZXM7XG4gICAgfVxuXG4gICAgaWYgKCFyZXMuY2FuRGVjcmVtZW50TWludXRlcykge1xuICAgICAgY29uc3QgX25ld1NlY29uZHMgPSBjaGFuZ2VUaW1lKHZhbHVlLCB7IHNlY29uZHM6IC1zZWNvbmRzU3RlcCB9KTtcbiAgICAgIHJlcy5jYW5EZWNyZW1lbnRTZWNvbmRzID0gbWluIDw9IF9uZXdTZWNvbmRzO1xuICAgIH1cblxuICAgIGlmICh2YWx1ZS5nZXRIb3VycygpID49IGhvdXJzUGVyRGF5SGFsZikge1xuICAgICAgcmVzLmNhblRvZ2dsZU1lcmlkaWFuID0gY2hhbmdlVGltZSh2YWx1ZSwgeyBob3VyOiAtaG91cnNQZXJEYXlIYWxmIH0pID4gbWluO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXM7XG59XG4iLCJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbi8qKiBQcm92aWRlcyBkZWZhdWx0IGNvbmZpZ3VyYXRpb24gdmFsdWVzIGZvciB0aW1lcGlja2VyICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgVGltZXBpY2tlckNvbmZpZyB7XG4gIC8qKiBob3VycyBjaGFuZ2Ugc3RlcCAqL1xuICBob3VyU3RlcCA9IDE7XG4gIC8qKiBob3VycyBjaGFuZ2Ugc3RlcCAqL1xuICBtaW51dGVTdGVwID0gNTtcbiAgLyoqIHNlY29uZHMgY2hhbmdlcyBzdGVwICovXG4gIHNlY29uZHNTdGVwID0gMTA7XG4gIC8qKiBpZiB0cnVlIHdvcmtzIGluIDEySCBtb2RlIGFuZCBkaXNwbGF5cyBBTS9QTS4gSWYgZmFsc2Ugd29ya3MgaW4gMjRIIG1vZGUgYW5kIGhpZGVzIEFNL1BNICovXG4gIHNob3dNZXJpZGlhbiA9IHRydWU7XG4gIC8qKiBtZXJpZGlhbiBsYWJlbHMgYmFzZWQgb24gbG9jYWxlICovXG4gIG1lcmlkaWFucyA9IFsnQU0nLCAnUE0nXTtcbiAgLyoqIGlmIHRydWUgaG91cnMgYW5kIG1pbnV0ZXMgZmllbGRzIHdpbGwgYmUgcmVhZG9ubHkgKi9cbiAgcmVhZG9ubHlJbnB1dCA9IGZhbHNlO1xuICAvKiogaWYgdHJ1ZSBob3VycyBhbmQgbWludXRlcyBmaWVsZHMgd2lsbCBiZSBkaXNhYmxlZCAqL1xuICBkaXNhYmxlZCA9IGZhbHNlO1xuICAvKiogaWYgdHJ1ZSBzY3JvbGwgaW5zaWRlIGhvdXJzIGFuZCBtaW51dGVzIGlucHV0cyB3aWxsIGNoYW5nZSB0aW1lICovXG4gIG1vdXNld2hlZWwgPSB0cnVlO1xuICAvKiogaWYgdHJ1ZSB0aGUgdmFsdWVzIG9mIGhvdXJzIGFuZCBtaW51dGVzIGNhbiBiZSBjaGFuZ2VkIHVzaW5nIHRoZSB1cC9kb3duIGFycm93IGtleXMgb24gdGhlIGtleWJvYXJkICovXG4gIGFycm93a2V5cyA9IHRydWU7XG4gIC8qKiBpZiB0cnVlIHNwaW5uZXIgYXJyb3dzIGFib3ZlIGFuZCBiZWxvdyB0aGUgaW5wdXRzIHdpbGwgYmUgc2hvd24gKi9cbiAgc2hvd1NwaW5uZXJzID0gdHJ1ZTtcbiAgLyoqIHNob3cgc2Vjb25kcyBpbiB0aW1lcGlja2VyICovXG4gIHNob3dTZWNvbmRzID0gZmFsc2U7XG4gIC8qKiBzaG93IG1pbnV0ZXMgaW4gdGltZXBpY2tlciAqL1xuICBzaG93TWludXRlcyA9IHRydWU7XG4gIC8qKiBtaW5pbXVtIHRpbWUgdXNlciBjYW4gc2VsZWN0ICovXG4gIG1pbjogRGF0ZTtcbiAgLyoqIG1heGltdW0gdGltZSB1c2VyIGNhbiBzZWxlY3QgKi9cbiAgbWF4OiBEYXRlO1xufVxuIiwiaW1wb3J0IHsgQWN0aW9uIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9taW5pLW5ncngnO1xuaW1wb3J0IHtcbiAgY2FuQ2hhbmdlSG91cnMsXG4gIGNhbkNoYW5nZU1pbnV0ZXMsXG4gIGNhbkNoYW5nZVNlY29uZHMsXG4gIGNhbkNoYW5nZVZhbHVlLFxuICB0aW1lcGlja2VyQ29udHJvbHNcbn0gZnJvbSAnLi4vdGltZXBpY2tlci1jb250cm9scy51dGlsJztcbmltcG9ydCB7IFRpbWVwaWNrZXJDb25maWcgfSBmcm9tICcuLi90aW1lcGlja2VyLmNvbmZpZyc7XG5pbXBvcnQge1xuICBUaW1lcGlja2VyQ29tcG9uZW50U3RhdGUsXG4gIFRpbWVwaWNrZXJDb250cm9sc1xufSBmcm9tICcuLi90aW1lcGlja2VyLm1vZGVscyc7XG5pbXBvcnQgeyBjaGFuZ2VUaW1lLCBzZXRUaW1lLCBpc1ZhbGlkTGltaXQgfSBmcm9tICcuLi90aW1lcGlja2VyLnV0aWxzJztcbmltcG9ydCB7IFRpbWVwaWNrZXJBY3Rpb25zIH0gZnJvbSAnLi90aW1lcGlja2VyLmFjdGlvbnMnO1xuXG5leHBvcnQgY2xhc3MgVGltZXBpY2tlclN0YXRlIHtcbiAgdmFsdWU6IERhdGU7XG4gIGNvbmZpZzogVGltZXBpY2tlckNvbXBvbmVudFN0YXRlO1xuICBjb250cm9sczogVGltZXBpY2tlckNvbnRyb2xzO1xufVxuXG5leHBvcnQgY29uc3QgaW5pdGlhbFN0YXRlOiBUaW1lcGlja2VyU3RhdGUgPSB7XG4gIHZhbHVlOiBudWxsLFxuICBjb25maWc6IG5ldyBUaW1lcGlja2VyQ29uZmlnKCksXG4gIGNvbnRyb2xzOiB7XG4gICAgY2FuSW5jcmVtZW50SG91cnM6IHRydWUsXG4gICAgY2FuSW5jcmVtZW50TWludXRlczogdHJ1ZSxcbiAgICBjYW5JbmNyZW1lbnRTZWNvbmRzOiB0cnVlLFxuXG4gICAgY2FuRGVjcmVtZW50SG91cnM6IHRydWUsXG4gICAgY2FuRGVjcmVtZW50TWludXRlczogdHJ1ZSxcbiAgICBjYW5EZWNyZW1lbnRTZWNvbmRzOiB0cnVlLFxuXG4gICAgY2FuVG9nZ2xlTWVyaWRpYW46IHRydWVcbiAgfVxufTtcblxuLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmN5Y2xvbWF0aWMtY29tcGxleGl0eVxuZXhwb3J0IGZ1bmN0aW9uIHRpbWVwaWNrZXJSZWR1Y2VyKHN0YXRlID0gaW5pdGlhbFN0YXRlLCBhY3Rpb246IEFjdGlvbikge1xuICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gICAgY2FzZSBUaW1lcGlja2VyQWN0aW9ucy5XUklURV9WQUxVRToge1xuICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIHN0YXRlLCB7IHZhbHVlOiBhY3Rpb24ucGF5bG9hZCB9KTtcbiAgICB9XG5cbiAgICBjYXNlIFRpb