UNPKG

@favian/headwind-ui

Version:

Headless UI for Angular - Styleless Angular components to integrate with Tailwind CSS

190 lines 30.1 kB
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