ngx-scrollbar-v8
Version:
Custom overlay-scrollbars with native scrolling mechanism.
521 lines • 39.6 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, Inject, Input, ViewChild, ContentChild, ElementRef, ChangeDetectorRef, ChangeDetectionStrategy, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { CdkScrollable } from '@angular/cdk/scrolling';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { fromEvent, Subject } from 'rxjs';
import { takeUntil, tap, throttleTime } from 'rxjs/operators';
import { SmoothScroll } from '../smooth-scroll/smooth-scroll';
import { NgScrollbarView } from './ng-scrollbar-view';
var NgScrollbar = /** @class */ (function () {
function NgScrollbar(_changeDetectorRef, _breakpointObserver, _platform) {
this._changeDetectorRef = _changeDetectorRef;
this._breakpointObserver = _breakpointObserver;
this._platform = _platform;
/**
* Horizontal custom scrollbar
*/
this.trackX = false;
/**
* Vertical custom Scrollbar
*/
this.trackY = true;
/**
* Scrollbar visibility
*/
this.shown = 'native';
/**
* Auto update scrollbars on content changes (Mutation Observer)
*/
this.autoUpdate = true;
/**
* The smooth scroll duration when a scrollbar is clicked
*/
this.scrollToDuration = 300;
/**
* Disable custom scrollbars on specific breakpoints
*/
this.disableOnBreakpoints = [
Breakpoints.HandsetLandscape,
Breakpoints.HandsetPortrait
];
this._disabled = false;
/**
* Unsubscribe component observables on destroy
*/
this._unsubscribe$ = new Subject();
/**
* Steam that emits when scrollbar thumbnail needs to update (for internal uses)
*/
this._updateObserver = new Subject();
this.updateObserver = this._updateObserver.asObservable();
}
Object.defineProperty(NgScrollbar.prototype, "disabled", {
/** Disable custom scrollbars and switch back to native scrollbars */
get: /**
* Disable custom scrollbars and switch back to native scrollbars
* @return {?}
*/
function () {
return this._disabled;
},
set: /**
* @param {?} disable
* @return {?}
*/
function (disable) {
disable ? this.disable() : this.enable();
},
enumerable: true,
configurable: true
});
Object.defineProperty(NgScrollbar.prototype, "view", {
/** Viewport Element */
get: /**
* Viewport Element
* @return {?}
*/
function () {
return this.customViewPort
? this.customViewPort.virtualScrollViewport.getElementRef().nativeElement
: this.scrollViewport.getElementRef().nativeElement;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NgScrollbar.prototype, "scrollable", {
get: /**
* @return {?}
*/
function () {
return this.customViewPort
? this.customViewPort.virtualScrollViewport
: this.scrollViewport;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NgScrollbar.prototype, "smoothScroll", {
get: /**
* @return {?}
*/
function () {
return this.customViewPort
? this.customViewPort.smoothScroll
: this.viewSmoothScroll;
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
NgScrollbar.prototype.showScrollbarY = /**
* @return {?}
*/
function () {
return this.shown === 'always' || this.view.scrollHeight > this.view.clientHeight;
};
/**
* @return {?}
*/
NgScrollbar.prototype.showScrollbarX = /**
* @return {?}
*/
function () {
return this.shown === 'always' || this.view.scrollWidth > this.view.clientWidth;
};
/**
* @return {?}
*/
NgScrollbar.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
var _this = this;
// Avoid 'expression has changed after it was checked' error when 'disableOnBreakpoints' is set to false
Promise.resolve().then((/**
* @return {?}
*/
function () {
if (!_this.disabled) {
if (_this.disableOnBreakpoints) {
// Enable/Disable custom scrollbar on breakpoints (Used to disable scrollbars on mobile phones)
_this._breakpointObserver.observe(_this.disableOnBreakpoints).pipe(tap((/**
* @param {?} result
* @return {?}
*/
function (result) { return result.matches ? _this.disable() : _this.enable(); })), takeUntil(_this._unsubscribe$)).subscribe();
}
else {
_this.enable();
}
}
// Update state on content changes
_this.updateObserver.pipe(throttleTime(200), tap((/**
* @return {?}
*/
function () { return _this._changeDetectorRef.markForCheck(); })), takeUntil(_this._unsubscribe$)).subscribe();
if (isPlatformBrowser(_this._platform)) {
// Update on window resize
fromEvent(window, 'resize').pipe(throttleTime(200), tap((/**
* @return {?}
*/
function () { return _this.update(); })), takeUntil(_this._unsubscribe$)).subscribe();
}
}));
};
/**
* @return {?}
*/
NgScrollbar.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this._unsubscribe$.next();
this._unsubscribe$.complete();
if (this._observer) {
this._observer.disconnect();
}
};
/**
* Update scrollbar thumbnail position
*/
/**
* Update scrollbar thumbnail position
* @return {?}
*/
NgScrollbar.prototype.update = /**
* Update scrollbar thumbnail position
* @return {?}
*/
function () {
if (!this.disabled) {
this._updateObserver.next();
}
};
/**
* Enable custom scrollbar
*/
/**
* Enable custom scrollbar
* @return {?}
*/
NgScrollbar.prototype.enable = /**
* Enable custom scrollbar
* @return {?}
*/
function () {
var _this = this;
if (this.view) {
this._disabled = false;
// Update view
this._changeDetectorRef.markForCheck();
if (!this.customViewPort && this.autoUpdate && isPlatformBrowser(this._platform)) {
// Observe content changes
this._observer = new MutationObserver((/**
* @return {?}
*/
function () { return _this.update(); }));
this._observer.observe(this.view, { subtree: true, childList: true, characterData: true });
}
}
};
/**
* Disable custom scrollbar
*/
/**
* Disable custom scrollbar
* @return {?}
*/
NgScrollbar.prototype.disable = /**
* Disable custom scrollbar
* @return {?}
*/
function () {
this._disabled = true;
if (this._observer) {
this._observer.disconnect();
}
};
/**
* @param {?} options
* @return {?}
*/
NgScrollbar.prototype.scrollTo = /**
* @param {?} options
* @return {?}
*/
function (options) {
return this.smoothScroll.scrollTo(options);
};
/**
* @param {?} selector
* @param {?=} offset
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
NgScrollbar.prototype.scrollToElement = /**
* @param {?} selector
* @param {?=} offset
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
function (selector, offset, duration, easeFunc) {
if (offset === void 0) { offset = 0; }
return this.smoothScroll.scrollToElement(selector, offset, duration, easeFunc);
};
/**
* @param {?} to
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
NgScrollbar.prototype.scrollXTo = /**
* @param {?} to
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
function (to, duration, easeFunc) {
return this.smoothScroll.scrollXTo(to, duration, easeFunc);
};
/**
* @param {?} to
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
NgScrollbar.prototype.scrollYTo = /**
* @param {?} to
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
function (to, duration, easeFunc) {
return this.smoothScroll.scrollYTo(to, duration, easeFunc);
};
/**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
NgScrollbar.prototype.scrollToTop = /**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
function (duration, easeFunc) {
return this.smoothScroll.scrollToTop(duration, easeFunc);
};
/**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
NgScrollbar.prototype.scrollToBottom = /**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
function (duration, easeFunc) {
return this.smoothScroll.scrollToBottom(duration, easeFunc);
};
/**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
NgScrollbar.prototype.scrollToRight = /**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
function (duration, easeFunc) {
return this.smoothScroll.scrollToRight(duration, easeFunc);
};
/**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
NgScrollbar.prototype.scrollToLeft = /**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
function (duration, easeFunc) {
return this.smoothScroll.scrollToLeft(duration, easeFunc);
};
NgScrollbar.decorators = [
{ type: Component, args: [{
selector: 'ng-scrollbar',
template: "<div class=\"ng-scrollbar-layout ng-scrollbar-x-layout\"\n [class.ng-scrollbar-invert]=\"invertX\">\n\n <div class=\"ng-scrollbar-layout ng-scrollbar-y-layout\"\n [class.ng-scrollbar-invert]=\"invertY\">\n\n <div class=\"ng-scroll-view-container\">\n <div #view\n cdkScrollable\n smoothScroll\n class=\"ng-scroll-view {{viewClass}}\">\n <ng-content></ng-content>\n </div>\n </div>\n\n <ng-scrollbar-y #y\n *ngIf=\"!disabled && trackY\"\n [class.ng-scrollbar-visible]=\"showScrollbarY()\"\n [barClass]=\"barClass\"\n [thumbClass]=\"thumbClass\"\n [scrollToDuration]=\"scrollToDuration\">\n </ng-scrollbar-y>\n </div>\n\n <ng-scrollbar-x #x\n *ngIf=\"!disabled && trackX\"\n [class.ng-scrollbar-visible]=\"showScrollbarX()\"\n [barClass]=\"barClass\"\n [thumbClass]=\"thumbClass\"\n [scrollToDuration]=\"scrollToDuration\">\n </ng-scrollbar-x>\n\n</div>\n",
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'[attr.customView]': '!!customViewPort',
'[attr.trackX]': 'trackX',
'[attr.trackY]': 'trackY',
'[attr.compact]': 'compact',
'[attr.autoHide]': 'shown === "hover"',
'[attr.disabled]': 'disabled'
},
styles: [":host{display:block;overflow:hidden;--scrollbar-color:transparent;--scrollbar-container-color:transparent;--scrollbar-thumb-color:rgba(0, 0, 0, 0.2);--scrollbar-thumb-hover-color:rgba(0, 0, 0, 0.3);--scrollbar-border-radius:4px;--scrollbar-size:6px;--scrollbar-padding:8px;--scroll-view-margin:0;--scroll-view-color:transparent}:host[trackY=true]>.ng-scrollbar-layout>.ng-scrollbar-layout>.ng-scroll-view-container>.ng-scroll-view{overflow-y:scroll}:host[trackX=true]>.ng-scrollbar-layout>.ng-scrollbar-layout>.ng-scroll-view-container>.ng-scroll-view{overflow-x:scroll}:host>.ng-scrollbar-x-layout{flex-direction:column}:host>.ng-scrollbar-x-layout.ng-scrollbar-invert{flex-direction:column-reverse}:host>.ng-scrollbar-x-layout>.ng-scrollbar-y-layout{flex-direction:row}:host>.ng-scrollbar-x-layout>.ng-scrollbar-y-layout.ng-scrollbar-invert{flex-direction:row-reverse}:host[compact=true]>.ng-scrollbar-x-layout>ng-scrollbar-x{position:absolute;bottom:0}:host[compact=true]>.ng-scrollbar-x-layout.ng-scrollbar-invert>ng-scrollbar-x{top:0;bottom:unset}:host[compact=true]>.ng-scrollbar-x-layout>.ng-scrollbar-y-layout>ng-scrollbar-y{position:absolute;right:0;left:unset}:host[compact=true]>.ng-scrollbar-x-layout>.ng-scrollbar-y-layout.ng-scrollbar-invert>ng-scrollbar-y{right:unset;left:0}:host[autoHide=true]>.ng-scrollbar-layout>.ng-scrollbar-layout>ng-scrollbar-y,:host[autoHide=true]>.ng-scrollbar-layout>ng-scrollbar-x{opacity:0;transition:opacity 120ms ease-out}:host[autoHide=true]:active>.ng-scrollbar-layout>.ng-scrollbar-layout>ng-scrollbar-y,:host[autoHide=true]:active>.ng-scrollbar-layout>ng-scrollbar-x,:host[autoHide=true]:focus>.ng-scrollbar-layout>.ng-scrollbar-layout>ng-scrollbar-y,:host[autoHide=true]:focus>.ng-scrollbar-layout>ng-scrollbar-x,:host[autoHide=true]:hover>.ng-scrollbar-layout>.ng-scrollbar-layout>ng-scrollbar-y,:host[autoHide=true]:hover>.ng-scrollbar-layout>ng-scrollbar-x{opacity:1;transition:opacity 340ms ease-out}:host[customView=true] .ng-scroll-view{overflow:hidden!important}.ng-scroll-view,.ng-scrollbar-layout,:host{position:relative;height:100%;width:100%}.ng-scrollbar-layout{display:flex;min-height:0}.ng-scroll-view-container{flex:1;position:relative;overflow:hidden;margin:var(--scroll-view-margin)}.ng-scroll-view{box-sizing:content-box;-webkit-transform:translateZ(0);transform:translateZ(0);background:var(--scroll-view-color);-webkit-overflow-scrolling:touch}ng-scrollbar-x,ng-scrollbar-y{display:none;box-sizing:border-box;padding:var(--scrollbar-padding);background:var(--scrollbar-container-color)}ng-scrollbar-x.ng-scrollbar-visible,ng-scrollbar-y.ng-scrollbar-visible{display:block}ng-scrollbar-y{top:0;bottom:0}ng-scrollbar-x{left:0;right:0}::ng-deep ng-scrollbar-y .ng-scrollbar{width:var(--scrollbar-size)}::ng-deep ng-scrollbar-y .ng-scrollbar-thumb{width:100%}::ng-deep ng-scrollbar-x .ng-scrollbar{height:var(--scrollbar-size)}::ng-deep ng-scrollbar-x .ng-scrollbar-thumb{height:100%}::ng-deep .ng-scrollbar{height:100%;width:100%;z-index:1;border-radius:var(--scrollbar-border-radius);background-color:var(--scrollbar-color)}::ng-deep .ng-scrollbar-thumb{box-sizing:border-box;position:relative;width:0;height:0;border-radius:inherit;background-color:var(--scrollbar-thumb-color);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);transition:height 150ms ease-out}::ng-deep .ng-scrollbar-thumb:active,::ng-deep .ng-scrollbar-thumb:hover{background-color:var(--scrollbar-thumb-hover-color)}::ng-deep .ng-custom-scroll-view{height:100%}.show-native-scrollbars,:host[disabled=true] .ng-scroll-view,:host[disabled=true] ::ng-deep .ng-scroll-view>.ng-custom-scroll-view{margin:0!important;padding:0!important}.hide-native-scrollbars,:host[disabled=false] .ng-scroll-view,:host[disabled=false] ::ng-deep .ng-scroll-view>.ng-custom-scroll-view{margin-right:-30px!important;padding-right:30px!important;margin-bottom:-30px!important;padding-bottom:30px!important}"]
}] }
];
/** @nocollapse */
NgScrollbar.ctorParameters = function () { return [
{ type: ChangeDetectorRef },
{ type: BreakpointObserver },
{ type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }
]; };
NgScrollbar.propDecorators = {
trackX: [{ type: Input }],
trackY: [{ type: Input }],
shown: [{ type: Input }],
autoUpdate: [{ type: Input }],
viewClass: [{ type: Input }],
barClass: [{ type: Input }],
thumbClass: [{ type: Input }],
scrollToDuration: [{ type: Input }],
compact: [{ type: Input }],
invertY: [{ type: Input }],
invertX: [{ type: Input }],
disableOnBreakpoints: [{ type: Input }],
disabled: [{ type: Input, args: ['disabled',] }],
verticalScrollbar: [{ type: ViewChild, args: ['y', { read: ElementRef, static: false },] }],
horizontalScrollbar: [{ type: ViewChild, args: ['x', { read: ElementRef, static: false },] }],
scrollViewport: [{ type: ViewChild, args: [CdkScrollable, { static: true },] }],
viewSmoothScroll: [{ type: ViewChild, args: [SmoothScroll, { static: true },] }],
customViewPort: [{ type: ContentChild, args: [NgScrollbarView, { static: true },] }]
};
return NgScrollbar;
}());
export { NgScrollbar };
if (false) {
/**
* Horizontal custom scrollbar
* @type {?}
*/
NgScrollbar.prototype.trackX;
/**
* Vertical custom Scrollbar
* @type {?}
*/
NgScrollbar.prototype.trackY;
/**
* Scrollbar visibility
* @type {?}
*/
NgScrollbar.prototype.shown;
/**
* Auto update scrollbars on content changes (Mutation Observer)
* @type {?}
*/
NgScrollbar.prototype.autoUpdate;
/**
* Viewport class
* @type {?}
*/
NgScrollbar.prototype.viewClass;
/**
* Scrollbars class
* @type {?}
*/
NgScrollbar.prototype.barClass;
/**
* Scrollbars thumbnails class
* @type {?}
*/
NgScrollbar.prototype.thumbClass;
/**
* The smooth scroll duration when a scrollbar is clicked
* @type {?}
*/
NgScrollbar.prototype.scrollToDuration;
/**
* Compact mode
* @type {?}
*/
NgScrollbar.prototype.compact;
/**
* Invert vertical scrollbar position, if set the scrollbar will be on the right
* @type {?}
*/
NgScrollbar.prototype.invertY;
/**
* Invert horizontal scrollbar position, if set the scrollbar will go the top
* @type {?}
*/
NgScrollbar.prototype.invertX;
/**
* Disable custom scrollbars on specific breakpoints
* @type {?}
*/
NgScrollbar.prototype.disableOnBreakpoints;
/**
* @type {?}
* @private
*/
NgScrollbar.prototype._disabled;
/**
* Scrollbars ElementRef
* @type {?}
*/
NgScrollbar.prototype.verticalScrollbar;
/** @type {?} */
NgScrollbar.prototype.horizontalScrollbar;
/**
* Default viewport and smoothScroll references
* @type {?}
*/
NgScrollbar.prototype.scrollViewport;
/** @type {?} */
NgScrollbar.prototype.viewSmoothScroll;
/**
* Virtual viewport and smoothScroll references
* @type {?}
*/
NgScrollbar.prototype.customViewPort;
/**
* Unsubscribe component observables on destroy
* @type {?}
* @private
*/
NgScrollbar.prototype._unsubscribe$;
/**
* Observe content changes
* @type {?}
* @private
*/
NgScrollbar.prototype._observer;
/**
* Steam that emits when scrollbar thumbnail needs to update (for internal uses)
* @type {?}
* @private
*/
NgScrollbar.prototype._updateObserver;
/** @type {?} */
NgScrollbar.prototype.updateObserver;
/**
* @type {?}
* @private
*/
NgScrollbar.prototype._changeDetectorRef;
/**
* @type {?}
* @private
*/
NgScrollbar.prototype._breakpointObserver;
/**
* @type {?}
* @private
*/
NgScrollbar.prototype._platform;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctc2Nyb2xsYmFyLmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LXNjcm9sbGJhci8iLCJzb3VyY2VzIjpbInNjcm9sbGJhci9uZy1zY3JvbGxiYXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsTUFBTSxFQUNOLEtBQUssRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUdaLFVBQVUsRUFDVixpQkFBaUIsRUFDakIsdUJBQXVCLEVBQ3ZCLFdBQVcsRUFDWixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUNsRCxPQUFPLEVBQUMsYUFBYSxFQUEyQixNQUFNLHdCQUF3QixDQUFDO0FBQy9FLE9BQU8sRUFBQyxrQkFBa0IsRUFBRSxXQUFXLEVBQWtCLE1BQU0scUJBQXFCLENBQUM7QUFDckYsT0FBTyxFQUFDLFNBQVMsRUFBYyxPQUFPLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDcEQsT0FBTyxFQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUQsT0FBTyxFQUFrQixZQUFZLEVBQXVCLE1BQU0sZ0NBQWdDLENBQUM7QUFDbkcsT0FBTyxFQUFDLGVBQWUsRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBRXBEO0lBK0ZFLHFCQUFvQixrQkFBcUMsRUFDckMsbUJBQXVDLEVBQ2xCLFNBQWlCO1FBRnRDLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBbUI7UUFDckMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFvQjtRQUNsQixjQUFTLEdBQVQsU0FBUyxDQUFROzs7O1FBaEZqRCxXQUFNLEdBQUcsS0FBSyxDQUFDOzs7O1FBRWYsV0FBTSxHQUFHLElBQUksQ0FBQzs7OztRQUVkLFVBQUssR0FBa0MsUUFBUSxDQUFDOzs7O1FBRWhELGVBQVUsR0FBRyxJQUFJLENBQUM7Ozs7UUFRbEIscUJBQWdCLEdBQUcsR0FBRyxDQUFD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MEU7O0lBQzFFLHVDQUEwRTs7Ozs7SUFHMUUscUNBQWlGOzs7Ozs7SUFzQmpGLG9DQUFzQzs7Ozs7O0lBRXRDLGdDQUFvQzs7Ozs7O0lBR3BDLHNDQUF3Qzs7SUFDeEMscUNBQXFEOzs7OztJQUV6Qyx5Q0FBNkM7Ozs7O0lBQzdDLDBDQUErQzs7Ozs7SUFDL0MsZ0NBQThDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBJbmplY3QsXG4gIElucHV0LFxuICBWaWV3Q2hpbGQsXG4gIENvbnRlbnRDaGlsZCxcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgT25EZXN0cm95LFxuICBFbGVtZW50UmVmLFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIFBMQVRGT1JNX0lEXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtpc1BsYXRmb3JtQnJvd3Nlcn0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7Q2RrU2Nyb2xsYWJsZSwgQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0fSBmcm9tICdAYW5ndWxhci9jZGsvc2Nyb2xsaW5nJztcbmltcG9ydCB7QnJlYWtwb2ludE9ic2VydmVyLCBCcmVha3BvaW50cywgQnJlYWtwb2ludFN0YXRlfSBmcm9tICdAYW5ndWxhci9jZGsvbGF5b3V0JztcbmltcG9ydCB7ZnJvbUV2ZW50LCBPYnNlcnZhYmxlLCBTdWJqZWN0fSBmcm9tICdyeGpzJztcbmltcG9ydCB7dGFrZVVudGlsLCB0YXAsIHRocm90dGxlVGltZX0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtTY3JvbGxUb09wdGlvbnMsIFNtb290aFNjcm9sbCwgU21vb3RoU2Nyb2xsRWFzZUZ1bmN9IGZyb20gJy4uL3Ntb290aC1zY3JvbGwvc21vb3RoLXNjcm9sbCc7XG5pbXBvcnQge05nU2Nyb2xsYmFyVmlld30gZnJvbSAnLi9uZy1zY3JvbGxiYXItdmlldyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25nLXNjcm9sbGJhcicsXG4gIHRlbXBsYXRlVXJsOiAnbmctc2Nyb2xsYmFyLmh0bWwnLFxuICBzdHlsZVVybHM6IFsnbmctc2Nyb2xsYmFyLnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGhvc3Q6IHtcbiAgICAnW2F0dHIuY3VzdG9tVmlld10nOiAnISFjdXN0b21WaWV3UG9ydCcsXG4gICAgJ1thdHRyLnRyYWNrWF0nOiAndHJhY2tYJyxcbiAgICAnW2F0dHIudHJhY2tZXSc6ICd0cmFja1knLFxuICAgICdbYXR0ci5jb21wYWN0XSc6ICdjb21wYWN0JyxcbiAgICAnW2F0dHIuYXV0b0hpZGVdJzogJ3Nob3duID09PSBcImhvdmVyXCInLFxuICAgICdbYXR0ci5kaXNhYmxlZF0nOiAnZGlzYWJsZWQnXG4gIH1cbn0pXG5leHBvcnQgY2xhc3MgTmdTY3JvbGxiYXIgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuXG4gIC8qKiBIb3Jpem9udGFsIGN1c3RvbSBzY3JvbGxiYXIgKi9cbiAgQElucHV0KCkgdHJhY2tYID0gZmFsc2U7XG4gIC8qKiBWZXJ0aWNhbCBjdXN0b20gU2Nyb2xsYmFyICovXG4gIEBJbnB1dCgpIHRyYWNrWSA9IHRydWU7XG4gIC8qKiBTY3JvbGxiYXIgdmlzaWJpbGl0eSAqL1xuICBASW5wdXQoKSBzaG93bjogJ2hvdmVyJyB8ICdhbHdheXMnIHwgJ25hdGl2ZScgPSAnbmF0aXZlJztcbiAgLyoqIEF1dG8gdXBkYXRlIHNjcm9sbGJhcnMgb24gY29udGVudCBjaGFuZ2VzIChNdXRhdGlvbiBPYnNlcnZlcikgKi9cbiAgQElucHV0KCkgYXV0b1VwZGF0ZSA9IHRydWU7XG4gIC8qKiBWaWV3cG9ydCBjbGFzcyAqL1xuICBASW5wdXQoKSB2aWV3Q2xhc3M6IHN0cmluZztcbiAgLyoqIFNjcm9sbGJhcnMgY2xhc3MgKi9cbiAgQElucHV0KCkgYmFyQ2xhc3M6IHN0cmluZztcbiAgLyoqIFNjcm9sbGJhcnMgdGh1bWJuYWlscyBjbGFzcyAqL1xuICBASW5wdXQoKSB0aHVtYkNsYXNzOiBzdHJpbmc7XG4gIC8qKiBUaGUgc21vb3RoIHNjcm9sbCBkdXJhdGlvbiB3aGVuIGEgc2Nyb2xsYmFyIGlzIGNsaWNrZWQgKi9cbiAgQElucHV0KCkgc2Nyb2xsVG9EdXJhdGlvbiA9IDMwMDtcbiAgLyoqIENvbXBhY3QgbW9kZSAqL1xuICBASW5wdXQoKSBjb21wYWN0OiBib29sZWFuO1xuICAvKiogSW52ZXJ0IHZlcnRpY2FsIHNjcm9sbGJhciBwb3NpdGlvbiwgaWYgc2V0IHRoZSBzY3JvbGxiYXIgd2lsbCBiZSBvbiB0aGUgcmlnaHQgKi9cbiAgQElucHV0KCkgaW52ZXJ0WTogYm9vbGVhbjtcbiAgLyoqIEludmVydCBob3Jpem9udGFsIHNjcm9sbGJhciBwb3NpdGlvbiwgaWYgc2V0IHRoZSBzY3JvbGxiYXIgd2lsbCBnbyB0aGUgdG9wICovXG4gIEBJbnB1dCgpIGludmVydFg6IGJvb2xlYW47XG4gIC8qKiBEaXNhYmxlIGN1c3RvbSBzY3JvbGxiYXJzIG9uIHNwZWNpZmljIGJyZWFrcG9pbnRzICovXG4gIEBJbnB1dCgpIGRpc2FibGVPbkJyZWFrcG9pbnRzID0gW1xuICAgIEJyZWFrcG9pbnRzLkhhbmRzZXRMYW5kc2NhcGUsXG4gICAgQnJlYWtwb2ludHMuSGFuZHNldFBvcnRyYWl0XG4gIF07XG5cbiAgLyoqIERpc2FibGUgY3VzdG9tIHNjcm9sbGJhcnMgYW5kIHN3aXRjaCBiYWNrIHRvIG5hdGl2ZSBzY3JvbGxiYXJzICovXG4gIEBJbnB1dCgnZGlzYWJsZWQnKVxuICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2Rpc2FibGVkO1xuICB9XG5cbiAgc2V0IGRpc2FibGVkKGRpc2FibGU6IGJvb2xlYW4pIHtcbiAgICBkaXNhYmxlID8gdGhpcy5kaXNhYmxlKCkgOiB0aGlzLmVuYWJsZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBfZGlzYWJsZWQgPSBmYWxzZTtcblxuICAvKiogU2Nyb2xsYmFycyBFbGVtZW50UmVmICovXG4gIEBWaWV3Q2hpbGQoJ3knLCB7IHJlYWQ6IEVsZW1lbnRSZWYsIHN0YXRpYzogZmFsc2UgfSkgdmVydGljYWxTY3JvbGxiYXI6IEVsZW1lbnRSZWY7XG4gIEBWaWV3Q2hpbGQoJ3gnLCB7IHJlYWQ6IEVsZW1lbnRSZWYsIHN0YXRpYzogZmFsc2UgfSkgaG9yaXpvbnRhbFNjcm9sbGJhcjogRWxlbWVudFJlZjtcblxuICAvKiogRGVmYXVsdCB2aWV3cG9ydCBhbmQgc21vb3RoU2Nyb2xsIHJlZmVyZW5jZXMgKi9cbiAgQFZpZXdDaGlsZChDZGtTY3JvbGxhYmxlLCB7IHN0YXRpYzogdHJ1ZSB9KSBzY3JvbGxWaWV3cG9ydDogQ2RrU2Nyb2xsYWJsZTtcbiAgQFZpZXdDaGlsZChTbW9vdGhTY3JvbGwsIHsgc3RhdGljOiB0cnVlIH0pIHZpZXdTbW9vdGhTY3JvbGw6IFNtb290aFNjcm9sbDtcblxuICAvKiogVmlydHVhbCB2aWV3cG9ydCBhbmQgc21vb3RoU2Nyb2xsIHJlZmVyZW5jZXMgKi9cbiAgQENvbnRlbnRDaGlsZChOZ1Njcm9sbGJhclZpZXcsIHsgc3RhdGljOiB0cnVlIH0pIGN1c3RvbVZpZXdQb3J0OiBOZ1Njcm9sbGJhclZpZXc7XG5cbiAgLyoqIFZpZXdwb3J0IEVsZW1lbnQgKi9cbiAgZ2V0IHZpZXcoKTogSFRNTEVsZW1lbnQge1xuICAgIHJldHVybiB0aGlzLmN1c3RvbVZpZXdQb3J0XG4gICAgICA/IHRoaXMuY3VzdG9tVmlld1BvcnQudmlydHVhbFNjcm9sbFZpZXdwb3J0LmdldEVsZW1lbnRSZWYoKS5uYXRpdmVFbGVtZW50XG4gICAgICA6IHRoaXMuc2Nyb2xsVmlld3BvcnQuZ2V0RWxlbWVudFJlZigpLm5hdGl2ZUVsZW1lbnQ7XG4gIH1cblxuICBnZXQgc2Nyb2xsYWJsZSgpOiBDZGtTY3JvbGxhYmxlIHwgQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0IHtcbiAgICByZXR1cm4gdGhpcy5jdXN0b21WaWV3UG9ydFxuICAgICAgPyB0aGlzLmN1c3RvbVZpZXdQb3J0LnZpcnR1YWxTY3JvbGxWaWV3cG9ydFxuICAgICAgOiB0aGlzLnNjcm9sbFZpZXdwb3J0O1xuICB9XG5cbiAgZ2V0IHNtb290aFNjcm9sbCgpOiBTbW9vdGhTY3JvbGwge1xuICAgIHJldHVybiB0aGlzLmN1c3RvbVZpZXdQb3J0XG4gICAgICA/IHRoaXMuY3VzdG9tVmlld1BvcnQuc21vb3RoU2Nyb2xsXG4gICAgICA6IHRoaXMudmlld1Ntb290aFNjcm9sbDtcbiAgfVxuXG4gIC8qKiBVbnN1YnNjcmliZSBjb21wb25lbnQgb2JzZXJ2YWJsZXMgb24gZGVzdHJveSAqL1xuICBwcml2YXRlIF91bnN1YnNjcmliZSQgPSBuZXcgU3ViamVjdCgpO1xuICAvKiogT2JzZXJ2ZSBjb250ZW50IGNoYW5nZXMgKi9cbiAgcHJpdmF0ZSBfb2JzZXJ2ZXI6IE11dGF0aW9uT2JzZXJ2ZXI7XG5cbiAgLyoqIFN0ZWFtIHRoYXQgZW1pdHMgd2hlbiBzY3JvbGxiYXIgdGh1bWJuYWlsIG5lZWRzIHRvIHVwZGF0ZSAoZm9yIGludGVybmFsIHVzZXMpICovXG4gIHByaXZhdGUgX3VwZGF0ZU9ic2VydmVyID0gbmV3IFN1YmplY3QoKTtcbiAgdXBkYXRlT2JzZXJ2ZXIgPSB0aGlzLl91cGRhdGVPYnNlcnZlci5hc09ic2VydmFibGUoKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9jaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgICAgICAgICAgIHByaXZhdGUgX2JyZWFrcG9pbnRPYnNlcnZlcjogQnJlYWtwb2ludE9ic2VydmVyLFxuICAgICAgICAgICAgICBASW5qZWN0KFBMQVRGT1JNX0lEKSBwcml2YXRlIF9wbGF0Zm9ybTogT2JqZWN0KSB7XG4gIH1cblxuICBzaG93U2Nyb2xsYmFyWSgpIHtcbiAgICByZXR1cm4gdGhpcy5zaG93biA9PT0gJ2Fsd2F5cycgfHwgdGhpcy52aWV3LnNjcm9sbEhlaWdodCA+IHRoaXMudmlldy5jbGllbnRIZWlnaHQ7XG4gIH1cblxuICBzaG93U2Nyb2xsYmFyWCgpIHtcbiAgICByZXR1cm4gdGhpcy5zaG93biA9PT0gJ2Fsd2F5cycgfHwgdGhpcy52aWV3LnNjcm9sbFdpZHRoID4gdGhpcy52aWV3LmNsaWVudFdpZHRoO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIC8vIEF2b2lkICdleHByZXNzaW9uIGhhcyBjaGFuZ2VkIGFmdGVyIGl0IHdhcyBjaGVja2VkJyBlcnJvciB3aGVuICdkaXNhYmxlT25CcmVha3BvaW50cycgaXMgc2V0IHRvIGZhbHNlXG4gICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgaWYgKHRoaXMuZGlzYWJsZU9uQnJlYWtwb2ludHMpIHtcbiAgICAgICAgICAvLyBFbmFibGUvRGlzYWJsZSBjdXN0b20gc2Nyb2xsYmFyIG9uIGJyZWFrcG9pbnRzIChVc2VkIHRvIGRpc2FibGUgc2Nyb2xsYmFycyBvbiBtb2JpbGUgcGhvbmVzKVxuICAgICAgICAgIHRoaXMuX2JyZWFrcG9pbnRPYnNlcnZlci5vYnNlcnZlKHRoaXMuZGlzYWJsZU9uQnJlYWtwb2ludHMpLnBpcGUoXG4gICAgICAgICAgICB0YXAoKHJlc3VsdDogQnJlYWtwb2ludFN0YXRlKSA9PiByZXN1bHQubWF0Y2hlcyA/IHRoaXMuZGlzYWJsZSgpIDogdGhpcy5lbmFibGUoKSksXG4gICAgICAgICAgICB0YWtlVW50aWwodGhpcy5fdW5zdWJzY3JpYmUkKVxuICAgICAgICAgICkuc3Vic2NyaWJlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5lbmFibGUoKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBVcGRhdGUgc3RhdGUgb24gY29udGVudCBjaGFuZ2VzXG4gICAgICB0aGlzLnVwZGF0ZU9ic2VydmVyLnBpcGUoXG4gICAgICAgIHRocm90dGxlVGltZSgyMDApLFxuICAgICAgICB0YXAoKCkgPT4gdGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCkpLFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fdW5zdWJzY3JpYmUkKVxuICAgICAgKS5zdWJzY3JpYmUoKTtcblxuXG4gICAgICBpZiAoaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5fcGxhdGZvcm0pKSB7XG4gICAgICAgIC8vIFVwZGF0ZSBvbiB3aW5kb3cgcmVzaXplXG4gICAgICAgIGZyb21FdmVudCh3aW5kb3csICdyZXNpemUnKS5waXBlKFxuICAgICAgICAgIHRocm90dGxlVGltZSgyMDApLFxuICAgICAgICAgIHRhcCgoKSA9PiB0aGlzLnVwZGF0ZSgpKSxcbiAgICAgICAgICB0YWtlVW50aWwodGhpcy5fdW5zdWJzY3JpYmUkKVxuICAgICAgICApLnN1YnNjcmliZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5fdW5zdWJzY3JpYmUkLm5leHQoKTtcbiAgICB0aGlzLl91bnN1YnNjcmliZSQuY29tcGxldGUoKTtcbiAgICBpZiAodGhpcy5fb2JzZXJ2ZXIpIHtcbiAgICAgIHRoaXMuX29ic2VydmVyLmRpc2Nvbm5lY3QoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlIHNjcm9sbGJhciB0aHVtYm5haWwgcG9zaXRpb25cbiAgICovXG4gIHVwZGF0ZSgpIHtcbiAgICBpZiAoIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZU9ic2VydmVyLm5leHQoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRW5hYmxlIGN1c3RvbSBzY3JvbGxiYXJcbiAgICovXG4gIGVuYWJsZSgpIHtcbiAgICBpZiAodGhpcy52aWV3KSB7XG4gICAgICB0aGlzLl9kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgLy8gVXBkYXRlIHZpZXdcbiAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuXG4gICAgICBpZiAoIXRoaXMuY3VzdG9tVmlld1BvcnQgJiYgdGhpcy5hdXRvVXBkYXRlICYmIGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMuX3BsYXRmb3JtKSkge1xuICAgICAgICAvLyBPYnNlcnZlIGNvbnRlbnQgY2hhbmdlc1xuICAgICAgICB0aGlzLl9vYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKCgpID0+IHRoaXMudXBkYXRlKCkpO1xuICAgICAgICB0aGlzLl9vYnNlcnZlci5vYnNlcnZlKHRoaXMudmlldywge3N1YnRyZWU6IHRydWUsIGNoaWxkTGlzdDogdHJ1ZSwgY2hhcmFjdGVyRGF0YTogdHJ1ZX0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNhYmxlIGN1c3RvbSBzY3JvbGxiYXJcbiAgICovXG4gIGRpc2FibGUoKSB7XG4gICAgdGhpcy5fZGlzYWJsZWQgPSB0cnVlO1xuICAgIGlmICh0aGlzLl9vYnNlcnZlcikge1xuICAgICAgdGhpcy5fb2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgIH1cbiAgfVxuXG4gIHNjcm9sbFRvKG9wdGlvbnM6IFNjcm9sbFRvT3B0aW9ucyk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnNtb290aFNjcm9sbC5zY3JvbGxUbyhvcHRpb25zKTtcbiAgfVxuXG4gIHNjcm9sbFRvRWxlbWVudChzZWxlY3Rvcjogc3RyaW5nLCBvZmZzZXQgPSAwLCBkdXJhdGlvbj86IG51bWJlciwgZWFzZUZ1bmM/OiBTbW9vdGhTY3JvbGxFYXNlRnVuYyk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnNtb290aFNjcm9sbC5zY3JvbGxUb0VsZW1lbnQoc2VsZWN0b3IsIG9mZnNldCwgZHVyYXRpb24sIGVhc2VGdW5jKTtcbiAgfVxuXG4gIHNjcm9sbFhUbyh0bzogbnVtYmVyLCBkdXJhdGlvbj86IG51bWJlciwgZWFzZUZ1bmM/OiBTbW9vdGhTY3JvbGxFYXNlRnVuYyk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnNtb290aFNjcm9sbC5zY3JvbGxYVG8odG8sIGR1cmF0aW9uLCBlYXNlRnVuYyk7XG4gIH1cblxuICBzY3JvbGxZVG8odG86IG51bWJlciwgZHVyYXRpb24/OiBudW1iZXIsIGVhc2VGdW5jPzogU21vb3RoU2Nyb2xsRWFzZUZ1bmMpOiBPYnNlcnZhYmxlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5zbW9vdGhTY3JvbGwuc2Nyb2xsWVRvKHRvLCBkdXJhdGlvbiwgZWFzZUZ1bmMpO1xuICB9XG5cbiAgc2Nyb2xsVG9Ub3AoZHVyYXRpb24/OiBudW1iZXIsIGVhc2VGdW5jPzogU21vb3RoU2Nyb2xsRWFzZUZ1bmMpOiBPYnNlcnZhYmxlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5zbW9vdGhTY3JvbGwuc2Nyb2xsVG9Ub3AoZHVyYXRpb24sIGVhc2VGdW5jKTtcbiAgfVxuXG4gIHNjcm9sbFRvQm90dG9tKGR1cmF0aW9uPzogbnVtYmVyLCBlYXNlRnVuYz86IFNtb290aFNjcm9sbEVhc2VGdW5jKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuc21vb3RoU2Nyb2xsLnNjcm9sbFRvQm90dG9tKGR1cmF0aW9uLCBlYXNlRnVuYyk7XG4gIH1cblxuICBzY3JvbGxUb1JpZ2h0KGR1cmF0aW9uPzogbnVtYmVyLCBlYXNlRnVuYz86IFNtb290aFNjcm9sbEVhc2VGdW5jKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuc21vb3RoU2Nyb2xsLnNjcm9sbFRvUmlnaHQoZHVyYXRpb24sIGVhc2VGdW5jKTtcbiAgfVxuXG4gIHNjcm9sbFRvTGVmdChkdXJhdGlvbj86IG51bWJlciwgZWFzZUZ1bmM/OiBTbW9vdGhTY3JvbGxFYXNlRnVuYyk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnNtb290aFNjcm9sbC5zY3JvbGxUb0xlZnQoZHVyYXRpb24sIGVhc2VGdW5jKTtcbiAgfVxufVxuIl19