UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

124 lines 21.8 kB
import { animate, state, style, transition, trigger } from '@angular/animations'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostBinding, inject, Input, Renderer2, ViewChildren } from '@angular/core'; import { Subject } from 'rxjs'; import { map, takeUntil, withLatestFrom } from 'rxjs/operators'; import { tick } from '../../common/index'; import { NotificationService } from './notification.service'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; export class NotificationListComponent { constructor() { this._notificationService = inject(NotificationService); this._changeDetectorRef = inject(ChangeDetectorRef); this._renderer = inject(Renderer2); /** Sets the position of the list of notifications within the browser window. */ this.position = 'bottom-right'; /** The list of notifications that have not been dismissed */ this.notifications$ = this._notificationService.notifications$.pipe(map(() => this._notifications)); /** Unsubscribe from all subscriptions on component destroy */ this._onDestroy = new Subject(); } /** * Sets the order in which notifications are displayed: `above` - newer notifications will appear above older ones. `below` - newer notifications will appear below older ones. */ set direction(direction) { this._notificationService.direction = direction; } /** Filter out any hidden notifications */ get _notifications() { return this._notificationService.notifications.filter(notification => notification.visible); } ngAfterViewInit() { // whenever the notifications change we want to recalculate the positions and height this._elements.changes.pipe(takeUntil(this._onDestroy), tick(), map(changes => changes.toArray()), withLatestFrom(this.notifications$)).subscribe(([elements, notifications]) => { // Set the `top` style property of each element this.applyElementPositions(elements, notifications); this.updateListPosition(elements, notifications); this._changeDetectorRef.markForCheck(); }); } ngOnChanges() { if (this._elements) { this.updateListPosition(this._elements.toArray(), this._notifications); } } ngOnDestroy() { this._onDestroy.next(); this._onDestroy.complete(); } applyElementPositions(elements, notifications) { let top = 0; for (let i = 0; i < elements.length; i += 1) { const element = elements[i].nativeElement; const notification = notifications[i]; this._renderer.setStyle(element, 'top', `${top}px`); top = top + this.getNotificationHeightInPixels(notification, elements[i]); } } updateListPosition(elements, notifications) { if (this.position === 'bottom-left' || this.position === 'bottom-right') { this._bottom = notifications.reduce((totalHeight, notification, index) => totalHeight + this.getNotificationHeightInPixels(notification, elements[index]), 0); } else { // In a top position, bottom should be unset. this._bottom = undefined; } } /** Get the height of the notification, including spacing if configured. */ getNotificationHeightInPixels(notification, elementRef) { if (notification.spacing === undefined) { return this.getElementOuterHeightInPixels(elementRef); } return elementRef.nativeElement.offsetHeight + notification.spacing; } /** Get the total height of the element including margins. */ getElementOuterHeightInPixels(elementRef) { const element = elementRef.nativeElement; const { marginTop, marginBottom } = getComputedStyle(element); return element.offsetHeight + parseInt(marginTop) + parseInt(marginBottom); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: NotificationListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: NotificationListComponent, selector: "ux-notification-list", inputs: { direction: "direction", position: "position" }, host: { properties: { "class": "this.position", "style.bottom.px": "this._bottom" } }, viewQueries: [{ propertyName: "_elements", predicate: ["notification"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "@for (notificationRef of notifications$ | async; track notificationRef; let index = $index) {\n <div #notification\n class=\"notification\"\n [style.height.px]=\"notificationRef.height\"\n [style.background-color]=\"notificationRef.backgroundColor\"\n [@notificationState]>\n <!-- Notification Content -->\n <ng-container\n [ngTemplateOutlet]=\"notificationRef.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: notificationRef, data: notificationRef.data }\">\n </ng-container>\n </div>\n}\n", dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], animations: [ trigger('notificationState', [ state('in', style({ transform: 'translateY(0)', opacity: 0.9 })), transition(':enter', [ style({ transform: 'translateY(-50px)', opacity: 0 }), animate(500) ]), transition(':leave', [ animate(500, style({ transform: 'translateY(50px)', opacity: 0 })) ]) ]) ], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: NotificationListComponent, decorators: [{ type: Component, args: [{ selector: 'ux-notification-list', changeDetection: ChangeDetectionStrategy.OnPush, animations: [ trigger('notificationState', [ state('in', style({ transform: 'translateY(0)', opacity: 0.9 })), transition(':enter', [ style({ transform: 'translateY(-50px)', opacity: 0 }), animate(500) ]), transition(':leave', [ animate(500, style({ transform: 'translateY(50px)', opacity: 0 })) ]) ]) ], template: "@for (notificationRef of notifications$ | async; track notificationRef; let index = $index) {\n <div #notification\n class=\"notification\"\n [style.height.px]=\"notificationRef.height\"\n [style.background-color]=\"notificationRef.backgroundColor\"\n [@notificationState]>\n <!-- Notification Content -->\n <ng-container\n [ngTemplateOutlet]=\"notificationRef.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: notificationRef, data: notificationRef.data }\">\n </ng-container>\n </div>\n}\n" }] }], propDecorators: { direction: [{ type: Input }], position: [{ type: Input }, { type: HostBinding, args: ['class'] }], _bottom: [{ type: HostBinding, args: ['style.bottom.px'] }], _elements: [{ type: ViewChildren, args: ['notification'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWZpY2F0aW9uLWxpc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvbm90aWZpY2F0aW9uL25vdGlmaWNhdGlvbi1saXN0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL25vdGlmaWNhdGlvbi9ub3RpZmljYXRpb24tbGlzdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2pGLE9BQU8sRUFBaUIsdUJBQXVCLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxFQUFjLFdBQVcsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFtQyxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZNLE9BQU8sRUFBYyxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDM0MsT0FBTyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEUsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzFDLE9BQU8sRUFBOEMsbUJBQW1CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQzs7O0FBbUJ6RyxNQUFNLE9BQU8seUJBQXlCO0lBakJ0QztRQWtCcUIseUJBQW9CLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFFbkQsdUJBQWtCLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFFL0MsY0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQVkvQyxnRkFBZ0Y7UUFHaEYsYUFBUSxHQUE0QixjQUFjLENBQUM7UUFFbkQsNkRBQTZEO1FBQzdELG1CQUFjLEdBQWtDLElBQUksQ0FBQyxvQkFB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QUMsUUFBUSxFQUFFO29CQUNqQixPQUFPLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxFQUFFLFNBQVMsRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztpQkFDckUsQ0FBQzthQUNMLENBQUM7U0FDTDs7NEZBRVEseUJBQXlCO2tCQWpCckMsU0FBUzsrQkFDSSxzQkFBc0IsbUJBRWYsdUJBQXVCLENBQUMsTUFBTSxjQUNuQzt3QkFDUixPQUFPLENBQUMsbUJBQW1CLEVBQUU7NEJBQ3pCLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQzs0QkFDaEUsVUFBVSxDQUFDLFFBQVEsRUFBRTtnQ0FDakIsS0FBSyxDQUFDLEVBQUUsU0FBUyxFQUFFLG1CQUFtQixFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQztnQ0FDckQsT0FBTyxDQUFDLEdBQUcsQ0FBQzs2QkFDZixDQUFDOzRCQUNGLFVBQVUsQ0FBQyxRQUFRLEVBQUU7Z0NBQ2pCLE9BQU8sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUUsU0FBUyxFQUFFLGtCQUFrQixFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDOzZCQUNyRSxDQUFDO3lCQUNMLENBQUM7cUJBQ0w7OEJBZUcsU0FBUztzQkFEWixLQUFLO2dCQVFOLFFBQVE7c0JBRlAsS0FBSzs7c0JBQ0wsV0FBVzt1QkFBQyxPQUFPO2dCQVFwQixPQUFPO3NCQUROLFdBQVc7dUJBQUMsaUJBQWlCO2dCQUlBLFNBQVM7c0JBQXRDLFlBQVk7dUJBQUMsY0FBYyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGFuaW1hdGUsIHN0YXRlLCBzdHlsZSwgdHJhbnNpdGlvbiwgdHJpZ2dlciB9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEhvc3RCaW5kaW5nLCBpbmplY3QsIElucHV0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgUXVlcnlMaXN0LCBSZW5kZXJlcjIsIFZpZXdDaGlsZHJlbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCB0YWtlVW50aWwsIHdpdGhMYXRlc3RGcm9tIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgdGljayB9IGZyb20gJy4uLy4uL2NvbW1vbi9pbmRleCc7XG5pbXBvcnQgeyBOb3RpZmljYXRpb25MaXN0RGlyZWN0aW9uLCBOb3RpZmljYXRpb25SZWYsIE5vdGlmaWNhdGlvblNlcnZpY2UgfSBmcm9tICcuL25vdGlmaWNhdGlvbi5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICd1eC1ub3RpZmljYXRpb24tbGlzdCcsXG4gICAgdGVtcGxhdGVVcmw6ICcuL25vdGlmaWNhdGlvbi1saXN0LmNvbXBvbmVudC5odG1sJyxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgICBhbmltYXRpb25zOiBbXG4gICAgICAgIHRyaWdnZXIoJ25vdGlmaWNhdGlvblN0YXRlJywgW1xuICAgICAgICAgICAgc3RhdGUoJ2luJywgc3R5bGUoeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGVZKDApJywgb3BhY2l0eTogMC45IH0pKSxcbiAgICAgICAgICAgIHRyYW5zaXRpb24oJzplbnRlcicsIFtcbiAgICAgICAgICAgICAgICBzdHlsZSh7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZVkoLTUwcHgpJywgb3BhY2l0eTogMCB9KSxcbiAgICAgICAgICAgICAgICBhbmltYXRlKDUwMClcbiAgICAgICAgICAgIF0pLFxuICAgICAgICAgICAgdHJhbnNpdGlvbignOmxlYXZlJywgW1xuICAgICAgICAgICAgICAgIGFuaW1hdGUoNTAwLCBzdHlsZSh7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZVkoNTBweCknLCBvcGFjaXR5OiAwIH0pKVxuICAgICAgICAgICAgXSlcbiAgICAgICAgXSlcbiAgICBdXG59KVxuZXhwb3J0IGNsYXNzIE5vdGlmaWNhdGlvbkxpc3RDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfbm90aWZpY2F0aW9uU2VydmljZSA9IGluamVjdChOb3RpZmljYXRpb25TZXJ2aWNlKTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NoYW5nZURldGVjdG9yUmVmID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3JlbmRlcmVyID0gaW5qZWN0KFJlbmRlcmVyMik7XG5cbiAgICAvKipcbiAgICAgKiAgU2V0cyB0aGUgb3JkZXIgaW4gd2hpY2ggbm90aWZpY2F0aW9ucyBhcmUgZGlzcGxheWVkOlxuICAgICAgICBgYWJvdmVgIC0gbmV3ZXIgbm90aWZpY2F0aW9ucyB3aWxsIGFwcGVhciBhYm92ZSBvbGRlciBvbmVzLlxuICAgICAgICBgYmVsb3dgIC0gbmV3ZXIgbm90aWZpY2F0aW9ucyB3aWxsIGFwcGVhciBiZWxvdyBvbGRlciBvbmVzLlxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgc2V0IGRpcmVjdGlvbihkaXJlY3Rpb246IE5vdGlmaWNhdGlvbkxpc3REaXJlY3Rpb24pIHtcbiAgICAgICAgdGhpcy5fbm90aWZpY2F0aW9uU2VydmljZS5kaXJlY3Rpb24gPSBkaXJlY3Rpb247XG4gICAgfVxuXG4gICAgLyoqIFNldHMgdGhlIHBvc2l0aW9uIG9mIHRoZSBsaXN0IG9mIG5vdGlmaWNhdGlvbnMgd2l0aGluIHRoZSBicm93c2VyIHdpbmRvdy4gKi9cbiAgICBASW5wdXQoKVxuICAgIEBIb3N0QmluZGluZygnY2xhc3MnKVxuICAgIHBvc2l0aW9uOiBOb3RpZmljYXRpb25MaXN0UG9zdGlvbiA9ICdib3R0b20tcmlnaHQnO1xuXG4gICAgLyoqIFRoZSBsaXN0IG9mIG5vdGlmaWNhdGlvbnMgdGhhdCBoYXZlIG5vdCBiZWVuIGRpc21pc3NlZCAqL1xuICAgIG5vdGlmaWNhdGlvbnMkOiBPYnNlcnZhYmxlPE5vdGlmaWNhdGlvblJlZltdPiA9IHRoaXMuX25vdGlmaWNhdGlvblNlcnZpY2Uubm90aWZpY2F0aW9ucyQucGlwZShtYXAoKCkgPT4gdGhpcy5fbm90aWZpY2F0aW9ucykpO1xuXG4gICAgLyoqIFN0b3JlIHRoZSBib3R0b20gcG9zaXRpb24gb2YgdGhlIG5vdGlmaWNhdGlvbiBsaXN0ICovXG4gICAgQEhvc3RCaW5kaW5nKCdzdHlsZS5ib3R0b20ucHgnKVxuICAgIF9ib3R0b206IG51bWJlcjtcblxuICAgIC8qKiBTdG9yZSBhIGxpc3Qgb2YgYWxsIGVsZW1lbnQgcmVmcyAqL1xuICAgIEBWaWV3Q2hpbGRyZW4oJ25vdGlmaWNhdGlvbicpIF9lbGVtZW50czogUXVlcnlMaXN0PEVsZW1lbnRSZWY+O1xuXG4gICAgLyoqIEZpbHRlciBvdXQgYW55IGhpZGRlbiBub3RpZmljYXRpb25zICovXG4gICAgcHJpdmF0ZSBnZXQgX25vdGlmaWNhdGlvbnMoKTogTm90aWZpY2F0aW9uUmVmW10ge1xuICAgICAgICByZXR1cm4gdGhpcy5fbm90aWZpY2F0aW9uU2VydmljZS5ub3RpZmljYXRpb25zLmZpbHRlcihub3RpZmljYXRpb24gPT4gbm90aWZpY2F0aW9uLnZpc2libGUpO1xuICAgIH1cblxuICAgIC8qKiBVbnN1YnNjcmliZSBmcm9tIGFsbCBzdWJzY3JpcHRpb25zIG9uIGNvbXBvbmVudCBkZXN0cm95ICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBfb25EZXN0cm95ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcblxuICAgICAgICAvLyB3aGVuZXZlciB0aGUgbm90aWZpY2F0aW9ucyBjaGFuZ2Ugd2Ugd2FudCB0byByZWNhbGN1bGF0ZSB0aGUgcG9zaXRpb25zIGFuZCBoZWlnaHRcbiAgICAgICAgdGhpcy5fZWxlbWVudHMuY2hhbmdlcy5waXBlKFxuICAgICAgICAgICAgdGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSksXG4gICAgICAgICAgICB0aWNrKCksXG4gICAgICAgICAgICBtYXAoY2hhbmdlcyA9PiBjaGFuZ2VzLnRvQXJyYXkoKSBhcyBFbGVtZW50UmVmW10pLFxuICAgICAgICAgICAgd2l0aExhdGVzdEZyb20odGhpcy5ub3RpZmljYXRpb25zJClcbiAgICAgICAgKS5zdWJzY3JpYmUoKFtlbGVtZW50cywgbm90aWZpY2F0aW9uc10pID0+IHtcblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBgdG9wYCBzdHlsZSBwcm9wZXJ0eSBvZiBlYWNoIGVsZW1lbnRcbiAgICAgICAgICAgIHRoaXMuYXBwbHlFbGVtZW50UG9zaXRpb25zKGVsZW1lbnRzLCBub3RpZmljYXRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy51cGRhdGVMaXN0UG9zaXRpb24oZWxlbWVudHMsIG5vdGlmaWNhdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLl9lbGVtZW50cykge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVMaXN0UG9zaXRpb24odGhpcy5fZWxlbWVudHMudG9BcnJheSgpLCB0aGlzLl9ub3RpZmljYXRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9vbkRlc3Ryb3kubmV4dCgpO1xuICAgICAgICB0aGlzLl9vbkRlc3Ryb3kuY29tcGxldGUoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFwcGx5RWxlbWVudFBvc2l0aW9ucyhlbGVtZW50czogRWxlbWVudFJlZltdLCBub3RpZmljYXRpb25zOiBOb3RpZmljYXRpb25SZWZbXSk6IHZvaWQge1xuICAgICAgICBsZXQgdG9wID0gMDtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IGVsZW1lbnRzW2ldLm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgICAgICBjb25zdCBub3RpZmljYXRpb24gPSBub3RpZmljYXRpb25zW2ldO1xuICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0U3R5bGUoZWxlbWVudCwgJ3RvcCcsIGAke3RvcH1weGApO1xuICAgICAgICAgICAgdG9wID0gdG9wICsgdGhpcy5nZXROb3RpZmljYXRpb25IZWlnaHRJblBpeGVscyhub3RpZmljYXRpb24sIGVsZW1lbnRzW2ldKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgdXBkYXRlTGlzdFBvc2l0aW9uKGVsZW1lbnRzOiBFbGVtZW50UmVmW10sIG5vdGlmaWNhdGlvbnM6IE5vdGlmaWNhdGlvblJlZltdKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnBvc2l0aW9uID09PSAnYm90dG9tLWxlZnQnIHx8IHRoaXMucG9zaXRpb24gPT09ICdib3R0b20tcmlnaHQnKSB7XG4gICAgICAgICAgICB0aGlzLl9ib3R0b20gPSBub3RpZmljYXRpb25zLnJlZHVjZSgodG90YWxIZWlnaHQsIG5vdGlmaWNhdGlvbiwgaW5kZXgpID0+XG4gICAgICAgICAgICAgICAgdG90YWxIZWlnaHQgKyB0aGlzLmdldE5vdGlmaWNhdGlvbkhlaWdodEluUGl4ZWxzKG5vdGlmaWNhdGlvbiwgZWxlbWVudHNbaW5kZXhdKSwgMCk7XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIC8vIEluIGEgdG9wIHBvc2l0aW9uLCBib3R0b20gc2hvdWxkIGJlIHVuc2V0LlxuICAgICAgICAgICAgdGhpcy5fYm90dG9tID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEdldCB0aGUgaGVpZ2h0IG9mIHRoZSBub3RpZmljYXRpb24sIGluY2x1ZGluZyBzcGFjaW5nIGlmIGNvbmZpZ3VyZWQuICovXG4gICAgcHJpdmF0ZSBnZXROb3RpZmljYXRpb25IZWlnaHRJblBpeGVscyhub3RpZmljYXRpb246IE5vdGlmaWNhdGlvblJlZiwgZWxlbWVudFJlZjogRWxlbWVudFJlZik6IG51bWJlciB7XG4gICAgICAgIGlmIChub3RpZmljYXRpb24uc3BhY2luZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRFbGVtZW50T3V0ZXJIZWlnaHRJblBpeGVscyhlbGVtZW50UmVmKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBlbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQub2Zmc2V0SGVpZ2h0ICsgbm90aWZpY2F0aW9uLnNwYWNpbmc7XG4gICAgfVxuXG4gICAgLyoqIEdldCB0aGUgdG90YWwgaGVpZ2h0IG9mIHRoZSBlbGVtZW50IGluY2x1ZGluZyBtYXJnaW5zLiAqL1xuICAgIHByaXZhdGUgZ2V0RWxlbWVudE91dGVySGVpZ2h0SW5QaXhlbHMoZWxlbWVudFJlZjogRWxlbWVudFJlZik6IG51bWJlciB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSBlbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgIGNvbnN0IHsgbWFyZ2luVG9wLCBtYXJnaW5Cb3R0b20gfSA9IGdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XG5cbiAgICAgICAgcmV0dXJuIGVsZW1lbnQub2Zmc2V0SGVpZ2h0ICsgcGFyc2VJbnQobWFyZ2luVG9wKSArIHBhcnNlSW50KG1hcmdpbkJvdHRvbSk7XG4gICAgfVxufVxuXG5leHBvcnQgdHlwZSBOb3RpZmljYXRpb25MaXN0UG9zdGlvbiA9ICd0b3AtbGVmdCcgfCAndG9wLXJpZ2h0JyB8ICdib3R0b20tbGVmdCcgfCAnYm90dG9tLXJpZ2h0JztcbiIsIkBmb3IgKG5vdGlmaWNhdGlvblJlZiBvZiBub3RpZmljYXRpb25zJCB8IGFzeW5jOyB0cmFjayBub3RpZmljYXRpb25SZWY7IGxldCBpbmRleCA9ICRpbmRleCkge1xuICA8ZGl2ICNub3RpZmljYXRpb25cbiAgICBjbGFzcz1cIm5vdGlmaWNhdGlvblwiXG4gICAgW3N0eWxlLmhlaWdodC5weF09XCJub3RpZmljYXRpb25SZWYuaGVpZ2h0XCJcbiAgICBbc3R5bGUuYmFja2dyb3VuZC1jb2xvcl09XCJub3RpZmljYXRpb25SZWYuYmFja2dyb3VuZENvbG9yXCJcbiAgICBbQG5vdGlmaWNhdGlvblN0YXRlXT5cbiAgICA8IS0tIE5vdGlmaWNhdGlvbiBDb250ZW50IC0tPlxuICAgIDxuZy1jb250YWluZXJcbiAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIm5vdGlmaWNhdGlvblJlZi50ZW1wbGF0ZVJlZlwiXG4gICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IG5vdGlmaWNhdGlvblJlZiwgZGF0YTogbm90aWZpY2F0aW9uUmVmLmRhdGEgfVwiPlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L2Rpdj5cbn1cbiJdfQ==