UNPKG

@ux-aspects/ux-aspects

Version:

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

77 lines 15.9 kB
import { Component, HostBinding, inject, Input, ViewChild } from '@angular/core'; import { CardTabsService } from '../card-tabs.service'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "../../../directives/resize/resize.directive"; import * as i3 from "../../icon/icon.component"; export class CardTabsetComponent { constructor() { this.tabService = inject(CardTabsService); this.offset = 0; this.bounds = { lower: 0, upper: 0 }; } set position(direction) { this.tabService.setPosition(direction); } get position() { return this.tabService.position$.getValue(); } select(tab, element) { // select the tab this.tabService.select(tab); // ensure the tab is moved into view if required this.moveIntoView(element); } resize(dimensions) { this._width = dimensions.width; this._innerWidth = this.tablist.nativeElement.scrollWidth; this.bounds.lower = 0; this.bounds.upper = -(this._innerWidth - this._width); } previous() { this.offset += this._width; // ensure it remains within the allowed bounds this.offset = Math.min(this.offset, this.bounds.lower); } next() { this.offset -= this._width; // ensure it remains within the allowed bounds this.offset = Math.max(this.offset, this.bounds.upper); } moveIntoView(element) { // if we dont have the dimensions we cant check if (!this._width || !this._innerWidth) { return; } // get the current element bounds const { offsetLeft, offsetWidth } = element; const { marginLeft, marginRight } = getComputedStyle(element); // calculate the visible area const viewportStart = Math.abs(this.offset); const viewportEnd = viewportStart + this._width; const cardWidth = parseFloat(marginLeft) + offsetWidth + parseFloat(marginRight); // if we need to move to the left - figure out how much if (offsetLeft < viewportStart) { this.offset -= (offsetLeft - parseFloat(marginLeft)) - viewportStart; } // if we need to move to the right - figure out how much if ((offsetLeft + cardWidth) > viewportEnd) { this.offset -= (offsetLeft + cardWidth) - viewportEnd; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: CardTabsetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: CardTabsetComponent, selector: "ux-card-tabset", inputs: { position: "position" }, host: { properties: { "class": "this.position" } }, providers: [CardTabsService], viewQueries: [{ propertyName: "tablist", first: true, predicate: ["tablist"], descendants: true, static: true }], ngImport: i0, template: "@if ((tabService.tab$ | async)) {\n <div class=\"card-tab-content\" role=\"tabpanel\">\n <ng-content></ng-content>\n </div>\n}\n\n<div class=\"card-tabs\" #tabs>\n\n @if (offset < bounds.lower) {\n <button type=\"button\" class=\"card-tabs-paging-btn card-tabs-paging-btn-previous\" aria-label=\"Previous Tabs\" (click)=\"previous()\">\n <ux-icon name=\"previous\"></ux-icon>\n </button>\n }\n\n <div class=\"card-tabs-list\" role=\"tablist\" #tablist (uxResize)=\"resize($event)\" [style.transform]=\"'translateX(' + offset + 'px)'\">\n\n @for (tab of tabService.tabs$ | async; track tab) {\n <div class=\"card-tab\"\n role=\"tab\"\n tabindex=\"0\" #card\n [ngClass]=\"tabService.position$ | async\"\n [class.active]=\"tab.active$ | async\"\n [attr.aria-selected]=\"tab.active$ | async\"\n (click)=\"select(tab, card)\"\n (focus)=\"tabs.scrollLeft = 0\"\n (keydown.enter)=\"select(tab, card)\">\n <ng-container [ngTemplateOutlet]=\"tab.content\"></ng-container>\n </div>\n }\n\n </div>\n\n @if (offset > bounds.upper) {\n <button type=\"button\" class=\"card-tabs-paging-btn card-tabs-paging-btn-next\" aria-label=\"Next Tabs\" (click)=\"next()\">\n <ux-icon name=\"next\"></ux-icon>\n </button>\n }\n</div>", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.ResizeDirective, selector: "[uxResize]", inputs: ["throttle"], outputs: ["uxResize"] }, { kind: "component", type: i3.IconComponent, selector: "ux-icon", inputs: ["name", "size", "rotate", "flipHorizontal", "flipVertical"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: CardTabsetComponent, decorators: [{ type: Component, args: [{ selector: 'ux-card-tabset', providers: [CardTabsService], template: "@if ((tabService.tab$ | async)) {\n <div class=\"card-tab-content\" role=\"tabpanel\">\n <ng-content></ng-content>\n </div>\n}\n\n<div class=\"card-tabs\" #tabs>\n\n @if (offset < bounds.lower) {\n <button type=\"button\" class=\"card-tabs-paging-btn card-tabs-paging-btn-previous\" aria-label=\"Previous Tabs\" (click)=\"previous()\">\n <ux-icon name=\"previous\"></ux-icon>\n </button>\n }\n\n <div class=\"card-tabs-list\" role=\"tablist\" #tablist (uxResize)=\"resize($event)\" [style.transform]=\"'translateX(' + offset + 'px)'\">\n\n @for (tab of tabService.tabs$ | async; track tab) {\n <div class=\"card-tab\"\n role=\"tab\"\n tabindex=\"0\" #card\n [ngClass]=\"tabService.position$ | async\"\n [class.active]=\"tab.active$ | async\"\n [attr.aria-selected]=\"tab.active$ | async\"\n (click)=\"select(tab, card)\"\n (focus)=\"tabs.scrollLeft = 0\"\n (keydown.enter)=\"select(tab, card)\">\n <ng-container [ngTemplateOutlet]=\"tab.content\"></ng-container>\n </div>\n }\n\n </div>\n\n @if (offset > bounds.upper) {\n <button type=\"button\" class=\"card-tabs-paging-btn card-tabs-paging-btn-next\" aria-label=\"Next Tabs\" (click)=\"next()\">\n <ux-icon name=\"next\"></ux-icon>\n </button>\n }\n</div>" }] }], propDecorators: { position: [{ type: HostBinding, args: ['class'] }, { type: Input }], tablist: [{ type: ViewChild, args: ['tablist', { static: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FyZC10YWJzZXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvY2FyZC10YWJzL2NhcmQtdGFic2V0L2NhcmQtdGFic2V0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL2NhcmQtdGFicy9jYXJkLXRhYnNldC9jYXJkLXRhYnNldC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFjLFdBQVcsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUc3RixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7Ozs7O0FBT3ZELE1BQU0sT0FBTyxtQkFBbUI7SUFMaEM7UUFPSSxlQUFVLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBYXJDLFdBQU0sR0FBVyxDQUFDLENBQUM7UUFDbkIsV0FBTSxHQUFtQixFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDO0tBNkRuRDtJQXpFRyxJQUNhLFFBQVEsQ0FBQyxTQUFpQjtRQUNuQyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQsSUFBSSxRQUFRO1FBQ1IsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNoRCxDQUFDO0lBVUQsTUFBTSxDQUFDLEdBQXFCLEVBQUUsT0FBb0I7UUFDOUMsaUJBQWlCO1FBQ2pCLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRTVCLGdEQUFnRDtRQUNoRCxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFRCxNQUFNLENBQUMsVUFBNEI7UUFDL0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDO1FBQy9CLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDO1FBRTFELElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztRQUN0QixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVELFFBQVE7UUFDSixJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUM7UUFFM0IsOENBQThDO1FBQzlDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVELElBQUk7UUFDQSxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUM7UUFFM0IsOENBQThDO1FBQzlDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVPLFlBQVksQ0FBQyxPQUFvQjtRQUVyQywrQ0FBK0M7UUFDL0MsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDcEMsT0FBTztRQUNYLENBQUM7UUFFRCxpQ0FBaUM7UUFDakMsTUFBTSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFDNUMsTUFBTSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUU5RCw2QkFBNkI7UUFDN0IsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDNUMsTUFBTSxXQUFXLEdBQUcsYUFBYSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDaEQsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLFVBQVUsQ0FBQyxHQUFHLFdBQVcsR0FBRyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFakYsdURBQXVEO1FBQ3ZELElBQUksVUFBVSxHQUFHLGFBQWEsRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEdBQUcsYUFBYSxDQUFDO1FBQ3pFLENBQUM7UUFFRCx3REFBd0Q7UUFDeEQsSUFBSSxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUMsR0FBRyxXQUFXLEVBQUUsQ0FBQztZQUN6QyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQyxHQUFHLFdBQVcsQ0FBQztRQUMxRCxDQUFDO0lBQ0wsQ0FBQzsrR0E1RVEsbUJBQW1CO21HQUFuQixtQkFBbUIsK0hBRmpCLENBQUMsZUFBZSxDQUFDLDRJQ1JoQywweUNBcUNNOzs0RkQzQk8sbUJBQW1CO2tCQUwvQixTQUFTOytCQUNJLGdCQUFnQixhQUVmLENBQUMsZUFBZSxDQUFDOzhCQU9mLFFBQVE7c0JBRHBCLFdBQVc7dUJBQUMsT0FBTzs7c0JBQ25CLEtBQUs7Z0JBUWtDLE9BQU87c0JBQTlDLFNBQVM7dUJBQUMsU0FBUyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgSG9zdEJpbmRpbmcsIGluamVjdCwgSW5wdXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUmVzaXplRGltZW5zaW9ucyB9IGZyb20gJy4uLy4uLy4uL2RpcmVjdGl2ZXMvcmVzaXplJztcbmltcG9ydCB7IENhcmRUYWJDb21wb25lbnQgfSBmcm9tICcuLi9jYXJkLXRhYi9jYXJkLXRhYi5jb21wb25lbnQnO1xuaW1wb3J0IHsgQ2FyZFRhYnNTZXJ2aWNlIH0gZnJvbSAnLi4vY2FyZC10YWJzLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ3V4LWNhcmQtdGFic2V0JyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vY2FyZC10YWJzZXQuY29tcG9uZW50Lmh0bWwnLFxuICAgIHByb3ZpZGVyczogW0NhcmRUYWJzU2VydmljZV1cbn0pXG5leHBvcnQgY2xhc3MgQ2FyZFRhYnNldENvbXBvbmVudCB7XG5cbiAgICB0YWJTZXJ2aWNlID0gaW5qZWN0KENhcmRUYWJzU2VydmljZSk7XG5cbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzJylcbiAgICBASW5wdXQoKSBzZXQgcG9zaXRpb24oZGlyZWN0aW9uOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy50YWJTZXJ2aWNlLnNldFBvc2l0aW9uKGRpcmVjdGlvbik7XG4gICAgfVxuXG4gICAgZ2V0IHBvc2l0aW9uKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLnRhYlNlcnZpY2UucG9zaXRpb24kLmdldFZhbHVlKCk7XG4gICAgfVxuXG4gICAgQFZpZXdDaGlsZCgndGFibGlzdCcsIHsgc3RhdGljOiB0cnVlIH0pIHRhYmxpc3Q6IEVsZW1lbnRSZWY7XG5cbiAgICBvZmZzZXQ6IG51bWJlciA9IDA7XG4gICAgYm91bmRzOiBDYXJkVGFic0JvdW5kcyA9IHsgbG93ZXI6IDAsIHVwcGVyOiAwIH07XG5cbiAgICBwcml2YXRlIF93aWR0aDogbnVtYmVyO1xuICAgIHByaXZhdGUgX2lubmVyV2lkdGg6IG51bWJlcjtcblxuICAgIHNlbGVjdCh0YWI6IENhcmRUYWJDb21wb25lbnQsIGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG4gICAgICAgIC8vIHNlbGVjdCB0aGUgdGFiXG4gICAgICAgIHRoaXMudGFiU2VydmljZS5zZWxlY3QodGFiKTtcblxuICAgICAgICAvLyBlbnN1cmUgdGhlIHRhYiBpcyBtb3ZlZCBpbnRvIHZpZXcgaWYgcmVxdWlyZWRcbiAgICAgICAgdGhpcy5tb3ZlSW50b1ZpZXcoZWxlbWVudCk7XG4gICAgfVxuXG4gICAgcmVzaXplKGRpbWVuc2lvbnM6IFJlc2l6ZURpbWVuc2lvbnMpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fd2lkdGggPSBkaW1lbnNpb25zLndpZHRoO1xuICAgICAgICB0aGlzLl9pbm5lcldpZHRoID0gdGhpcy50YWJsaXN0Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsV2lkdGg7XG5cbiAgICAgICAgdGhpcy5ib3VuZHMubG93ZXIgPSAwO1xuICAgICAgICB0aGlzLmJvdW5kcy51cHBlciA9IC0odGhpcy5faW5uZXJXaWR0aCAtIHRoaXMuX3dpZHRoKTtcbiAgICB9XG5cbiAgICBwcmV2aW91cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5vZmZzZXQgKz0gdGhpcy5fd2lkdGg7XG5cbiAgICAgICAgLy8gZW5zdXJlIGl0IHJlbWFpbnMgd2l0aGluIHRoZSBhbGxvd2VkIGJvdW5kc1xuICAgICAgICB0aGlzLm9mZnNldCA9IE1hdGgubWluKHRoaXMub2Zmc2V0LCB0aGlzLmJvdW5kcy5sb3dlcik7XG4gICAgfVxuXG4gICAgbmV4dCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5vZmZzZXQgLT0gdGhpcy5fd2lkdGg7XG5cbiAgICAgICAgLy8gZW5zdXJlIGl0IHJlbWFpbnMgd2l0aGluIHRoZSBhbGxvd2VkIGJvdW5kc1xuICAgICAgICB0aGlzLm9mZnNldCA9IE1hdGgubWF4KHRoaXMub2Zmc2V0LCB0aGlzLmJvdW5kcy51cHBlcik7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtb3ZlSW50b1ZpZXcoZWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICAvLyBpZiB3ZSBkb250IGhhdmUgdGhlIGRpbWVuc2lvbnMgd2UgY2FudCBjaGVja1xuICAgICAgICBpZiAoIXRoaXMuX3dpZHRoIHx8ICF0aGlzLl9pbm5lcldpZHRoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBnZXQgdGhlIGN1cnJlbnQgZWxlbWVudCBib3VuZHNcbiAgICAgICAgY29uc3QgeyBvZmZzZXRMZWZ0LCBvZmZzZXRXaWR0aCB9ID0gZWxlbWVudDtcbiAgICAgICAgY29uc3QgeyBtYXJnaW5MZWZ0LCBtYXJnaW5SaWdodCB9ID0gZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KTtcblxuICAgICAgICAvLyBjYWxjdWxhdGUgdGhlIHZpc2libGUgYXJlYVxuICAgICAgICBjb25zdCB2aWV3cG9ydFN0YXJ0ID0gTWF0aC5hYnModGhpcy5vZmZzZXQpO1xuICAgICAgICBjb25zdCB2aWV3cG9ydEVuZCA9IHZpZXdwb3J0U3RhcnQgKyB0aGlzLl93aWR0aDtcbiAgICAgICAgY29uc3QgY2FyZFdpZHRoID0gcGFyc2VGbG9hdChtYXJnaW5MZWZ0KSArIG9mZnNldFdpZHRoICsgcGFyc2VGbG9hdChtYXJnaW5SaWdodCk7XG5cbiAgICAgICAgLy8gaWYgd2UgbmVlZCB0byBtb3ZlIHRvIHRoZSBsZWZ0IC0gZmlndXJlIG91dCBob3cgbXVjaFxuICAgICAgICBpZiAob2Zmc2V0TGVmdCA8IHZpZXdwb3J0U3RhcnQpIHtcbiAgICAgICAgICAgIHRoaXMub2Zmc2V0IC09IChvZmZzZXRMZWZ0IC0gcGFyc2VGbG9hdChtYXJnaW5MZWZ0KSkgLSB2aWV3cG9ydFN0YXJ0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaWYgd2UgbmVlZCB0byBtb3ZlIHRvIHRoZSByaWdodCAtIGZpZ3VyZSBvdXQgaG93IG11Y2hcbiAgICAgICAgaWYgKChvZmZzZXRMZWZ0ICsgY2FyZFdpZHRoKSA+IHZpZXdwb3J0RW5kKSB7XG4gICAgICAgICAgICB0aGlzLm9mZnNldCAtPSAob2Zmc2V0TGVmdCArIGNhcmRXaWR0aCkgLSB2aWV3cG9ydEVuZDtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBDYXJkVGFic0JvdW5kcyB7XG4gICAgbG93ZXI6IG51bWJlcjtcbiAgICB1cHBlcjogbnVtYmVyO1xufVxuIiwiQGlmICgodGFiU2VydmljZS50YWIkIHwgYXN5bmMpKSB7XG4gIDxkaXYgY2xhc3M9XCJjYXJkLXRhYi1jb250ZW50XCIgcm9sZT1cInRhYnBhbmVsXCI+XG4gICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICA8L2Rpdj5cbn1cblxuPGRpdiBjbGFzcz1cImNhcmQtdGFic1wiICN0YWJzPlxuXG4gIEBpZiAob2Zmc2V0IDwgYm91bmRzLmxvd2VyKSB7XG4gICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJjYXJkLXRhYnMtcGFnaW5nLWJ0biBjYXJkLXRhYnMtcGFnaW5nLWJ0bi1wcmV2aW91c1wiIGFyaWEtbGFiZWw9XCJQcmV2aW91cyBUYWJzXCIgKGNsaWNrKT1cInByZXZpb3VzKClcIj5cbiAgICAgIDx1eC1pY29uIG5hbWU9XCJwcmV2aW91c1wiPjwvdXgtaWNvbj5cbiAgICA8L2J1dHRvbj5cbiAgfVxuXG4gIDxkaXYgY2xhc3M9XCJjYXJkLXRhYnMtbGlzdFwiIHJvbGU9XCJ0YWJsaXN0XCIgI3RhYmxpc3QgKHV4UmVzaXplKT1cInJlc2l6ZSgkZXZlbnQpXCIgW3N0eWxlLnRyYW5zZm9ybV09XCIndHJhbnNsYXRlWCgnICsgb2Zmc2V0ICsgJ3B4KSdcIj5cblxuICAgIEBmb3IgKHRhYiBvZiB0YWJTZXJ2aWNlLnRhYnMkIHwgYXN5bmM7IHRyYWNrIHRhYikge1xuICAgICAgPGRpdiBjbGFzcz1cImNhcmQtdGFiXCJcbiAgICAgICAgcm9sZT1cInRhYlwiXG4gICAgICAgIHRhYmluZGV4PVwiMFwiICNjYXJkXG4gICAgICAgIFtuZ0NsYXNzXT1cInRhYlNlcnZpY2UucG9zaXRpb24kIHwgYXN5bmNcIlxuICAgICAgICBbY2xhc3MuYWN0aXZlXT1cInRhYi5hY3RpdmUkIHwgYXN5bmNcIlxuICAgICAgICBbYXR0ci5hcmlhLXNlbGVjdGVkXT1cInRhYi5hY3RpdmUkIHwgYXN5bmNcIlxuICAgICAgICAoY2xpY2spPVwic2VsZWN0KHRhYiwgY2FyZClcIlxuICAgICAgICAoZm9jdXMpPVwidGFicy5zY3JvbGxMZWZ0ID0gMFwiXG4gICAgICAgIChrZXlkb3duLmVudGVyKT1cInNlbGVjdCh0YWIsIGNhcmQpXCI+XG4gICAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwidGFiLmNvbnRlbnRcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvZGl2PlxuICAgIH1cblxuICA8L2Rpdj5cblxuICBAaWYgKG9mZnNldCA+IGJvdW5kcy51cHBlcikge1xuICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiY2FyZC10YWJzLXBhZ2luZy1idG4gY2FyZC10YWJzLXBhZ2luZy1idG4tbmV4dFwiIGFyaWEtbGFiZWw9XCJOZXh0IFRhYnNcIiAoY2xpY2spPVwibmV4dCgpXCI+XG4gICAgICA8dXgtaWNvbiBuYW1lPVwibmV4dFwiPjwvdXgtaWNvbj5cbiAgICA8L2J1dHRvbj5cbiAgfVxuPC9kaXY+Il19