ngx-scrollbar-v8
Version:
Custom overlay-scrollbars with native scrolling mechanism.
427 lines • 36.3 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';
export class NgScrollbar {
/**
* @param {?} _changeDetectorRef
* @param {?} _breakpointObserver
* @param {?} _platform
*/
constructor(_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();
}
/**
* Disable custom scrollbars and switch back to native scrollbars
* @return {?}
*/
get disabled() {
return this._disabled;
}
/**
* @param {?} disable
* @return {?}
*/
set disabled(disable) {
disable ? this.disable() : this.enable();
}
/**
* Viewport Element
* @return {?}
*/
get view() {
return this.customViewPort
? this.customViewPort.virtualScrollViewport.getElementRef().nativeElement
: this.scrollViewport.getElementRef().nativeElement;
}
/**
* @return {?}
*/
get scrollable() {
return this.customViewPort
? this.customViewPort.virtualScrollViewport
: this.scrollViewport;
}
/**
* @return {?}
*/
get smoothScroll() {
return this.customViewPort
? this.customViewPort.smoothScroll
: this.viewSmoothScroll;
}
/**
* @return {?}
*/
showScrollbarY() {
return this.shown === 'always' || this.view.scrollHeight > this.view.clientHeight;
}
/**
* @return {?}
*/
showScrollbarX() {
return this.shown === 'always' || this.view.scrollWidth > this.view.clientWidth;
}
/**
* @return {?}
*/
ngAfterViewInit() {
// Avoid 'expression has changed after it was checked' error when 'disableOnBreakpoints' is set to false
Promise.resolve().then((/**
* @return {?}
*/
() => {
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 {?}
*/
(result) => 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 {?}
*/
() => this._changeDetectorRef.markForCheck())), takeUntil(this._unsubscribe$)).subscribe();
if (isPlatformBrowser(this._platform)) {
// Update on window resize
fromEvent(window, 'resize').pipe(throttleTime(200), tap((/**
* @return {?}
*/
() => this.update())), takeUntil(this._unsubscribe$)).subscribe();
}
}));
}
/**
* @return {?}
*/
ngOnDestroy() {
this._unsubscribe$.next();
this._unsubscribe$.complete();
if (this._observer) {
this._observer.disconnect();
}
}
/**
* Update scrollbar thumbnail position
* @return {?}
*/
update() {
if (!this.disabled) {
this._updateObserver.next();
}
}
/**
* Enable custom scrollbar
* @return {?}
*/
enable() {
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 {?}
*/
() => this.update()));
this._observer.observe(this.view, { subtree: true, childList: true, characterData: true });
}
}
}
/**
* Disable custom scrollbar
* @return {?}
*/
disable() {
this._disabled = true;
if (this._observer) {
this._observer.disconnect();
}
}
/**
* @param {?} options
* @return {?}
*/
scrollTo(options) {
return this.smoothScroll.scrollTo(options);
}
/**
* @param {?} selector
* @param {?=} offset
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
scrollToElement(selector, offset = 0, duration, easeFunc) {
return this.smoothScroll.scrollToElement(selector, offset, duration, easeFunc);
}
/**
* @param {?} to
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
scrollXTo(to, duration, easeFunc) {
return this.smoothScroll.scrollXTo(to, duration, easeFunc);
}
/**
* @param {?} to
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
scrollYTo(to, duration, easeFunc) {
return this.smoothScroll.scrollYTo(to, duration, easeFunc);
}
/**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
scrollToTop(duration, easeFunc) {
return this.smoothScroll.scrollToTop(duration, easeFunc);
}
/**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
scrollToBottom(duration, easeFunc) {
return this.smoothScroll.scrollToBottom(duration, easeFunc);
}
/**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
scrollToRight(duration, easeFunc) {
return this.smoothScroll.scrollToRight(duration, easeFunc);
}
/**
* @param {?=} duration
* @param {?=} easeFunc
* @return {?}
*/
scrollToLeft(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 = () => [
{ 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 },] }]
};
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctc2Nyb2xsYmFyLmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LXNjcm9sbGJhci8iLCJzb3VyY2VzIjpbInNjcm9sbGJhci9uZy1zY3JvbGxiYXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsTUFBTSxFQUNOLEtBQUssRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUdaLFVBQVUsRUFDVixpQkFBaUIsRUFDakIsdUJBQXVCLEVBQ3ZCLFdBQVcsRUFDWixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUNsRCxPQUFPLEVBQUMsYUFBYSxFQUEyQixNQUFNLHdCQUF3QixDQUFDO0FBQy9FLE9BQU8sRUFBQyxrQkFBa0IsRUFBRSxXQUFXLEVBQWtCLE1BQU0scUJBQXFCLENBQUM7QUFDckYsT0FBTyxFQUFDLFNBQVMsRUFBYyxPQUFPLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDcEQsT0FBTyxFQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUQsT0FBTyxFQUFrQixZQUFZLEVBQXVCLE1BQU0sZ0NBQWdDLENBQUM7QUFDbkcsT0FBTyxFQUFDLGVBQWUsRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBZ0JwRCxNQUFNLE9BQU8sV0FBVzs7Ozs7O0lBaUZ0QixZQUFvQixrQkFBcUMsRUFDckMsbUJBQXVDLEVBQ2xCLFNBQWlCO1FBRnRDLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBbUI7UUFDckMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFvQjtRQUNsQixjQUFTLEdBQVQsU0FBUyxDQUFROzs7O1FBaEZqRCxXQUFNLEdBQUcsS0FBSyxDQUFDOzs7O1FBRWYsV0FBTSxHQUFHLElBQUksQ0FBQzs7OztRQUVkLFVBQUssR0FBa0MsUUFBUSxDQUFDOzs7O1FBRWhELGVBQVUsR0FBRyxJQUFJLENBQUM7Ozs7UUFRbEIs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VUFBVTtnQ0FZaEIsU0FBUyxTQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtrQ0FDbEQsU0FBUyxTQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTs2QkFHbEQsU0FBUyxTQUFDLGFBQWEsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7K0JBQ3pDLFNBQVMsU0FBQyxZQUFZLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFOzZCQUd4QyxZQUFZLFNBQUMsZUFBZSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTs7Ozs7OztJQWhEL0MsNkJBQXdCOzs7OztJQUV4Qiw2QkFBdUI7Ozs7O0lBRXZCLDRCQUF5RDs7Ozs7SUFFekQsaUNBQTJCOzs7OztJQUUzQixnQ0FBMkI7Ozs7O0lBRTNCLCtCQUEwQjs7Ozs7SUFFMUIsaUNBQTRCOzs7OztJQUU1Qix1Q0FBZ0M7Ozs7O0lBRWhDLDhCQUEwQjs7Ozs7SUFFMUIsOEJBQTBCOzs7OztJQUUxQiw4QkFBMEI7Ozs7O0lBRTFCLDJDQUdFOzs7OztJQVlGLGdDQUEwQjs7Ozs7SUFHMUIsd0NBQW1GOztJQUNuRiwwQ0FBcUY7Ozs7O0lBR3JGLHFDQUEwRTs7SUFDMUUsdUNBQTBFOzs7OztJQUcxRSxxQ0FBaUY7Ozs7OztJQXNCakYsb0NBQXNDOzs7Ozs7SUFFdEMsZ0NBQW9DOzs7Ozs7SUFHcEMsc0NBQXdDOztJQUN4QyxxQ0FBcUQ7Ozs7O0lBRXpDLHlDQUE2Qzs7Ozs7SUFDN0MsMENBQStDOzs7OztJQUMvQyxnQ0FBOEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIEluamVjdCxcbiAgSW5wdXQsXG4gIFZpZXdDaGlsZCxcbiAgQ29udGVudENoaWxkLFxuICBBZnRlclZpZXdJbml0LFxuICBPbkRlc3Ryb3ksXG4gIEVsZW1lbnRSZWYsXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgUExBVEZPUk1fSURcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge2lzUGxhdGZvcm1Ccm93c2VyfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtDZGtTY3JvbGxhYmxlLCBDZGtWaXJ0dWFsU2Nyb2xsVmlld3BvcnR9IGZyb20gJ0Bhbmd1bGFyL2Nkay9zY3JvbGxpbmcnO1xuaW1wb3J0IHtCcmVha3BvaW50T2JzZXJ2ZXIsIEJyZWFrcG9pbnRzLCBCcmVha3BvaW50U3RhdGV9IGZyb20gJ0Bhbmd1bGFyL2Nkay9sYXlvdXQnO1xuaW1wb3J0IHtmcm9tRXZlbnQsIE9ic2VydmFibGUsIFN1YmplY3R9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHt0YWtlVW50aWwsIHRhcCwgdGhyb3R0bGVUaW1lfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge1Njcm9sbFRvT3B0aW9ucywgU21vb3RoU2Nyb2xsLCBTbW9vdGhTY3JvbGxFYXNlRnVuY30gZnJvbSAnLi4vc21vb3RoLXNjcm9sbC9zbW9vdGgtc2Nyb2xsJztcbmltcG9ydCB7TmdTY3JvbGxiYXJWaWV3fSBmcm9tICcuL25nLXNjcm9sbGJhci12aWV3JztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmctc2Nyb2xsYmFyJyxcbiAgdGVtcGxhdGVVcmw6ICduZy1zY3JvbGxiYXIuaHRtbCcsXG4gIHN0eWxlVXJsczogWyduZy1zY3JvbGxiYXIuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgaG9zdDoge1xuICAgICdbYXR0ci5jdXN0b21WaWV3XSc6ICchIWN1c3RvbVZpZXdQb3J0JyxcbiAgICAnW2F0dHIudHJhY2tYXSc6ICd0cmFja1gnLFxuICAgICdbYXR0ci50cmFja1ldJzogJ3RyYWNrWScsXG4gICAgJ1thdHRyLmNvbXBhY3RdJzogJ2NvbXBhY3QnLFxuICAgICdbYXR0ci5hdXRvSGlkZV0nOiAnc2hvd24gPT09IFwiaG92ZXJcIicsXG4gICAgJ1thdHRyLmRpc2FibGVkXSc6ICdkaXNhYmxlZCdcbiAgfVxufSlcbmV4cG9ydCBjbGFzcyBOZ1Njcm9sbGJhciBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG5cbiAgLyoqIEhvcml6b250YWwgY3VzdG9tIHNjcm9sbGJhciAqL1xuICBASW5wdXQoKSB0cmFja1ggPSBmYWxzZTtcbiAgLyoqIFZlcnRpY2FsIGN1c3RvbSBTY3JvbGxiYXIgKi9cbiAgQElucHV0KCkgdHJhY2tZID0gdHJ1ZTtcbiAgLyoqIFNjcm9sbGJhciB2aXNpYmlsaXR5ICovXG4gIEBJbnB1dCgpIHNob3duOiAnaG92ZXInIHwgJ2Fsd2F5cycgfCAnbmF0aXZlJyA9ICduYXRpdmUnO1xuICAvKiogQXV0byB1cGRhdGUgc2Nyb2xsYmFycyBvbiBjb250ZW50IGNoYW5nZXMgKE11dGF0aW9uIE9ic2VydmVyKSAqL1xuICBASW5wdXQoKSBhdXRvVXBkYXRlID0gdHJ1ZTtcbiAgLyoqIFZpZXdwb3J0IGNsYXNzICovXG4gIEBJbnB1dCgpIHZpZXdDbGFzczogc3RyaW5nO1xuICAvKiogU2Nyb2xsYmFycyBjbGFzcyAqL1xuICBASW5wdXQoKSBiYXJDbGFzczogc3RyaW5nO1xuICAvKiogU2Nyb2xsYmFycyB0aHVtYm5haWxzIGNsYXNzICovXG4gIEBJbnB1dCgpIHRodW1iQ2xhc3M6IHN0cmluZztcbiAgLyoqIFRoZSBzbW9vdGggc2Nyb2xsIGR1cmF0aW9uIHdoZW4gYSBzY3JvbGxiYXIgaXMgY2xpY2tlZCAqL1xuICBASW5wdXQoKSBzY3JvbGxUb0R1cmF0aW9uID0gMzAwO1xuICAvKiogQ29tcGFjdCBtb2RlICovXG4gIEBJbnB1dCgpIGNvbXBhY3Q6IGJvb2xlYW47XG4gIC8qKiBJbnZlcnQgdmVydGljYWwgc2Nyb2xsYmFyIHBvc2l0aW9uLCBpZiBzZXQgdGhlIHNjcm9sbGJhciB3aWxsIGJlIG9uIHRoZSByaWdodCAqL1xuICBASW5wdXQoKSBpbnZlcnRZOiBib29sZWFuO1xuICAvKiogSW52ZXJ0IGhvcml6b250YWwgc2Nyb2xsYmFyIHBvc2l0aW9uLCBpZiBzZXQgdGhlIHNjcm9sbGJhciB3aWxsIGdvIHRoZSB0b3AgKi9cbiAgQElucHV0KCkgaW52ZXJ0WDogYm9vbGVhbjtcbiAgLyoqIERpc2FibGUgY3VzdG9tIHNjcm9sbGJhcnMgb24gc3BlY2lmaWMgYnJlYWtwb2ludHMgKi9cbiAgQElucHV0KCkgZGlzYWJsZU9uQnJlYWtwb2ludHMgPSBbXG4gICAgQnJlYWtwb2ludHMuSGFuZHNldExhbmRzY2FwZSxcbiAgICBCcmVha3BvaW50cy5IYW5kc2V0UG9ydHJhaXRcbiAgXTtcblxuICAvKiogRGlzYWJsZSBjdXN0b20gc2Nyb2xsYmFycyBhbmQgc3dpdGNoIGJhY2sgdG8gbmF0aXZlIHNjcm9sbGJhcnMgKi9cbiAgQElucHV0KCdkaXNhYmxlZCcpXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZGlzYWJsZWQ7XG4gIH1cblxuICBzZXQgZGlzYWJsZWQoZGlzYWJsZTogYm9vbGVhbikge1xuICAgIGRpc2FibGUgPyB0aGlzLmRpc2FibGUoKSA6IHRoaXMuZW5hYmxlKCk7XG4gIH1cblxuICBwcml2YXRlIF9kaXNhYmxlZCA9IGZhbHNlO1xuXG4gIC8qKiBTY3JvbGxiYXJzIEVsZW1lbnRSZWYgKi9cbiAgQFZpZXdDaGlsZCgneScsIHsgcmVhZDogRWxlbWVudFJlZiwgc3RhdGljOiBmYWxzZSB9KSB2ZXJ0aWNhbFNjcm9sbGJhcjogRWxlbWVudFJlZjtcbiAgQFZpZXdDaGlsZCgneCcsIHsgcmVhZDogRWxlbWVudFJlZiwgc3RhdGljOiBmYWxzZSB9KSBob3Jpem9udGFsU2Nyb2xsYmFyOiBFbGVtZW50UmVmO1xuXG4gIC8qKiBEZWZhdWx0IHZpZXdwb3J0IGFuZCBzbW9vdGhTY3JvbGwgcmVmZXJlbmNlcyAqL1xuICBAVmlld0NoaWxkKENka1Njcm9sbGFibGUsIHsgc3RhdGljOiB0cnVlIH0pIHNjcm9sbFZpZXdwb3J0OiBDZGtTY3JvbGxhYmxlO1xuICBAVmlld0NoaWxkKFNtb290aFNjcm9sbCwgeyBzdGF0aWM6IHRydWUgfSkgdmlld1Ntb290aFNjcm9sbDogU21vb3RoU2Nyb2xsO1xuXG4gIC8qKiBWaXJ0dWFsIHZpZXdwb3J0IGFuZCBzbW9vdGhTY3JvbGwgcmVmZXJlbmNlcyAqL1xuICBAQ29udGVudENoaWxkKE5nU2Nyb2xsYmFyVmlldywgeyBzdGF0aWM6IHRydWUgfSkgY3VzdG9tVmlld1BvcnQ6IE5nU2Nyb2xsYmFyVmlldztcblxuICAvKiogVmlld3BvcnQgRWxlbWVudCAqL1xuICBnZXQgdmlldygpOiBIVE1MRWxlbWVudCB7XG4gICAgcmV0dXJuIHRoaXMuY3VzdG9tVmlld1BvcnRcbiAgICAgID8gdGhpcy5jdXN0b21WaWV3UG9ydC52aXJ0dWFsU2Nyb2xsVmlld3BvcnQuZ2V0RWxlbWVudFJlZigpLm5hdGl2ZUVsZW1lbnRcbiAgICAgIDogdGhpcy5zY3JvbGxWaWV3cG9ydC5nZXRFbGVtZW50UmVmKCkubmF0aXZlRWxlbWVudDtcbiAgfVxuXG4gIGdldCBzY3JvbGxhYmxlKCk6IENka1Njcm9sbGFibGUgfCBDZGtWaXJ0dWFsU2Nyb2xsVmlld3BvcnQge1xuICAgIHJldHVybiB0aGlzLmN1c3RvbVZpZXdQb3J0XG4gICAgICA/IHRoaXMuY3VzdG9tVmlld1BvcnQudmlydHVhbFNjcm9sbFZpZXdwb3J0XG4gICAgICA6IHRoaXMuc2Nyb2xsVmlld3BvcnQ7XG4gIH1cblxuICBnZXQgc21vb3RoU2Nyb2xsKCk6IFNtb290aFNjcm9sbCB7XG4gICAgcmV0dXJuIHRoaXMuY3VzdG9tVmlld1BvcnRcbiAgICAgID8gdGhpcy5jdXN0b21WaWV3UG9ydC5zbW9vdGhTY3JvbGxcbiAgICAgIDogdGhpcy52aWV3U21vb3RoU2Nyb2xsO1xuICB9XG5cbiAgLyoqIFVuc3Vic2NyaWJlIGNvbXBvbmVudCBvYnNlcnZhYmxlcyBvbiBkZXN0cm95ICovXG4gIHByaXZhdGUgX3Vuc3Vic2NyaWJlJCA9IG5ldyBTdWJqZWN0KCk7XG4gIC8qKiBPYnNlcnZlIGNvbnRlbnQgY2hhbmdlcyAqL1xuICBwcml2YXRlIF9vYnNlcnZlcjogTXV0YXRpb25PYnNlcnZlcjtcblxuICAvKiogU3RlYW0gdGhhdCBlbWl0cyB3aGVuIHNjcm9sbGJhciB0aHVtYm5haWwgbmVlZHMgdG8gdXBkYXRlIChmb3IgaW50ZXJuYWwgdXNlcykgKi9cbiAgcHJpdmF0ZSBfdXBkYXRlT2JzZXJ2ZXIgPSBuZXcgU3ViamVjdCgpO1xuICB1cGRhdGVPYnNlcnZlciA9IHRoaXMuX3VwZGF0ZU9ic2VydmVyLmFzT2JzZXJ2YWJsZSgpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgX2NoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfYnJlYWtwb2ludE9ic2VydmVyOiBCcmVha3BvaW50T2JzZXJ2ZXIsXG4gICAgICAgICAgICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHByaXZhdGUgX3BsYXRmb3JtOiBPYmplY3QpIHtcbiAgfVxuXG4gIHNob3dTY3JvbGxiYXJZKCkge1xuICAgIHJldHVybiB0aGlzLnNob3duID09PSAnYWx3YXlzJyB8fCB0aGlzLnZpZXcuc2Nyb2xsSGVpZ2h0ID4gdGhpcy52aWV3LmNsaWVudEhlaWdodDtcbiAgfVxuXG4gIHNob3dTY3JvbGxiYXJYKCkge1xuICAgIHJldHVybiB0aGlzLnNob3duID09PSAnYWx3YXlzJyB8fCB0aGlzLnZpZXcuc2Nyb2xsV2lkdGggPiB0aGlzLnZpZXcuY2xpZW50V2lkdGg7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgLy8gQXZvaWQgJ2V4cHJlc3Npb24gaGFzIGNoYW5nZWQgYWZ0ZXIgaXQgd2FzIGNoZWNrZWQnIGVycm9yIHdoZW4gJ2Rpc2FibGVPbkJyZWFrcG9pbnRzJyBpcyBzZXQgdG8gZmFsc2VcbiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcbiAgICAgIGlmICghdGhpcy5kaXNhYmxlZCkge1xuICAgICAgICBpZiAodGhpcy5kaXNhYmxlT25CcmVha3BvaW50cykge1xuICAgICAgICAgIC8vIEVuYWJsZS9EaXNhYmxlIGN1c3RvbSBzY3JvbGxiYXIgb24gYnJlYWtwb2ludHMgKFVzZWQgdG8gZGlzYWJsZSBzY3JvbGxiYXJzIG9uIG1vYmlsZSBwaG9uZXMpXG4gICAgICAgICAgdGhpcy5fYnJlYWtwb2ludE9ic2VydmVyLm9ic2VydmUodGhpcy5kaXNhYmxlT25CcmVha3BvaW50cykucGlwZShcbiAgICAgICAgICAgIHRhcCgocmVzdWx0OiBCcmVha3BvaW50U3RhdGUpID0+IHJlc3VsdC5tYXRjaGVzID8gdGhpcy5kaXNhYmxlKCkgOiB0aGlzLmVuYWJsZSgpKSxcbiAgICAgICAgICAgIHRha2VVbnRpbCh0aGlzLl91bnN1YnNjcmliZSQpXG4gICAgICAgICAgKS5zdWJzY3JpYmUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmVuYWJsZSgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFVwZGF0ZSBzdGF0ZSBvbiBjb250ZW50IGNoYW5nZXNcbiAgICAgIHRoaXMudXBkYXRlT2JzZXJ2ZXIucGlwZShcbiAgICAgICAgdGhyb3R0bGVUaW1lKDIwMCksXG4gICAgICAgIHRhcCgoKSA9PiB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKSksXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLl91bnN1YnNjcmliZSQpXG4gICAgICApLnN1YnNjcmliZSgpO1xuXG5cbiAgICAgIGlmIChpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLl9wbGF0Zm9ybSkpIHtcbiAgICAgICAgLy8gVXBkYXRlIG9uIHdpbmRvdyByZXNpemVcbiAgICAgICAgZnJvbUV2ZW50KHdpbmRvdywgJ3Jlc2l6ZScpLnBpcGUoXG4gICAgICAgICAgdGhyb3R0bGVUaW1lKDIwMCksXG4gICAgICAgICAgdGFwKCgpID0+IHRoaXMudXBkYXRlKCkpLFxuICAgICAgICAgIHRha2VVbnRpbCh0aGlzLl91bnN1YnNjcmliZSQpXG4gICAgICAgICkuc3Vic2NyaWJlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLl91bnN1YnNjcmliZSQubmV4dCgpO1xuICAgIHRoaXMuX3Vuc3Vic2NyaWJlJC5jb21wbGV0ZSgpO1xuICAgIGlmICh0aGlzLl9vYnNlcnZlcikge1xuICAgICAgdGhpcy5fb2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgc2Nyb2xsYmFyIHRodW1ibmFpbCBwb3NpdGlvblxuICAgKi9cbiAgdXBkYXRlKCkge1xuICAgIGlmICghdGhpcy5kaXNhYmxlZCkge1xuICAgICAgdGhpcy5fdXBkYXRlT2JzZXJ2ZXIubmV4dCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGUgY3VzdG9tIHNjcm9sbGJhclxuICAgKi9cbiAgZW5hYmxlKCkge1xuICAgIGlmICh0aGlzLnZpZXcpIHtcbiAgICAgIHRoaXMuX2Rpc2FibGVkID0gZmFsc2U7XG4gICAgICAvLyBVcGRhdGUgdmlld1xuICAgICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG5cbiAgICAgIGlmICghdGhpcy5jdXN0b21WaWV3UG9ydCAmJiB0aGlzLmF1dG9VcGRhdGUgJiYgaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5fcGxhdGZvcm0pKSB7XG4gICAgICAgIC8vIE9ic2VydmUgY29udGVudCBjaGFuZ2VzXG4gICAgICAgIHRoaXMuX29ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKCkgPT4gdGhpcy51cGRhdGUoKSk7XG4gICAgICAgIHRoaXMuX29ic2VydmVyLm9ic2VydmUodGhpcy52aWV3LCB7c3VidHJlZTogdHJ1ZSwgY2hpbGRMaXN0OiB0cnVlLCBjaGFyYWN0ZXJEYXRhOiB0cnVlfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERpc2FibGUgY3VzdG9tIHNjcm9sbGJhclxuICAgKi9cbiAgZGlzYWJsZSgpIHtcbiAgICB0aGlzLl9kaXNhYmxlZCA9IHRydWU7XG4gICAgaWYgKHRoaXMuX29ic2VydmVyKSB7XG4gICAgICB0aGlzLl9vYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgfVxuICB9XG5cbiAgc2Nyb2xsVG8ob3B0aW9uczogU2Nyb2xsVG9PcHRpb25zKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuc21vb3RoU2Nyb2xsLnNjcm9sbFRvKG9wdGlvbnMpO1xuICB9XG5cbiAgc2Nyb2xsVG9FbGVtZW50KHNlbGVjdG9yOiBzdHJpbmcsIG9mZnNldCA9IDAsIGR1cmF0aW9uPzogbnVtYmVyLCBlYXNlRnVuYz86IFNtb290aFNjcm9sbEVhc2VGdW5jKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuc21vb3RoU2Nyb2xsLnNjcm9sbFRvRWxlbWVudChzZWxlY3Rvciwgb2Zmc2V0LCBkdXJhdGlvbiwgZWFzZUZ1bmMpO1xuICB9XG5cbiAgc2Nyb2xsWFRvKHRvOiBudW1iZXIsIGR1cmF0aW9uPzogbnVtYmVyLCBlYXNlRnVuYz86IFNtb290aFNjcm9sbEVhc2VGdW5jKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuc21vb3RoU2Nyb2xsLnNjcm9sbFhUbyh0bywgZHVyYXRpb24sIGVhc2VGdW5jKTtcbiAgfVxuXG4gIHNjcm9sbFlUbyh0bzogbnVtYmVyLCBkdXJhdGlvbj86IG51bWJlciwgZWFzZUZ1bmM/OiBTbW9vdGhTY3JvbGxFYXNlRnVuYyk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnNtb290aFNjcm9sbC5zY3JvbGxZVG8odG8sIGR1cmF0aW9uLCBlYXNlRnVuYyk7XG4gIH1cblxuICBzY3JvbGxUb1RvcChkdXJhdGlvbj86IG51bWJlciwgZWFzZUZ1bmM/OiBTbW9vdGhTY3JvbGxFYXNlRnVuYyk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnNtb290aFNjcm9sbC5zY3JvbGxUb1RvcChkdXJhdGlvbiwgZWFzZUZ1bmMpO1xuICB9XG5cbiAgc2Nyb2xsVG9Cb3R0b20oZHVyYXRpb24/OiBudW1iZXIsIGVhc2VGdW5jPzogU21vb3RoU2Nyb2xsRWFzZUZ1bmMpOiBPYnNlcnZhYmxlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5zbW9vdGhTY3JvbGwuc2Nyb2xsVG9Cb3R0b20oZHVyYXRpb24sIGVhc2VGdW5jKTtcbiAgfVxuXG4gIHNjcm9sbFRvUmlnaHQoZHVyYXRpb24/OiBudW1iZXIsIGVhc2VGdW5jPzogU21vb3RoU2Nyb2xsRWFzZUZ1bmMpOiBPYnNlcnZhYmxlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5zbW9vdGhTY3JvbGwuc2Nyb2xsVG9SaWdodChkdXJhdGlvbiwgZWFzZUZ1bmMpO1xuICB9XG5cbiAgc2Nyb2xsVG9MZWZ0KGR1cmF0aW9uPzogbnVtYmVyLCBlYXNlRnVuYz86IFNtb290aFNjcm9sbEVhc2VGdW5jKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuc21vb3RoU2Nyb2xsLnNjcm9sbFRvTGVmdChkdXJhdGlvbiwgZWFzZUZ1bmMpO1xuICB9XG59XG4iXX0=