@favian/headwind-ui
Version:
Headless UI for Angular - Styleless Angular components to integrate with Tailwind CSS
190 lines • 30.1 kB
JavaScript
import { Component, ContentChildren, EventEmitter, HostListener, Output, } from '@angular/core';
import { HeadwindOptionComponent } from './headwind-option/headwind-option.component';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { HeadwindClickDetector } from '../../../services/headwind-click-detector.service';
import * as i0 from "@angular/core";
import * as i1 from "../../../services/headwind-window.service";
import * as i2 from "../../../services/headwind-platform.service";
import * as i3 from "../../../services/headwind-click-detector.service";
import * as i4 from "../../../services/headwind-query-list.service";
import * as i5 from "../service/headwind-select.service";
export class HeadwindOptionsOverlayComponent {
constructor(_renderer, _elementRef, _headwindWindowService, _headwindPlatformService, _headwindClickDetector, _headwindQueryListService, _headwindSelectService) {
this._renderer = _renderer;
this._elementRef = _elementRef;
this._headwindWindowService = _headwindWindowService;
this._headwindPlatformService = _headwindPlatformService;
this._headwindClickDetector = _headwindClickDetector;
this._headwindQueryListService = _headwindQueryListService;
this._headwindSelectService = _headwindSelectService;
this.actualDirectionChange = new EventEmitter();
this._focusedIndex = -1;
this._headwindClickDetector.outsideClick.pipe(takeUntilDestroyed()).subscribe(() => {
if (this._headwindSelectService.optionsOpened) {
this._headwindSelectService.closeOptions.emit();
}
});
this._headwindSelectService.focusOption.pipe(takeUntilDestroyed()).subscribe((value) => {
this._focusedIndex = this.findOptionIndexByValue(value);
this.scrollToOptionByValue(value);
});
this._headwindSelectService.hoverOption.pipe(takeUntilDestroyed()).subscribe(() => {
this._focusedIndex = -1;
});
this._headwindSelectService.optionsOpened$.pipe(takeUntilDestroyed()).subscribe((opened) => {
if (opened) {
this._headwindClickDetector.register(this._elementRef.nativeElement);
}
else {
this._headwindClickDetector.unregister();
}
});
}
get optionsLastIndex() {
return this.optionList ? this.optionList.length - 1 : 0;
}
ngAfterContentInit() {
this.focusToSelected();
this.scrollToOptionByValue(this._headwindSelectService.value);
}
onWindowArrowUpKeydown(event) {
if (!this._headwindSelectService.optionsOpened) {
return;
}
event.preventDefault();
event.stopPropagation();
this.focusToPrevious();
}
onWindowArrowDownKeydown(event) {
if (!this._headwindSelectService.optionsOpened) {
return;
}
event.preventDefault();
event.stopPropagation();
this.focusToNext();
}
onWindowSpaceKeydown(event) {
if (!this._headwindSelectService.optionsOpened) {
return;
}
event.preventDefault();
event.stopPropagation();
this.selectFocusedOption();
if (!this._headwindSelectService.multiple) {
this._headwindSelectService.closeOptions.emit();
}
}
onWindowEnterKeydown(event) {
if (!this._headwindSelectService.optionsOpened) {
return;
}
event.preventDefault();
event.stopPropagation();
this.selectFocusedOption();
if (!this._headwindSelectService.multiple) {
this._headwindSelectService.closeOptions.emit();
}
}
/** Focus to option that is equal to value */
focusToSelected() {
this._elementRef?.nativeElement.focus();
const { multiple, value } = this._headwindSelectService;
let targetOption;
if (multiple) {
targetOption = this.findOptionByValue(value[value.length - 1]);
}
else {
targetOption = this.findOptionByValue(value);
}
if (!targetOption) {
targetOption = this.optionList?.get(0);
}
targetOption?.focus();
}
focusToPrevious() {
this.optionList?.get(Math.max(this._focusedIndex - 1, 0))?.focus();
}
focusToNext() {
this.optionList?.get(Math.min(this._focusedIndex + 1, this.optionsLastIndex))?.focus();
}
selectFocusedOption() {
const focusedOption = this.optionList?.get(this._focusedIndex);
if (focusedOption) {
this._headwindSelectService.selectOption.emit(focusedOption.value);
}
}
findOptionByValue(value) {
return this.optionList?.get(this.findOptionIndexByValue(value));
}
findOptionIndexByValue(value) {
return this._headwindQueryListService.findIndex(this.optionList, (option) => option.value === value);
}
updatePosition(select) {
if (this._headwindPlatformService.isBrowser && this._elementRef) {
const options = this._elementRef.nativeElement;
this._renderer.removeStyle(options, 'top');
this._renderer.removeStyle(options, 'bottom');
const selectDomRect = select.getBoundingClientRect();
const optionsDomRect = options.getBoundingClientRect();
this._renderer.setStyle(options, 'width', selectDomRect.width + 'px');
this._renderer.setStyle(options, 'left', selectDomRect.left + 'px');
if (this._headwindWindowService.isBottomSpaceAvailable(selectDomRect.bottom, optionsDomRect.height)) {
this._renderer.setStyle(options, 'top', selectDomRect.bottom + 'px');
this._emitActualDirectionBottom();
}
else if (this._headwindWindowService.isTopSpaceAvailable(selectDomRect.top, optionsDomRect.height)) {
this._renderer.setStyle(options, 'bottom', `calc(100% - ${selectDomRect.top}px)`);
this._emitActualDirectionTop();
}
else {
this._renderer.setStyle(options, 'top', selectDomRect.bottom + 'px');
this._emitActualDirectionBottom();
}
}
}
scrollToOptionByValue(value) {
const optionIndex = this.findOptionIndexByValue(value);
const option = this.optionList?.get(optionIndex);
const host = this._elementRef?.nativeElement;
const optionDomRect = option?.getBoundingClientRect();
const hostDomRect = host?.getBoundingClientRect();
if (host && optionDomRect && hostDomRect) {
const scrollTop = host.scrollTop;
host.scrollTop =
scrollTop + (optionDomRect.y - hostDomRect.y) - hostDomRect.height / 2 + optionDomRect.height / 2;
}
}
_emitActualDirectionTop() {
this.actualDirectionChange.emit('top');
}
_emitActualDirectionBottom() {
this.actualDirectionChange.emit('bottom');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HeadwindOptionsOverlayComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i1.HeadwindWindowService }, { token: i2.HeadwindPlatformService }, { token: i3.HeadwindClickDetector }, { token: i4.HeadwindQueryListService }, { token: i5.HeadwindSelectService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: HeadwindOptionsOverlayComponent, isStandalone: true, selector: "headwind-options-overlay", outputs: { actualDirectionChange: "actualDirectionChange" }, host: { attributes: { "role": "listbox" }, listeners: { "window:keydown.arrowUp": "onWindowArrowUpKeydown($event)", "window:keydown.arrowDown": "onWindowArrowDownKeydown($event)", "window:keydown.space": "onWindowSpaceKeydown($event)", "window:keydown.enter": "onWindowEnterKeydown($event)" }, classAttribute: "headwind-options-overlay" }, providers: [HeadwindClickDetector], queries: [{ propertyName: "optionList", predicate: HeadwindOptionComponent, descendants: true }], ngImport: i0, template: "<ng-content></ng-content>\r\n", styles: [":host{position:absolute}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HeadwindOptionsOverlayComponent, decorators: [{
type: Component,
args: [{ selector: 'headwind-options-overlay', standalone: true, imports: [], providers: [HeadwindClickDetector], host: {
class: 'headwind-options-overlay',
role: 'listbox',
}, template: "<ng-content></ng-content>\r\n", styles: [":host{position:absolute}\n"] }]
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i1.HeadwindWindowService }, { type: i2.HeadwindPlatformService }, { type: i3.HeadwindClickDetector }, { type: i4.HeadwindQueryListService }, { type: i5.HeadwindSelectService }], propDecorators: { actualDirectionChange: [{
type: Output
}], optionList: [{
type: ContentChildren,
args: [HeadwindOptionComponent, { descendants: true }]
}], onWindowArrowUpKeydown: [{
type: HostListener,
args: ['window:keydown.arrowUp', ['$event']]
}], onWindowArrowDownKeydown: [{
type: HostListener,
args: ['window:keydown.arrowDown', ['$event']]
}], onWindowSpaceKeydown: [{
type: HostListener,
args: ['window:keydown.space', ['$event']]
}], onWindowEnterKeydown: [{
type: HostListener,
args: ['window:keydown.enter', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZHdpbmQtb3B0aW9ucy1vdmVybGF5LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2hlYWR3aW5kLXVpL3NyYy9jb21wb25lbnRzL2hlYWR3aW5kLXNlbGVjdC9oZWFkd2luZC1vcHRpb25zLW92ZXJsYXkvaGVhZHdpbmQtb3B0aW9ucy1vdmVybGF5LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2hlYWR3aW5kLXVpL3NyYy9jb21wb25lbnRzL2hlYWR3aW5kLXNlbGVjdC9oZWFkd2luZC1vcHRpb25zLW92ZXJsYXkvaGVhZHdpbmQtb3B0aW9ucy1vdmVybGF5LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCxTQUFTLEVBQ1QsZUFBZSxFQUVmLFlBQVksRUFDWixZQUFZLEVBQ1osTUFBTSxHQUdQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBQ3RGLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG1EQUFtRCxDQUFDOzs7Ozs7O0FBbUIxRixNQUFNLE9BQU8sK0JBQStCO0lBUTFDLFlBQ21CLFNBQW9CLEVBQ3BCLFdBQW9DLEVBQ3BDLHNCQUE2QyxFQUM3Qyx3QkFBaUQsRUFDakQsc0JBQTZDLEVBQzdDLHlCQUFtRCxFQUNuRCxzQkFBNkM7UUFON0MsY0FBUyxHQUFULFNBQVMsQ0FBVztRQUNwQixnQkFBVyxHQUFYLFdBQVcsQ0FBeUI7UUFDcEMsMkJBQXNCLEdBQXRCLHNCQUFzQixDQUF1QjtRQUM3Qyw2QkFBd0IsR0FBeEIsd0JBQXdCLENBQXlCO1FBQ2pELDJCQUFzQixHQUF0QixzQkFBc0IsQ0FBdUI7UUFDN0MsOEJBQXlCLEdBQXpCLHlCQUF5QixD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QUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1QyxDQUFDOytHQXZNVSwrQkFBK0I7bUdBQS9CLCtCQUErQix3ZEFOL0IsQ0FBQyxxQkFBcUIsQ0FBQyxxREFTakIsdUJBQXVCLGdEQ25DMUMsK0JBQ0E7OzRGRCtCYSwrQkFBK0I7a0JBWjNDLFNBQVM7K0JBQ0UsMEJBQTBCLGNBQ3hCLElBQUksV0FDUCxFQUFFLGFBR0EsQ0FBQyxxQkFBcUIsQ0FBQyxRQUM1Qjt3QkFDSixLQUFLLEVBQUUsMEJBQTBCO3dCQUNqQyxJQUFJLEVBQUUsU0FBUztxQkFDaEI7Z1NBR1MscUJBQXFCO3NCQUE5QixNQUFNO2dCQUdQLFVBQVU7c0JBRFQsZUFBZTt1QkFBQyx1QkFBdUIsRUFBRSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUU7Z0JBZ0QvRCxzQkFBc0I7c0JBRHJCLFlBQVk7dUJBQUMsd0JBQXdCLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBYWxELHdCQUF3QjtzQkFEdkIsWUFBWTt1QkFBQywwQkFBMEIsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFhcEQsb0JBQW9CO3NCQURuQixZQUFZO3VCQUFDLHNCQUFzQixFQUFFLENBQUMsUUFBUSxDQUFDO2dCQWlCaEQsb0JBQW9CO3NCQURuQixZQUFZO3VCQUFDLHNCQUFzQixFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBBZnRlckNvbnRlbnRJbml0LFxyXG4gIENvbXBvbmVudCxcclxuICBDb250ZW50Q2hpbGRyZW4sXHJcbiAgRWxlbWVudFJlZixcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgSG9zdExpc3RlbmVyLFxyXG4gIE91dHB1dCxcclxuICBRdWVyeUxpc3QsXHJcbiAgUmVuZGVyZXIyLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBIZWFkd2luZE9wdGlvbkNvbXBvbmVudCB9IGZyb20gJy4vaGVhZHdpbmQtb3B0aW9uL2hlYWR3aW5kLW9wdGlvbi5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XHJcbmltcG9ydCB7IEhlYWR3aW5kQ2xpY2tEZXRlY3RvciB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2hlYWR3aW5kLWNsaWNrLWRldGVjdG9yLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBIZWFkd2luZFdpbmRvd1NlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9oZWFkd2luZC13aW5kb3cuc2VydmljZSc7XHJcbmltcG9ydCB7IEhlYWR3aW5kUGxhdGZvcm1TZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvaGVhZHdpbmQtcGxhdGZvcm0uc2VydmljZSc7XHJcbmltcG9ydCB7IEhlYWR3aW5kU2VsZWN0U2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2UvaGVhZHdpbmQtc2VsZWN0LnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBZRGlyZWN0aW9ucyB9IGZyb20gJy4uLy4uLy4uL3R5cGVzL3ktZGlyZWN0aW9ucyc7XHJcbmltcG9ydCB7IEhlYWR3aW5kUXVlcnlMaXN0U2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2hlYWR3aW5kLXF1ZXJ5LWxpc3Quc2VydmljZSc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2hlYWR3aW5kLW9wdGlvbnMtb3ZlcmxheScsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbXSxcclxuICB0ZW1wbGF0ZVVybDogJy4vaGVhZHdpbmQtb3B0aW9ucy1vdmVybGF5LmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybDogJy4vaGVhZHdpbmQtb3B0aW9ucy1vdmVybGF5LmNvbXBvbmVudC5zY3NzJyxcclxuICBwcm92aWRlcnM6IFtIZWFkd2luZENsaWNrRGV0ZWN0b3JdLFxyXG4gIGhvc3Q6IHtcclxuICAgIGNsYXNzOiAnaGVhZHdpbmQtb3B0aW9ucy1vdmVybGF5JyxcclxuICAgIHJvbGU6ICdsaXN0Ym94JyxcclxuICB9LFxyXG59KVxyXG5leHBvcnQgY2xhc3MgSGVhZHdpbmRPcHRpb25zT3ZlcmxheUNvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyQ29udGVudEluaXQge1xyXG4gIEBPdXRwdXQoKSBhY3R1YWxEaXJlY3Rpb25DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPFlEaXJlY3Rpb25zPigpO1xyXG5cclxuICBAQ29udGVudENoaWxkcmVuKEhlYWR3aW5kT3B0aW9uQ29tcG9uZW50LCB7IGRlc2NlbmRhbnRzOiB0cnVlIH0pXHJcbiAgb3B0aW9uTGlzdD86IFF1ZXJ5TGlzdDxIZWFkd2luZE9wdGlvbkNvbXBvbmVudD47XHJcblxyXG4gIHByaXZhdGUgX2ZvY3VzZWRJbmRleCA9IC0xO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3JlbmRlcmVyOiBSZW5kZXJlcjIsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9lbGVtZW50UmVmOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2hlYWR3aW5kV2luZG93U2VydmljZTogSGVhZHdpbmRXaW5kb3dTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfaGVhZHdpbmRQbGF0Zm9ybVNlcnZpY2U6IEhlYWR3aW5kUGxhdGZvcm1TZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfaGVhZHdpbmRDbGlja0RldGVjdG9yOiBIZWFkd2luZENsaWNrRGV0ZWN0b3IsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9oZWFkd2luZFF1ZXJ5TGlzdFNlcnZpY2U6IEhlYWR3aW5kUXVlcnlMaXN0U2VydmljZSxcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2hlYWR3aW5kU2VsZWN0U2VydmljZTogSGVhZHdpbmRTZWxlY3RTZXJ2aWNlLFxyXG4gICkge1xyXG4gICAgdGhpcy5faGVhZHdpbmRDbGlja0RldGVjdG9yLm91dHNpZGVDbGljay5waXBlKHRha2VVbnRpbERlc3Ryb3llZCgpKS5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICBpZiAodGhpcy5faGVhZHdpbmRTZWxlY3RTZXJ2aWNlLm9wdGlvbnNPcGVuZWQpIHtcclxuICAgICAgICB0aGlzLl9oZWFkd2luZFNlbGVjdFNlcnZpY2UuY2xvc2VPcHRpb25zLmVtaXQoKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5faGVhZHdpbmRTZWxlY3RTZXJ2aWNlLmZvY3VzT3B0aW9uLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKCkpLnN1YnNjcmliZSgodmFsdWUpID0+IHtcclxuICAgICAgdGhpcy5fZm9jdXNlZEluZGV4ID0gdGhpcy5maW5kT3B0aW9uSW5kZXhCeVZhbHVlKHZhbHVlKTtcclxuICAgICAgdGhpcy5zY3JvbGxUb09wdGlvbkJ5VmFsdWUodmFsdWUpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5faGVhZHdpbmRTZWxlY3RTZXJ2aWNlLmhvdmVyT3B0aW9uLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKCkpLnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICAgIHRoaXMuX2ZvY3VzZWRJbmRleCA9IC0xO1xyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5faGVhZHdpbmRTZWxlY3RTZXJ2aWNlLm9wdGlvbnNPcGVuZWQkLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKCkpLnN1YnNjcmliZSgob3BlbmVkKSA9PiB7XHJcbiAgICAgIGlmIChvcGVuZWQpIHtcclxuICAgICAgICB0aGlzLl9oZWFkd2luZENsaWNrRGV0ZWN0b3IucmVnaXN0ZXIodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50KTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLl9oZWFkd2luZENsaWNrRGV0ZWN0b3IudW5yZWdpc3RlcigpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGdldCBvcHRpb25zTGFzdEluZGV4KCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gdGhpcy5vcHRpb25MaXN0ID8gdGhpcy5vcHRpb25MaXN0Lmxlbmd0aCAtIDEgOiAwO1xyXG4gIH1cclxuXHJcbiAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xyXG4gICAgdGhpcy5mb2N1c1RvU2VsZWN0ZWQoKTtcclxuICAgIHRoaXMuc2Nyb2xsVG9PcHRpb25CeVZhbHVlKHRoaXMuX2hlYWR3aW5kU2VsZWN0U2VydmljZS52YWx1ZSk7XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5ZG93bi5hcnJvd1VwJywgWyckZXZlbnQnXSlcclxuICBvbldpbmRvd0Fycm93VXBLZXlkb3duKGV2ZW50OiBFdmVudCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLl9oZWFkd2luZFNlbGVjdFNlcnZpY2Uub3B0aW9uc09wZW5lZCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cclxuICAgIHRoaXMuZm9jdXNUb1ByZXZpb3VzKCk7XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5ZG93bi5hcnJvd0Rvd24nLCBbJyRldmVudCddKVxyXG4gIG9uV2luZG93QXJyb3dEb3duS2V5ZG93bihldmVudDogRXZlbnQpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5faGVhZHdpbmRTZWxlY3RTZXJ2aWNlLm9wdGlvbnNPcGVuZWQpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuXHJcbiAgICB0aGlzLmZvY3VzVG9OZXh0KCk7XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5ZG93bi5zcGFjZScsIFsnJGV2ZW50J10pXHJcbiAgb25XaW5kb3dTcGFjZUtleWRvd24oZXZlbnQ6IEV2ZW50KTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuX2hlYWR3aW5kU2VsZWN0U2VydmljZS5vcHRpb25zT3BlbmVkKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcblxyXG4gICAgdGhpcy5zZWxlY3RGb2N1c2VkT3B0aW9uKCk7XHJcblxyXG4gICAgaWYgKCF0aGlzLl9oZWFkd2luZFNlbGVjdFNlcnZpY2UubXVsdGlwbGUpIHtcclxuICAgICAgdGhpcy5faGVhZHdpbmRTZWxlY3RTZXJ2aWNlLmNsb3NlT3B0aW9ucy5lbWl0KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5ZG93bi5lbnRlcicsIFsnJGV2ZW50J10pXHJcbiAgb25XaW5kb3dFbnRlcktleWRvd24oZXZlbnQ6IEV2ZW50KTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuX2hlYWR3aW5kU2VsZWN0U2VydmljZS5vcHRpb25zT3BlbmVkKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcblxyXG4gICAgdGhpcy5zZWxlY3RGb2N1c2VkT3B0aW9uKCk7XHJcblxyXG4gICAgaWYgKCF0aGlzLl9oZWFkd2luZFNlbGVjdFNlcnZpY2UubXVsdGlwbGUpIHtcclxuICAgICAgdGhpcy5faGVhZHdpbmRTZWxlY3RTZXJ2aWNlLmNsb3NlT3B0aW9ucy5lbWl0KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogRm9jdXMgdG8gb3B0aW9uIHRoYXQgaXMgZXF1YWwgdG8gdmFsdWUgKi9cclxuICBmb2N1c1RvU2VsZWN0ZWQoKTogdm9pZCB7XHJcbiAgICB0aGlzLl9lbGVtZW50UmVmPy5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XHJcblxyXG4gICAgY29uc3QgeyBtdWx0aXBsZSwgdmFsdWUgfSA9IHRoaXMuX2hlYWR3aW5kU2VsZWN0U2VydmljZTtcclxuXHJcbiAgICBsZXQgdGFyZ2V0T3B0aW9uOiBIZWFkd2luZE9wdGlvbkNvbXBvbmVudCB8IHVuZGVmaW5lZDtcclxuXHJcbiAgICBpZiAobXVsdGlwbGUpIHtcclxuICAgICAgdGFyZ2V0T3B0aW9uID0gdGhpcy5maW5kT3B0aW9uQnlWYWx1ZSh2YWx1ZVt2YWx1ZS5sZW5ndGggLSAxXSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0YXJnZXRPcHRpb24gPSB0aGlzLmZpbmRPcHRpb25CeVZhbHVlKHZhbHVlKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIXRhcmdldE9wdGlvbikge1xyXG4gICAgICB0YXJnZXRPcHRpb24gPSB0aGlzLm9wdGlvbkxpc3Q/LmdldCgwKTtcclxuICAgIH1cclxuXHJcbiAgICB0YXJnZXRPcHRpb24/LmZvY3VzKCk7XHJcbiAgfVxyXG5cclxuICBmb2N1c1RvUHJldmlvdXMoKTogdm9pZCB7XHJcbiAgICB0aGlzLm9wdGlvbkxpc3Q/LmdldChNYXRoLm1heCh0aGlzLl9mb2N1c2VkSW5kZXggLSAxLCAwKSk/LmZvY3VzKCk7XHJcbiAgfVxyXG5cclxuICBmb2N1c1RvTmV4dCgpOiB2b2lkIHtcclxuICAgIHRoaXMub3B0aW9uTGlzdD8uZ2V0KE1hdGgubWluKHRoaXMuX2ZvY3VzZWRJbmRleCArIDEsIHRoaXMub3B0aW9uc0xhc3RJbmRleCkpPy5mb2N1cygpO1xyXG4gIH1cclxuXHJcbiAgc2VsZWN0Rm9jdXNlZE9wdGlvbigpOiB2b2lkIHtcclxuICAgIGNvbnN0IGZvY3VzZWRPcHRpb24gPSB0aGlzLm9wdGlvbkxpc3Q/LmdldCh0aGlzLl9mb2N1c2VkSW5kZXgpO1xyXG5cclxuICAgIGlmIChmb2N1c2VkT3B0aW9uKSB7XHJcbiAgICAgIHRoaXMuX2hlYWR3aW5kU2VsZWN0U2VydmljZS5zZWxlY3RPcHRpb24uZW1pdChmb2N1c2VkT3B0aW9uLnZhbHVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGZpbmRPcHRpb25CeVZhbHVlKHZhbHVlOiBhbnkpOiBIZWFkd2luZE9wdGlvbkNvbXBvbmVudCB8IHVuZGVmaW5lZCB7XHJcbiAgICByZXR1cm4gdGhpcy5vcHRpb25MaXN0Py5nZXQodGhpcy5maW5kT3B0aW9uSW5kZXhCeVZhbHVlKHZhbHVlKSk7XHJcbiAgfVxyXG5cclxuICBmaW5kT3B0aW9uSW5kZXhCeVZhbHVlKHZhbHVlOiBhbnkpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuX2hlYWR3aW5kUXVlcnlMaXN0U2VydmljZS5maW5kSW5kZXgodGhpcy5vcHRpb25MaXN0LCAob3B0aW9uKSA9PiBvcHRpb24udmFsdWUgPT09IHZhbHVlKTtcclxuICB9XHJcblxyXG4gIHVwZGF0ZVBvc2l0aW9uKHNlbGVjdDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLl9oZWFkd2luZFBsYXRmb3JtU2VydmljZS5pc0Jyb3dzZXIgJiYgdGhpcy5fZWxlbWVudFJlZikge1xyXG4gICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xyXG5cclxuICAgICAgdGhpcy5fcmVuZGVyZXIucmVtb3ZlU3R5bGUob3B0aW9ucywgJ3RvcCcpO1xyXG4gICAgICB0aGlzLl9yZW5kZXJlci5yZW1vdmVTdHlsZShvcHRpb25zLCAnYm90dG9tJyk7XHJcblxyXG4gICAgICBjb25zdCBzZWxlY3REb21SZWN0ID0gc2VsZWN0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgICBjb25zdCBvcHRpb25zRG9tUmVjdCA9IG9wdGlvbnMuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XHJcblxyXG4gICAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZShvcHRpb25zLCAnd2lkdGgnLCBzZWxlY3REb21SZWN0LndpZHRoICsgJ3B4Jyk7XHJcbiAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKG9wdGlvbnMsICdsZWZ0Jywgc2VsZWN0RG9tUmVjdC5sZWZ0ICsgJ3B4Jyk7XHJcblxyXG4gICAgICBpZiAodGhpcy5faGVhZHdpbmRXaW5kb3dTZXJ2aWNlLmlzQm90dG9tU3BhY2VBdmFpbGFibGUoc2VsZWN0RG9tUmVjdC5ib3R0b20sIG9wdGlvbnNEb21SZWN0LmhlaWdodCkpIHtcclxuICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZShvcHRpb25zLCAndG9wJywgc2VsZWN0RG9tUmVjdC5ib3R0b20gKyAncHgnKTtcclxuICAgICAgICB0aGlzLl9lbWl0QWN0dWFsRGlyZWN0aW9uQm90dG9tKCk7XHJcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5faGVhZHdpbmRXaW5kb3dTZXJ2aWNlLmlzVG9wU3BhY2VBdmFpbGFibGUoc2VsZWN0RG9tUmVjdC50b3AsIG9wdGlvbnNEb21SZWN0LmhlaWdodCkpIHtcclxuICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZShvcHRpb25zLCAnYm90dG9tJywgYGNhbGMoMTAwJSAtICR7c2VsZWN0RG9tUmVjdC50b3B9cHgpYCk7XHJcbiAgICAgICAgdGhpcy5fZW1pdEFjdHVhbERpcmVjdGlvblRvcCgpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKG9wdGlvbnMsICd0b3AnLCBzZWxlY3REb21SZWN0LmJvdHRvbSArICdweCcpO1xyXG4gICAgICAgIHRoaXMuX2VtaXRBY3R1YWxEaXJlY3Rpb25Cb3R0b20oKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc2Nyb2xsVG9PcHRpb25CeVZhbHVlKHZhbHVlOiBhbnkpOiB2b2lkIHtcclxuICAgIGNvbnN0IG9wdGlvbkluZGV4ID0gdGhpcy5maW5kT3B0aW9uSW5kZXhCeVZhbHVlKHZhbHVlKTtcclxuICAgIGNvbnN0IG9wdGlvbiA9IHRoaXMub3B0aW9uTGlzdD8uZ2V0KG9wdGlvbkluZGV4KTtcclxuICAgIGNvbnN0IGhvc3QgPSB0aGlzLl9lbGVtZW50UmVmPy5uYXRpdmVFbGVtZW50O1xyXG5cclxuICAgIGNvbnN0IG9wdGlvbkRvbVJlY3QgPSBvcHRpb24/LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgY29uc3QgaG9zdERvbVJlY3QgPSBob3N0Py5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuXHJcbiAgICBpZiAoaG9zdCAmJiBvcHRpb25Eb21SZWN0ICYmIGhvc3REb21SZWN0KSB7XHJcbiAgICAgIGNvbnN0IHNjcm9sbFRvcCA9IGhvc3Quc2Nyb2xsVG9wO1xyXG5cclxuICAgICAgaG9zdC5zY3JvbGxUb3AgPVxyXG4gICAgICAgIHNjcm9sbFRvcCArIChvcHRpb25Eb21SZWN0LnkgLSBob3N0RG9tUmVjdC55KSAtIGhvc3REb21SZWN0LmhlaWdodCAvIDIgKyBvcHRpb25Eb21SZWN0LmhlaWdodCAvIDI7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9lbWl0QWN0dWFsRGlyZWN0aW9uVG9wKCk6IHZvaWQge1xyXG4gICAgdGhpcy5hY3R1YWxEaXJlY3Rpb25DaGFuZ2UuZW1pdCgndG9wJyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9lbWl0QWN0dWFsRGlyZWN0aW9uQm90dG9tKCk6IHZvaWQge1xyXG4gICAgdGhpcy5hY3R1YWxEaXJlY3Rpb25DaGFuZ2UuZW1pdCgnYm90dG9tJyk7XHJcbiAgfVxyXG59XHJcbiIsIjxuZy1jb250ZW50PjwvbmctY29udGVudD5cclxuIl19