import { Directive, Optional, Input, Output } from '@angular/core'; import { Observable, Subject, Subscription, filter, map, tap, distinctUntilChanged } from 'rxjs'; import * as i0 from "@angular/core"; import * as i1 from "ngx-scrollbar"; import * as i2 from "@angular/cdk/bidi"; class ReachedFunctions { static reachedTop(offset, e) { return ReachedFunctions.reached(-e.target.scrollTop, 0, offset); } static reachedBottom(offset, e) { return ReachedFunctions.reached(e.target.scrollTop + e.target.clientHeight, e.target.scrollHeight, offset); } static reachedStart(offset, e, direction, rtlScrollAxisType) { if (direction === 'rtl') { if (rtlScrollAxisType === 1 /* RtlScrollAxisType.NEGATED */) { return ReachedFunctions.reached(e.target.scrollLeft, 0, offset); } if (rtlScrollAxisType === 2 /* RtlScrollAxisType.INVERTED */) { return ReachedFunctions.reached(-e.target.scrollLeft, 0, offset); } return ReachedFunctions.reached(e.target.scrollLeft + e.target.clientWidth, e.target.scrollWidth, offset); } return ReachedFunctions.reached(-e.target.scrollLeft, 0, offset); } static reachedEnd(offset, e, direction, rtlScrollAxisType) { if (direction === 'rtl') { if (rtlScrollAxisType === 1 /* RtlScrollAxisType.NEGATED */) { return ReachedFunctions.reached(-(e.target.scrollLeft - e.target.clientWidth), e.target.scrollWidth, offset); } if (rtlScrollAxisType === 2 /* RtlScrollAxisType.INVERTED */) { return ReachedFunctions.reached(-(e.target.scrollLeft + e.target.clientWidth), e.target.scrollWidth, offset); } return ReachedFunctions.reached(-e.target.scrollLeft, 0, offset); } return ReachedFunctions.reached(e.target.scrollLeft + e.target.clientWidth, e.target.scrollWidth, offset); } static reached(currPosition, targetPosition, offset) { return currPosition >= targetPosition - offset; } } class ScrollReached { constructor(scrollbar, zone) { this.scrollbar = scrollbar; this.zone = zone; /** offset: Reached offset value in px */ this.offset = 0; /** * Stream that emits scroll event when `NgScrollbar.scrolled` is initialized. * * **NOTE:** This subject is used to hold the place of `NgScrollbar.scrolled` when it's not initialized yet */ this.scrollEvent = new Subject(); /** subscription: Scrolled event subscription, used to unsubscribe from the event on destroy */ this.subscription = Subscription.EMPTY; /** A stream used to assign the reached output */ this.reachedEvent = new Observable((subscriber) => this.scrollReached().subscribe(_ => Promise.resolve().then(() => this.zone.run(() => subscriber.next(_))))); if (!scrollbar) { console.warn('[NgScrollbarReached Directive]: Host element must be an NgScrollbar component.'); } } ngOnDestroy() { this.subscription.unsubscribe(); } scrollReached() { // current event let currEvent; return this.scrollEvent.pipe(tap((e) => currEvent = e), // Check if scroll has reached map((e) => this.reached(this.offset, e)), // Distinct until reached value has changed distinctUntilChanged(), // Emit only if reached is true filter((reached) => reached), // Return scroll event map(() => currEvent)); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: ScrollReached, deps: [{ token: i1.NgScrollbar, optional: true }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.5", type: ScrollReached, inputs: { offset: ["reachedOffset", "offset"] }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: ScrollReached, decorators: [{ type: Directive }], ctorParameters: function () { return [{ type: i1.NgScrollbar, decorators: [{ type: Optional }] }, { type: i0.NgZone }]; }, propDecorators: { offset: [{ type: Input, args: ['reachedOffset'] }] } }); class VerticalScrollReached extends ScrollReached { constructor(scrollbar, zone) { super(scrollbar, zone); this.scrollbar = scrollbar; this.zone = zone; } ngOnInit() { this.zone.runOutsideAngular(() => { // Fix the viewport size in case the rendered size is not rounded const fixedSize = Math.round(this.scrollbar.viewport.nativeElement.getBoundingClientRect().height); this.scrollbar.viewport.nativeElement.style.height = `${fixedSize}px`; this.subscription = this.scrollbar.verticalScrolled.subscribe(this.scrollEvent); }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: VerticalScrollReached, deps: [{ token: i1.NgScrollbar, optional: true }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.5", type: VerticalScrollReached, usesInheritance: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: VerticalScrollReached, decorators: [{ type: Directive }], ctorParameters: function () { return [{ type: i1.NgScrollbar, decorators: [{ type: Optional }] }, { type: i0.NgZone }]; } }); class HorizontalScrollReached extends ScrollReached { constructor(scrollbar, zone) { super(scrollbar, zone); this.scrollbar = scrollbar; this.zone = zone; } ngOnInit() { this.zone.runOutsideAngular(() => { // Fix the viewport size in case the rendered size is not rounded const fixedSize = Math.round(this.scrollbar.viewport.nativeElement.getBoundingClientRect().width); this.scrollbar.viewport.nativeElement.style.width = `${fixedSize}px`; this.subscription = this.scrollbar.horizontalScrolled.subscribe(this.scrollEvent); }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: HorizontalScrollReached, deps: [{ token: i1.NgScrollbar, optional: true }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.5", type: HorizontalScrollReached, usesInheritance: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: HorizontalScrollReached, decorators: [{ type: Directive }], ctorParameters: function () { return [{ type: i1.NgScrollbar, decorators: [{ type: Optional }] }, { type: i0.NgZone }]; } }); export class NgScrollbarReachedTop extends VerticalScrollReached { constructor(scrollbar, zone) { super(scrollbar, zone); this.scrollbar = scrollbar; this.zone = zone; /** Stream that emits when scroll has reached the top */ this.reachedTop = this.reachedEvent; } ngOnInit() { super.ngOnInit(); } /** * Check if scroll has reached the top (vertically) * @param offset Scroll offset * @param e Scroll event */ reached(offset, e) { return ReachedFunctions.reachedTop(offset, e); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: NgScrollbarReachedTop, deps: [{ token: i1.NgScrollbar, optional: true }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.5", type: NgScrollbarReachedTop, isStandalone: true, selector: "[reachedTop], [reached-top]", outputs: { reachedTop: "reachedTop" }, usesInheritance: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: NgScrollbarReachedTop, decorators: [{ type: Directive, args: [{ selector: '[reachedTop], [reached-top]', standalone: true, }] }], ctorParameters: function () { return [{ type: i1.NgScrollbar, decorators: [{ type: Optional }] }, { type: i0.NgZone }]; }, propDecorators: { reachedTop: [{ type: Output }] } }); export class NgScrollbarReachedBottom extends VerticalScrollReached { constructor(scrollbar, zone) { super(scrollbar, zone); this.scrollbar = scrollbar; this.zone = zone; /** Stream that emits when scroll has reached the bottom */ this.reachedBottom = this.reachedEvent; } ngOnInit() { super.ngOnInit(); } /** * Check if scroll has reached the bottom (vertically) * @param offset Scroll offset * @param e Scroll event */ reached(offset, e) { return ReachedFunctions.reachedBottom(offset, e); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: NgScrollbarReachedBottom, deps: [{ token: i1.NgScrollbar, optional: true }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.5", type: NgScrollbarReachedBottom, isStandalone: true, selector: "[reachedBottom], [reached-bottom]", outputs: { reachedBottom: "reachedBottom" }, usesInheritance: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: NgScrollbarReachedBottom, decorators: [{ type: Directive, args: [{ selector: '[reachedBottom], [reached-bottom]', standalone: true, }] }], ctorParameters: function () { return [{ type: i1.NgScrollbar, decorators: [{ type: Optional }] }, { type: i0.NgZone }]; }, propDecorators: { reachedBottom: [{ type: Output }] } }); export class NgScrollbarReachedStart extends HorizontalScrollReached { constructor(scrollbar, zone, dir) { super(scrollbar, zone); this.scrollbar = scrollbar; this.zone = zone; this.dir = dir; /** Stream that emits when scroll has reached the start */ this.reachedStart = this.reachedEvent; } ngOnInit() { super.ngOnInit(); } /** * Check if scroll has reached the start (horizontally) * @param offset Scroll offset * @param e Scroll event */ reached(offset, e) { return ReachedFunctions.reachedStart(offset, e, this.dir.value, this.scrollbar.manager.rtlScrollAxisType); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: NgScrollbarReachedStart, deps: [{ token: i1.NgScrollbar, optional: true }, { token: i0.NgZone }, { token: i2.Directionality }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.5", type: NgScrollbarReachedStart, isStandalone: true, selector: "[reachedStart], [reached-start]", outputs: { reachedStart: "reachedStart" }, usesInheritance: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: NgScrollbarReachedStart, decorators: [{ type: Directive, args: [{ selector: '[reachedStart], [reached-start]', standalone: true, }] }], ctorParameters: function () { return [{ type: i1.NgScrollbar, decorators: [{ type: Optional }] }, { type: i0.NgZone }, { type: i2.Directionality }]; }, propDecorators: { reachedStart: [{ type: Output }] } }); export class NgScrollbarReachedEnd extends HorizontalScrollReached { constructor(scrollbar, zone, dir) { super(scrollbar, zone); this.scrollbar = scrollbar; this.zone = zone; this.dir = dir; /** Stream that emits when scroll has reached the end */ this.reachedEnd = this.reachedEvent; } ngOnInit() { super.ngOnInit(); } /** * Check if scroll has reached the end (horizontally) * @param offset Scroll offset * @param e Scroll event */ reached(offset, e) { return ReachedFunctions.reachedEnd(offset, e, this.dir.value, this.scrollbar.manager.rtlScrollAxisType); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: NgScrollbarReachedEnd, deps: [{ token: i1.NgScrollbar, optional: true }, { token: i0.NgZone }, { token: i2.Directionality }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.5", type: NgScrollbarReachedEnd, isStandalone: true, selector: "[reachedEnd], [reached-end]", outputs: { reachedEnd: "reachedEnd" }, usesInheritance: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: NgScrollbarReachedEnd, decorators: [{ type: Directive, args: [{ selector: '[reachedEnd], [reached-end]', standalone: true, }] }], ctorParameters: function () { return [{ type: i1.NgScrollbar, decorators: [{ type: Optional }] }, { type: i0.NgZone }, { type: i2.Directionality }]; }, propDecorators: { reachedEnd: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctc2Nyb2xsYmFyLXJlYWNoZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc2Nyb2xsYmFyL3JlYWNoZWQtZXZlbnQvc3JjL25nLXNjcm9sbGJhci1yZWFjaGVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQTZCLE1BQU0sZUFBZSxDQUFDO0FBSTlGLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBYyxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7OztBQUs3RyxNQUFNLGdCQUFnQjtJQUNwQixNQUFNLENBQUMsVUFBVSxDQUFDLE1BQWMsRUFBRSxDQUFlO1FBQy9DLE9BQU8sZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFFRCxNQUFNLENBQUMsYUFBYSxDQUFDLE1BQWMsRUFBRSxDQUFlO1FBQ2xELE9BQU8sZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzdHLENBQUM7SUFFRCxNQUFNLENBQUMsWUFBWSxDQUFDLE1BQWMsRUFBRSxDQUFlLEVBQUUsU0FBd0IsRUFBRSxpQkFBb0M7UUFDakgsSUFBSSxTQUFTLEtBQUssS0FBSyxFQUFFO1lBQ3ZCLElBQUksaUJBQWlCLHNDQUE4QixFQUFFO2dCQUNuRCxPQUFPLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDLEVB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QUFVLEdBQW1CO1FBQzNHLEtBQUssQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFEUyxjQUFTLEdBQVQsU0FBUyxDQUFhO1FBQVksU0FBSSxHQUFKLElBQUksQ0FBUTtRQUFVLFFBQUcsR0FBSCxHQUFHLENBQWdCO1FBSDdHLHdEQUF3RDtRQUM5QyxlQUFVLEdBQTZCLElBQUksQ0FBQyxZQUFZLENBQUM7SUFJbkUsQ0FBQztJQUVELFFBQVE7UUFDTixLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVEOzs7O09BSUc7SUFDTyxPQUFPLENBQUMsTUFBYyxFQUFFLENBQWU7UUFDL0MsT0FBTyxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQzFHLENBQUM7OEdBcEJVLHFCQUFxQjtrR0FBckIscUJBQXFCOzsyRkFBckIscUJBQXFCO2tCQUpqQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSw2QkFBNkI7b0JBQ3ZDLFVBQVUsRUFBRSxJQUFJO2lCQUNqQjs7MEJBTWMsUUFBUTs4RkFGWCxVQUFVO3NCQUFuQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGlyZWN0aXZlLCBPcHRpb25hbCwgSW5wdXQsIE91dHB1dCwgT25Jbml0LCBPbkRlc3Ryb3ksIE5nWm9uZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBEaXJlY3Rpb25hbGl0eSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9iaWRpJztcclxuaW1wb3J0IHsgUnRsU2Nyb2xsQXhpc1R5cGUgfSBmcm9tICdAYW5ndWxhci9jZGsvcGxhdGZvcm0nO1xyXG5pbXBvcnQgeyBOZ1Njcm9sbGJhciB9IGZyb20gJ25neC1zY3JvbGxiYXInO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0LCBTdWJzY3JpcHRpb24sIFN1YnNjcmliZXIsIGZpbHRlciwgbWFwLCB0YXAsIGRpc3RpbmN0VW50aWxDaGFuZ2VkIH0gZnJvbSAncnhqcyc7XHJcblxyXG4vLyBGaXggdGFyZ2V0IHR5cGUgb24gRWxlbWVudEV2ZW50XHJcbnR5cGUgRWxlbWVudEV2ZW50ID0gRXZlbnQgJiB7IHRhcmdldDogRWxlbWVudCB9O1xyXG5cclxuY2xhc3MgUmVhY2hlZEZ1bmN0aW9ucyB7XHJcbiAgc3RhdGljIHJlYWNoZWRUb3Aob2Zmc2V0OiBudW1iZXIsIGU6IEVsZW1lbnRFdmVudCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIFJlYWNoZWRGdW5jdGlvbnMucmVhY2hlZCgtZS50YXJnZXQuc2Nyb2xsVG9wLCAwLCBvZmZzZXQpO1xyXG4gIH1cclxuXHJcbiAgc3RhdGljIHJlYWNoZWRCb3R0b20ob2Zmc2V0OiBudW1iZXIsIGU6IEVsZW1lbnRFdmVudCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIFJlYWNoZWRGdW5jdGlvbnMucmVhY2hlZChlLnRhcmdldC5zY3JvbGxUb3AgKyBlLnRhcmdldC5jbGllbnRIZWlnaHQsIGUudGFyZ2V0LnNjcm9sbEhlaWdodCwgb2Zmc2V0KTtcclxuICB9XHJcblxyXG4gIHN0YXRpYyByZWFjaGVkU3RhcnQob2Zmc2V0OiBudW1iZXIsIGU6IEVsZW1lbnRFdmVudCwgZGlyZWN0aW9uOiAnbHRyJyB8ICdydGwnLCBydGxTY3JvbGxBeGlzVHlwZTogUnRsU2Nyb2xsQXhpc1R5cGUpOiBib29sZWFuIHtcclxuICAgIGlmIChkaXJlY3Rpb24gPT09ICdydGwnKSB7XHJcbiAgICAgIGlmIChydGxTY3JvbGxBeGlzVHlwZSA9PT0gUnRsU2Nyb2xsQXhpc1R5cGUuTkVHQVRFRCkge1xyXG4gICAgICAgIHJldHVybiBSZWFjaGVkRnVuY3Rpb25zLnJlYWNoZWQoZS50YXJnZXQuc2Nyb2xsTGVmdCwgMCwgb2Zmc2V0KTtcclxuICAgICAgfVxyXG4gICAgICBpZiAocnRsU2Nyb2xsQXhpc1R5cGUgPT09IFJ0bFNjcm9sbEF4aXNUeXBlLklOVkVSVEVEKSB7XHJcbiAgICAgICAgcmV0dXJuIFJlYWNoZWRGdW5jdGlvbnMucmVhY2hlZCgtZS50YXJnZXQuc2Nyb2xsTGVmdCwgMCwgb2Zmc2V0KTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gUmVhY2hlZEZ1bmN0aW9ucy5yZWFjaGVkKGUudGFyZ2V0LnNjcm9sbExlZnQgKyBlLnRhcmdldC5jbGllbnRXaWR0aCwgZS50YXJnZXQuc2Nyb2xsV2lkdGgsIG9mZnNldCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gUmVhY2hlZEZ1bmN0aW9ucy5yZWFjaGVkKC1lLnRhcmdldC5zY3JvbGxMZWZ0LCAwLCBvZmZzZXQpO1xyXG4gIH1cclxuXHJcbiAgc3RhdGljIHJlYWNoZWRFbmQob2Zmc2V0OiBudW1iZXIsIGU6IEVsZW1lbnRFdmVudCwgZGlyZWN0aW9uOiAnbHRyJyB8ICdydGwnLCBydGxTY3JvbGxBeGlzVHlwZTogUnRsU2Nyb2xsQXhpc1R5cGUpOiBib29sZWFuIHtcclxuICAgIGlmIChkaXJlY3Rpb24gPT09ICdydGwnKSB7XHJcbiAgICAgIGlmIChydGxTY3JvbGxBeGlzVHlwZSA9PT0gUnRsU2Nyb2xsQXhpc1R5cGUuTkVHQVRFRCkge1xyXG4gICAgICAgIHJldHVybiBSZWFjaGVkRnVuY3Rpb25zLnJlYWNoZWQoLShlLnRhcmdldC5zY3JvbGxMZWZ0IC0gZS50YXJnZXQuY2xpZW50V2lkdGgpLCBlLnRhcmdldC5zY3JvbGxXaWR0aCwgb2Zmc2V0KTtcclxuICAgICAgfVxyXG4gICAgICBpZiAocnRsU2Nyb2xsQXhpc1R5cGUgPT09IFJ0bFNjcm9sbEF4aXNUeXBlLklOVkVSVEVEKSB7XHJcbiAgICAgICAgcmV0dXJuIFJlYWNoZWRGdW5jdGlvbnMucmVhY2hlZCgtKGUudGFyZ2V0LnNjcm9sbExlZnQgKyBlLnRhcmdldC5jbGllbnRXaWR0aCksIGUudGFyZ2V0LnNjcm9sbFdpZHRoLCBvZmZzZXQpO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBSZWFjaGVkRnVuY3Rpb25zLnJlYWNoZWQoLWUudGFyZ2V0LnNjcm9sbExlZnQsIDAsIG9mZnNldCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gUmVhY2hlZEZ1bmN0aW9ucy5yZWFjaGVkKGUudGFyZ2V0LnNjcm9sbExlZnQgKyBlLnRhcmdldC5jbGllbnRXaWR0aCwgZS50YXJnZXQuc2Nyb2xsV2lkdGgsIG9mZnNldCk7XHJcbiAgfVxyXG5cclxuICBzdGF0aWMgcmVhY2hlZChjdXJyUG9zaXRpb246IG51bWJlciwgdGFyZ2V0UG9zaXRpb246IG51bWJlciwgb2Zmc2V0OiBudW1iZXIpOiBib29sZWFuIHtcclxuICAgIHJldHVybiBjdXJyUG9zaXRpb24gPj0gdGFyZ2V0UG9zaXRpb24gLSBvZmZzZXQ7XHJcbiAgfVxyXG59XHJcblxyXG5ARGlyZWN0aXZlKClcclxuYWJzdHJhY3QgY2xhc3MgU2Nyb2xsUmVhY2hlZCBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XHJcblxyXG4gIC8qKiBvZmZzZXQ6IFJlYWNoZWQgb2Zmc2V0IHZhbHVlIGluIHB4ICovXHJcbiAgQElucHV0KCdyZWFjaGVkT2Zmc2V0Jykgb2Zmc2V0OiBudW1iZXIgPSAwO1xyXG5cclxuICAvKipcclxuICAgKiBTdHJlYW0gdGhhdCBlbWl0cyBzY3JvbGwgZXZlbnQgd2hlbiBgTmdTY3JvbGxiYXIuc2Nyb2xsZWRgIGlzIGluaXRpYWxpemVkLlxyXG4gICAqXHJcbiAgICogKipOT1RFOioqIFRoaXMgc3ViamVjdCBpcyB1c2VkIHRvIGhvbGQgdGhlIHBsYWNlIG9mIGBOZ1Njcm9sbGJhci5zY3JvbGxlZGAgd2hlbiBpdCdzIG5vdCBpbml0aWFsaXplZCB5ZXRcclxuICAgKi9cclxuICBwcm90ZWN0ZWQgc2Nyb2xsRXZlbnQgPSBuZXcgU3ViamVjdDxFbGVtZW50RXZlbnQ+KCk7XHJcblxyXG4gIC8qKiBzdWJzY3JpcHRpb246IFNjcm9sbGVkIGV2ZW50IHN1YnNjcmlwdGlvbiwgdXNlZCB0byB1bnN1YnNjcmliZSBmcm9tIHRoZSBldmVudCBvbiBkZXN0cm95ICovXHJcbiAgcHJvdGVjdGVkIHN1YnNjcmlwdGlvbiA9IFN1YnNjcmlwdGlvbi5FTVBUWTtcclxuXHJcbiAgLyoqIEEgc3RyZWFtIHVzZWQgdG8gYXNzaWduIHRoZSByZWFjaGVkIG91dHB1dCAqL1xyXG4gIHByb3RlY3RlZCByZWFjaGVkRXZlbnQgPSBuZXcgT2JzZXJ2YWJsZSgoc3Vic2NyaWJlcjogU3Vic2NyaWJlcjxFbGVtZW50RXZlbnQ+KSA9PlxyXG4gICAgdGhpcy5zY3JvbGxSZWFjaGVkKCkuc3Vic2NyaWJlKF8gPT5cclxuICAgICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB0aGlzLnpvbmUucnVuKCgpID0+IHN1YnNjcmliZXIubmV4dChfKSkpKSk7XHJcblxyXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihAT3B0aW9uYWwoKSBwcm90ZWN0ZWQgc2Nyb2xsYmFyOiBOZ1Njcm9sbGJhciwgcHJvdGVjdGVkIHpvbmU6IE5nWm9uZSkge1xyXG4gICAgaWYgKCFzY3JvbGxiYXIpIHtcclxuICAgICAgY29uc29sZS53YXJuKCdbTmdTY3JvbGxiYXJSZWFjaGVkIERpcmVjdGl2ZV06IEhvc3QgZWxlbWVudCBtdXN0IGJlIGFuIE5nU2Nyb2xsYmFyIGNvbXBvbmVudC4nKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCkge1xyXG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICB9XHJcblxyXG4gIHByb3RlY3RlZCBzY3JvbGxSZWFjaGVkKCk6IE9ic2VydmFibGU8RWxlbWVudEV2ZW50PiB7XHJcbiAgICAvLyBjdXJyZW50IGV2ZW50XHJcbiAgICBsZXQgY3VyckV2ZW50OiBFbGVtZW50RXZlbnQ7XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuc2Nyb2xsRXZlbnQucGlwZShcclxuICAgICAgdGFwKChlOiBFbGVtZW50RXZlbnQpID0+IGN1cnJFdmVudCA9IGUpLFxyXG4gICAgICAvLyBDaGVjayBpZiBzY3JvbGwgaGFzIHJlYWNoZWRcclxuICAgICAgbWFwKChlOiBFbGVtZW50RXZlbnQpID0+IHRoaXMucmVhY2hlZCh0aGlzLm9mZnNldCwgZSkpLFxyXG4gICAgICAvLyBEaXN0aW5jdCB1bnRpbCByZWFjaGVkIHZhbHVlIGhhcyBjaGFuZ2VkXHJcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXHJcbiAgICAgIC8vIEVtaXQgb25seSBpZiByZWFjaGVkIGlzIHRydWVcclxuICAgICAgZmlsdGVyKChyZWFjaGVkOiBib29sZWFuKSA9PiByZWFjaGVkKSxcclxuICAgICAgLy8gUmV0dXJuIHNjcm9sbCBldmVudFxyXG4gICAgICBtYXAoKCkgPT4gY3VyckV2ZW50KVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHByb3RlY3RlZCBhYnN0cmFjdCByZWFjaGVkKG9mZnNldDogbnVtYmVyLCBlPzogRWxlbWVudEV2ZW50KTogYm9vbGVhbjtcclxufVxyXG5cclxuQERpcmVjdGl2ZSgpXHJcbmFic3RyYWN0IGNsYXNzIFZlcnRpY2FsU2Nyb2xsUmVhY2hlZCBleHRlbmRzIFNjcm9sbFJlYWNoZWQgaW1wbGVtZW50cyBPbkluaXQge1xyXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihAT3B0aW9uYWwoKSBwcm90ZWN0ZWQgc2Nyb2xsYmFyOiBOZ1Njcm9sbGJhciwgcHJvdGVjdGVkIHpvbmU6IE5nWm9uZSkge1xyXG4gICAgc3VwZXIoc2Nyb2xsYmFyLCB6b25lKTtcclxuICB9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuICAgICAgLy8gRml4IHRoZSB2aWV3cG9ydCBzaXplIGluIGNhc2UgdGhlIHJlbmRlcmVkIHNpemUgaXMgbm90IHJvdW5kZWRcclxuICAgICAgY29uc3QgZml4ZWRTaXplOiBudW1iZXIgPSBNYXRoLnJvdW5kKHRoaXMuc2Nyb2xsYmFyLnZpZXdwb3J0Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0KTtcclxuICAgICAgdGhpcy5zY3JvbGxiYXIudmlld3BvcnQubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSBgJHsgZml4ZWRTaXplIH1weGA7XHJcblxyXG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbiA9IHRoaXMuc2Nyb2xsYmFyLnZlcnRpY2FsU2Nyb2xsZWQhLnN1YnNjcmliZSh0aGlzLnNjcm9sbEV2ZW50KTtcclxuICAgIH0pO1xyXG4gIH1cclxufVxyXG5cclxuQERpcmVjdGl2ZSgpXHJcbmFic3RyYWN0IGNsYXNzIEhvcml6b250YWxTY3JvbGxSZWFjaGVkIGV4dGVuZHMgU2Nyb2xsUmVhY2hlZCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKEBPcHRpb25hbCgpIHByb3RlY3RlZCBzY3JvbGxiYXI6IE5nU2Nyb2xsYmFyLCBwcm90ZWN0ZWQgem9uZTogTmdab25lKSB7XHJcbiAgICBzdXBlcihzY3JvbGxiYXIsIHpvbmUpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICB0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xyXG4gICAgICAvLyBGaXggdGhlIHZpZXdwb3J0IHNpemUgaW4gY2FzZSB0aGUgcmVuZGVyZWQgc2l6ZSBpcyBub3Qgcm91bmRlZFxyXG4gICAgICBjb25zdCBmaXhlZFNpemU6IG51bWJlciA9IE1hdGgucm91bmQodGhpcy5zY3JvbGxiYXIudmlld3BvcnQubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aCk7XHJcbiAgICAgIHRoaXMuc2Nyb2xsYmFyLnZpZXdwb3J0Lm5hdGl2ZUVsZW1lbnQuc3R5bGUud2lkdGggPSBgJHsgZml4ZWRTaXplIH1weGA7XHJcblxyXG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbiA9IHRoaXMuc2Nyb2xsYmFyLmhvcml6b250YWxTY3JvbGxlZCEuc3Vic2NyaWJlKHRoaXMuc2Nyb2xsRXZlbnQpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG59XHJcblxyXG5ARGlyZWN0aXZlKHtcclxuICBzZWxlY3RvcjogJ1tyZWFjaGVkVG9wXSwgW3JlYWNoZWQtdG9wXScsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxufSlcclxuZXhwb3J0IGNsYXNzIE5nU2Nyb2xsYmFyUmVhY2hlZFRvcCBleHRlbmRzIFZlcnRpY2FsU2Nyb2xsUmVhY2hlZCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcblxyXG4gIC8qKiBTdHJlYW0gdGhhdCBlbWl0cyB3aGVuIHNjcm9sbCBoYXMgcmVhY2hlZCB0aGUgdG9wICovXHJcbiAgQE91dHB1dCgpIHJlYWNoZWRUb3A6IE9ic2VydmFibGU8RWxlbWVudEV2ZW50PiA9IHRoaXMucmVhY2hlZEV2ZW50O1xyXG5cclxuICBjb25zdHJ1Y3RvcihAT3B0aW9uYWwoKSBwcm90ZWN0ZWQgc2Nyb2xsYmFyOiBOZ1Njcm9sbGJhciwgcHJvdGVjdGVkIHpvbmU6IE5nWm9uZSkge1xyXG4gICAgc3VwZXIoc2Nyb2xsYmFyLCB6b25lKTtcclxuICB9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgc3VwZXIubmdPbkluaXQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENoZWNrIGlmIHNjcm9sbCBoYXMgcmVhY2hlZCB0aGUgdG9wICh2ZXJ0aWNhbGx5KVxyXG4gICAqIEBwYXJhbSBvZmZzZXQgU2Nyb2xsIG9mZnNldFxyXG4gICAqIEBwYXJhbSBlIFNjcm9sbCBldmVudFxyXG4gICAqL1xyXG4gIHByb3RlY3RlZCByZWFjaGVkKG9mZnNldDogbnVtYmVyLCBlOiBFbGVtZW50RXZlbnQpOiBib29sZWFuIHtcclxuICAgIHJldHVybiBSZWFjaGVkRnVuY3Rpb25zLnJlYWNoZWRUb3Aob2Zmc2V0LCBlKTtcclxuICB9XHJcbn1cclxuXHJcbkBEaXJlY3RpdmUoe1xyXG4gIHNlbGVjdG9yOiAnW3JlYWNoZWRCb3R0b21dLCBbcmVhY2hlZC1ib3R0b21dJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmdTY3JvbGxiYXJSZWFjaGVkQm90dG9tIGV4dGVuZHMgVmVydGljYWxTY3JvbGxSZWFjaGVkIGltcGxlbWVudHMgT25Jbml0IHtcclxuXHJcbiAgLyoqIFN0cmVhbSB0aGF0IGVtaXRzIHdoZW4gc2Nyb2xsIGhhcyByZWFjaGVkIHRoZSBib3R0b20gKi9cclxuICBAT3V0cHV0KCkgcmVhY2hlZEJvdHRvbTogT2JzZXJ2YWJsZTxFbGVtZW50RXZlbnQ+ID0gdGhpcy5yZWFjaGVkRXZlbnQ7XHJcblxyXG4gIGNvbnN0cnVjdG9yKEBPcHRpb25hbCgpIHByb3RlY3RlZCBzY3JvbGxiYXI6IE5nU2Nyb2xsYmFyLCBwcm90ZWN0ZWQgem9uZTogTmdab25lKSB7XHJcbiAgICBzdXBlcihzY3JvbGxiYXIsIHpvbmUpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICBzdXBlci5uZ09uSW5pdCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2hlY2sgaWYgc2Nyb2xsIGhhcyByZWFjaGVkIHRoZSBib3R0b20gKHZlcnRpY2FsbHkpXHJcbiAgICogQHBhcmFtIG9mZnNldCBTY3JvbGwgb2Zmc2V0XHJcbiAgICogQHBhcmFtIGUgU2Nyb2xsIGV2ZW50XHJcbiAgICovXHJcbiAgcHJvdGVjdGVkIHJlYWNoZWQob2Zmc2V0OiBudW1iZXIsIGU6IEVsZW1lbnRFdmVudCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIFJlYWNoZWRGdW5jdGlvbnMucmVhY2hlZEJvdHRvbShvZmZzZXQsIGUpO1xyXG4gIH1cclxufVxyXG5cclxuQERpcmVjdGl2ZSh7XHJcbiAgc2VsZWN0b3I6ICdbcmVhY2hlZFN0YXJ0XSwgW3JlYWNoZWQtc3RhcnRdJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmdTY3JvbGxiYXJSZWFjaGVkU3RhcnQgZXh0ZW5kcyBIb3Jpem9udGFsU2Nyb2xsUmVhY2hlZCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcblxyXG4gIC8qKiBTdHJlYW0gdGhhdCBlbWl0cyB3aGVuIHNjcm9sbCBoYXMgcmVhY2hlZCB0aGUgc3RhcnQgKi9cclxuICBAT3V0cHV0KCkgcmVhY2hlZFN0YXJ0OiBPYnNlcnZhYmxlPEVsZW1lbnRFdmVudD4gPSB0aGlzLnJlYWNoZWRFdmVudDtcclxuXHJcbiAgY29uc3RydWN0b3IoQE9wdGlvbmFsKCkgcHJvdGVjdGVkIHNjcm9sbGJhcjogTmdTY3JvbGxiYXIsIHByb3RlY3RlZCB6b25lOiBOZ1pvbmUsIHByaXZhdGUgZGlyOiBEaXJlY3Rpb25hbGl0eSkge1xyXG4gICAgc3VwZXIoc2Nyb2xsYmFyLCB6b25lKTtcclxuICB9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgc3VwZXIubmdPbkluaXQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENoZWNrIGlmIHNjcm9sbCBoYXMgcmVhY2hlZCB0aGUgc3RhcnQgKGhvcml6b250YWxseSlcclxuICAgKiBAcGFyYW0gb2Zmc2V0IFNjcm9sbCBvZmZzZXRcclxuICAgKiBAcGFyYW0gZSBTY3JvbGwgZXZlbnRcclxuICAgKi9cclxuICBwcm90ZWN0ZWQgcmVhY2hlZChvZmZzZXQ6IG51bWJlciwgZTogRWxlbWVudEV2ZW50KTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gUmVhY2hlZEZ1bmN0aW9ucy5yZWFjaGVkU3RhcnQob2Zmc2V0LCBlLCB0aGlzLmRpci52YWx1ZSwgdGhpcy5zY3JvbGxiYXIubWFuYWdlci5ydGxTY3JvbGxBeGlzVHlwZSk7XHJcbiAgfVxyXG59XHJcblxyXG5ARGlyZWN0aXZlKHtcclxuICBzZWxlY3RvcjogJ1tyZWFjaGVkRW5kXSwgW3JlYWNoZWQtZW5kXScsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxufSlcclxuZXhwb3J0IGNsYXNzIE5nU2Nyb2xsYmFyUmVhY2hlZEVuZCBleHRlbmRzIEhvcml6b250YWxTY3JvbGxSZWFjaGVkIGltcGxlbWVudHMgT25Jbml0IHtcclxuXHJcbiAgLyoqIFN0cmVhbSB0aGF0IGVtaXRzIHdoZW4gc2Nyb2xsIGhhcyByZWFjaGVkIHRoZSBlbmQgKi9cclxuICBAT3V0cHV0KCkgcmVhY2hlZEVuZDogT2JzZXJ2YWJsZTxFbGVtZW50RXZlbnQ+ID0gdGhpcy5yZWFjaGVkRXZlbnQ7XHJcblxyXG4gIGNvbnN0cnVjdG9yKEBPcHRpb25hbCgpIHByb3RlY3RlZCBzY3JvbGxiYXI6IE5nU2Nyb2xsYmFyLCBwcm90ZWN0ZWQgem9uZTogTmdab25lLCBwcml2YXRlIGRpcjogRGlyZWN0aW9uYWxpdHkpIHtcclxuICAgIHN1cGVyKHNjcm9sbGJhciwgem9uZSk7XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIHN1cGVyLm5nT25Jbml0KCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDaGVjayBpZiBzY3JvbGwgaGFzIHJlYWNoZWQgdGhlIGVuZCAoaG9yaXpvbnRhbGx5KVxyXG4gICAqIEBwYXJhbSBvZmZzZXQgU2Nyb2xsIG9mZnNldFxyXG4gICAqIEBwYXJhbSBlIFNjcm9sbCBldmVudFxyXG4gICAqL1xyXG4gIHByb3RlY3RlZCByZWFjaGVkKG9mZnNldDogbnVtYmVyLCBlOiBFbGVtZW50RXZlbnQpOiBib29sZWFuIHtcclxuICAgIHJldHVybiBSZWFjaGVkRnVuY3Rpb25zLnJlYWNoZWRFbmQob2Zmc2V0LCBlLCB0aGlzLmRpci52YWx1ZSwgdGhpcy5zY3JvbGxiYXIubWFuYWdlci5ydGxTY3JvbGxBeGlzVHlwZSk7XHJcbiAgfVxyXG59XHJcbiJdfQ==