design-angular-kit
Version:
Un toolkit Angular conforme alle linee guida di design per i servizi web della PA
116 lines • 29.3 kB
JavaScript
import { AsyncPipe, NgClass, NgTemplateOutlet, ViewportScroller } from '@angular/common';
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, HostListener, inject, Input, ViewChild, } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { RouterLink, RouterLinkActive, RouterLinkWithHref } from '@angular/router';
import { delay, filter, map, tap, withLatestFrom } from 'rxjs';
import { ItNavscrollListItemsComponent } from './navscroll-list-items.component';
import { NavscrollStore } from './navscroll.store';
import * as i0 from "@angular/core";
/**
* Navscroll
* @description Show a list of links to anchor of the document.
*/
export class ItNavscrollComponent {
onScroll() {
const sectionContainer = this.#elementRef.nativeElement.querySelector('.it-page-sections-container');
this.#store.updateProgressBar(sectionContainer);
}
onResize() {
this.#setMobile();
}
#store;
#scroller;
#destroyRef;
#elementRef;
constructor() {
/**
* Header of the Navscroll
*/
this.header = '';
/**
* Border position
* @default left
*/
this.borderPosition = 'left';
/**
* Alignment
* @default top
*/
this.alignment = 'top';
/**
* Theme
* @default light
*/
this.theme = 'light';
this.#store = inject(NavscrollStore);
this.#scroller = inject(ViewportScroller);
this.#destroyRef = inject(DestroyRef);
this.#elementRef = inject(ElementRef);
this.selectedTitle = this.#store.selected.pipe(map(selected => selected?.title ?? ''));
this.progressBarValue = this.#store.progressBar;
this.isMobile = this.#store.isMobile;
this.#store.menuItemSelected
.pipe(takeUntilDestroyed(), withLatestFrom(this.isMobile), tap(v => {
const isMobile = v[1];
if (isMobile) {
this.toggleButtonRef.nativeElement.click();
}
}))
.subscribe();
}
ngOnInit() {
this.#initViewScrollerSubscription();
this.#store.init(this.items);
this.#setMobile();
}
#initViewScrollerSubscription() {
this.#store.selected
.pipe(takeUntilDestroyed(this.#destroyRef), filter(selected => Boolean(selected)), map(v => v), delay(0), //WA
tap({
next: ({ href }) => {
this.#scroller.scrollToAnchor(href);
},
}))
.subscribe();
}
#setMobile() {
this.#store.setMobile(window);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: ItNavscrollComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.6", type: ItNavscrollComponent, isStandalone: true, selector: "it-navscroll", inputs: { header: "header", items: "items", borderPosition: "borderPosition", alignment: "alignment", theme: "theme", pageSectionsTemplate: "pageSectionsTemplate" }, host: { listeners: { "window:scroll": "onScroll($event)", "window:resize": "onResize($event)" } }, providers: [NavscrollStore], viewQueries: [{ propertyName: "toggleButtonRef", first: true, predicate: ["toggleButtonRef"], descendants: true }], ngImport: i0, template: "<div class=\"container py-lg-5\">\n <div class=\"row\">\n <div class=\"col-12 col-lg-4\">\n <div class=\"it-navscroll-sticky\" [ngClass]=\"{ 'it-navscroll-sticky-mobile': isMobile | async }\" data-bs-stackable=\"true\">\n <nav\n class=\"navbar it-navscroll-wrapper navbar-expand-lg\"\n [class.it-top-navscroll]=\"alignment === 'top'\"\n [class.it-bottom-navscroll]=\"alignment === 'bottom'\"\n [class.it-left-side]=\"borderPosition === 'left'\"\n [class.it-right-side]=\"borderPosition === 'right'\"\n [class.theme-dark-mobile]=\"theme === 'dark'\"\n [class.theme-dark-desktop]=\"theme === 'dark'\">\n <button\n class=\"custom-navbar-toggler\"\n type=\"button\"\n aria-controls=\"navbarNav\"\n aria-expanded=\"false\"\n aria-label=\"Toggle navigation\"\n data-bs-toggle=\"navbarcollapsible\"\n data-bs-target=\"#navbarNav\"\n #toggleButtonRef>\n <span class=\"it-list\"></span>{{ selectedTitle | async }}\n </button>\n <div class=\"progress custom-navbar-progressbar\">\n <div\n class=\"progress-bar it-navscroll-progressbar\"\n role=\"progressbar\"\n [style.width.%]=\"progressBarValue | async\"\n [attr.aria-valuenow]=\"progressBarValue | async\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"></div>\n </div>\n <div class=\"navbar-collapsable\" id=\"navbarNav\">\n <div class=\"overlay\"></div>\n <div class=\"close-div visually-hidden\">\n <button class=\"btn close-menu\" type=\"button\"><span class=\"it-close\"></span>Chiudi</button>\n </div>\n <button type=\"button\" class=\"it-back-button btn w-100 text-start\">\n <svg class=\"icon icon-sm icon-primary align-top\">\n <use\n href=\"/bootstrap-italia/dist/svg/sprites.svg#it-chevron-left\"\n xlink:href=\"/bootstrap-italia/dist/svg/sprites.svg#it-chevron-left\"></use>\n </svg>\n <span>Indietro</span>\n </button>\n <div class=\"menu-wrapper\">\n <div class=\"link-list-wrapper\">\n <h3>{{ header }}</h3>\n <div class=\"progress\">\n <div\n class=\"progress-bar it-navscroll-progressbar\"\n role=\"progressbar\"\n [style.width.%]=\"progressBarValue | async\"\n [attr.aria-valuenow]=\"progressBarValue | async\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"></div>\n </div>\n <it-navscroll-list-items [items]=\"items\"></it-navscroll-list-items>\n </div>\n </div>\n </div>\n </nav>\n </div>\n </div>\n <div class=\"col-12 col-lg-8 it-page-sections-container\">\n <ng-container\n *ngTemplateOutlet=\"pageSectionsTemplate ? pageSectionsTemplate : defaultPageSectionsTemplate; context: { items: items }\">\n </ng-container>\n </div>\n </div>\n</div>\n\n<ng-template #defaultPageSectionsTemplate let-items=\"items\">\n @for (item of items; track item.href) {\n <ng-container *ngTemplateOutlet=\"paragraphTemplate; context: { item: item, level: 1 }\"></ng-container>\n }\n</ng-template>\n\n<ng-template #paragraphTemplate let-item=\"item\" let-level=\"level\" let-nextLevel=\"level+1\">\n @switch (level) {\n @case (1) {\n <h2 class=\"it-page-section\" id=\"{{ item.href }}\">{{ item.title }}</h2>\n }\n @case (2) {\n <h3 class=\"it-page-section\" id=\"{{ item.href }}\">{{ item.title }}</h3>\n }\n @case (3) {\n <h4 class=\"it-page-section\" id=\"{{ item.href }}\">{{ item.title }}</h4>\n }\n @case (4) {\n <h5 class=\"it-page-section\" id=\"{{ item.href }}\">{{ item.title }}</h5>\n }\n @default {\n <h6 class=\"it-page-section\" id=\"{{ item.href }}\">{{ item.title }}</h6>\n }\n }\n <p>{{ item.text }}</p>\n @for (item of item.childs; track item.href) {\n <ng-container *ngTemplateOutlet=\"paragraphTemplate; context: { item: item, level: nextLevel }\"></ng-container>\n }\n</ng-template>\n", styles: [".it-navscroll-sticky{position:sticky;top:0}.it-navscroll-sticky-mobile{z-index:1020}\n"], dependencies: [{ kind: "component", type: ItNavscrollListItemsComponent, selector: "it-navscroll-list-items", inputs: ["items"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: ItNavscrollComponent, decorators: [{
type: Component,
args: [{ selector: 'it-navscroll', standalone: true, imports: [
ItNavscrollListItemsComponent,
AsyncPipe,
NgTemplateOutlet,
RouterLink,
RouterLinkActive,
RouterLinkWithHref,
AsyncPipe,
NgClass,
], changeDetection: ChangeDetectionStrategy.OnPush, providers: [NavscrollStore], template: "<div class=\"container py-lg-5\">\n <div class=\"row\">\n <div class=\"col-12 col-lg-4\">\n <div class=\"it-navscroll-sticky\" [ngClass]=\"{ 'it-navscroll-sticky-mobile': isMobile | async }\" data-bs-stackable=\"true\">\n <nav\n class=\"navbar it-navscroll-wrapper navbar-expand-lg\"\n [class.it-top-navscroll]=\"alignment === 'top'\"\n [class.it-bottom-navscroll]=\"alignment === 'bottom'\"\n [class.it-left-side]=\"borderPosition === 'left'\"\n [class.it-right-side]=\"borderPosition === 'right'\"\n [class.theme-dark-mobile]=\"theme === 'dark'\"\n [class.theme-dark-desktop]=\"theme === 'dark'\">\n <button\n class=\"custom-navbar-toggler\"\n type=\"button\"\n aria-controls=\"navbarNav\"\n aria-expanded=\"false\"\n aria-label=\"Toggle navigation\"\n data-bs-toggle=\"navbarcollapsible\"\n data-bs-target=\"#navbarNav\"\n #toggleButtonRef>\n <span class=\"it-list\"></span>{{ selectedTitle | async }}\n </button>\n <div class=\"progress custom-navbar-progressbar\">\n <div\n class=\"progress-bar it-navscroll-progressbar\"\n role=\"progressbar\"\n [style.width.%]=\"progressBarValue | async\"\n [attr.aria-valuenow]=\"progressBarValue | async\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"></div>\n </div>\n <div class=\"navbar-collapsable\" id=\"navbarNav\">\n <div class=\"overlay\"></div>\n <div class=\"close-div visually-hidden\">\n <button class=\"btn close-menu\" type=\"button\"><span class=\"it-close\"></span>Chiudi</button>\n </div>\n <button type=\"button\" class=\"it-back-button btn w-100 text-start\">\n <svg class=\"icon icon-sm icon-primary align-top\">\n <use\n href=\"/bootstrap-italia/dist/svg/sprites.svg#it-chevron-left\"\n xlink:href=\"/bootstrap-italia/dist/svg/sprites.svg#it-chevron-left\"></use>\n </svg>\n <span>Indietro</span>\n </button>\n <div class=\"menu-wrapper\">\n <div class=\"link-list-wrapper\">\n <h3>{{ header }}</h3>\n <div class=\"progress\">\n <div\n class=\"progress-bar it-navscroll-progressbar\"\n role=\"progressbar\"\n [style.width.%]=\"progressBarValue | async\"\n [attr.aria-valuenow]=\"progressBarValue | async\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"></div>\n </div>\n <it-navscroll-list-items [items]=\"items\"></it-navscroll-list-items>\n </div>\n </div>\n </div>\n </nav>\n </div>\n </div>\n <div class=\"col-12 col-lg-8 it-page-sections-container\">\n <ng-container\n *ngTemplateOutlet=\"pageSectionsTemplate ? pageSectionsTemplate : defaultPageSectionsTemplate; context: { items: items }\">\n </ng-container>\n </div>\n </div>\n</div>\n\n<ng-template #defaultPageSectionsTemplate let-items=\"items\">\n @for (item of items; track item.href) {\n <ng-container *ngTemplateOutlet=\"paragraphTemplate; context: { item: item, level: 1 }\"></ng-container>\n }\n</ng-template>\n\n<ng-template #paragraphTemplate let-item=\"item\" let-level=\"level\" let-nextLevel=\"level+1\">\n @switch (level) {\n @case (1) {\n <h2 class=\"it-page-section\" id=\"{{ item.href }}\">{{ item.title }}</h2>\n }\n @case (2) {\n <h3 class=\"it-page-section\" id=\"{{ item.href }}\">{{ item.title }}</h3>\n }\n @case (3) {\n <h4 class=\"it-page-section\" id=\"{{ item.href }}\">{{ item.title }}</h4>\n }\n @case (4) {\n <h5 class=\"it-page-section\" id=\"{{ item.href }}\">{{ item.title }}</h5>\n }\n @default {\n <h6 class=\"it-page-section\" id=\"{{ item.href }}\">{{ item.title }}</h6>\n }\n }\n <p>{{ item.text }}</p>\n @for (item of item.childs; track item.href) {\n <ng-container *ngTemplateOutlet=\"paragraphTemplate; context: { item: item, level: nextLevel }\"></ng-container>\n }\n</ng-template>\n", styles: [".it-navscroll-sticky{position:sticky;top:0}.it-navscroll-sticky-mobile{z-index:1020}\n"] }]
}], ctorParameters: () => [], propDecorators: { header: [{
type: Input
}], items: [{
type: Input
}], borderPosition: [{
type: Input
}], alignment: [{
type: Input
}], theme: [{
type: Input
}], pageSectionsTemplate: [{
type: Input
}], onScroll: [{
type: HostListener,
args: ['window:scroll', ['$event']]
}], onResize: [{
type: HostListener,
args: ['window:resize', ['$event']]
}], toggleButtonRef: [{
type: ViewChild,
args: ['toggleButtonRef']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF2c2Nyb2xsLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Rlc2lnbi1hbmd1bGFyLWtpdC9zcmMvbGliL2NvbXBvbmVudHMvbmF2aWdhdGlvbi9uYXZzY3JvbGwvbmF2c2Nyb2xsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Rlc2lnbi1hbmd1bGFyLWtpdC9zcmMvbGliL2NvbXBvbmVudHMvbmF2aWdhdGlvbi9uYXZzY3JvbGwvbmF2c2Nyb2xsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDekYsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsVUFBVSxFQUNWLFVBQVUsRUFDVixZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFHTCxTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDaEUsT0FBTyxFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ25GLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsY0FBYyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9ELE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBRWpGLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7QUFFbkQ7OztHQUdHO0FBbUJILE1BQU0sT0FBTyxvQkFBb0I7SUFpQy9CLFFBQVE7UUFDTixNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1FBQ3JHLElBQUksQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBR0QsUUFBUTtRQUNOLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNwQixDQUFDO0lBS1EsTUFBTSxDQUEwQjtJQUVoQyxTQUFTLENBQTRCO0lBRXJDLFdBQVcsQ0FBc0I7SUFFakMsV0FBVyxDQUFzQjtJQVExQztRQTNEQTs7V0FFRztRQUNNLFdBQU0sR0FBRyxFQUFFLENBQUM7UUFLckI7OztXQUdHO1FBQ00sbUJBQWMsR0FBcUIsTUFBTSxDQUFDO1FBQ25EOzs7V0FHRztRQUNNLGNBQVMsR0FBcUIsS0FBSyxDQUFDO1FBRTdDOzs7V0FHRztRQUNNLFVBQUssR0FBcUIsT0FBTyxDQUFDO1FBc0JsQyxXQUFNLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBRWhDLGNBQVMsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUVyQyxnQkFBVyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUVqQyxnQkFBVyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUVqQyxrQkFBYSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFbEYscUJBQWdCLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUM7UUFFM0MsYUFBUSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDO1FBR3ZDLElBQUksQ0FBQyxNQUFNLENBQUMsZ0JBQWdCO2FBQ3pCLElBQUksQ0FDSCxrQkFBa0IsRUFBRSxFQUNwQixjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUM3QixHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDTixNQUFNLFFBQVEsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdEIsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDYixJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUM3QyxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQ0g7YUFDQSxTQUFTLEVBQUUsQ0FBQztJQUNqQixDQUFDO0lBRUQsUUFBUTtRQUNOLElBQUksQ0FBQyw2QkFBNkIsRUFBRSxDQUFDO1FBQ3JDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVELDZCQUE2QjtRQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVE7YUFDakIsSUFBSSxDQUNILGtCQUFrQixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsRUFDcEMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQ3JDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQWtCLENBQUMsRUFDNUIsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUk7UUFDZCxHQUFHLENBQUM7WUFDRixJQUFJLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUU7Z0JBQ2pCLElBQUksQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3RDLENBQUM7U0FDRixDQUFDLENBQ0g7YUFDQSxTQUFTLEVBQUUsQ0FBQztJQUNqQixDQUFDO0lBRUQsVUFBVTtRQUNSLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2hDLENBQUM7OEdBbkdVLG9CQUFvQjtrR0FBcEIsb0JBQW9CLG9VQUZwQixDQUFDLGNBQWMsQ0FBQyw4SUN4QzdCLG94SUFxR0EsZ0pEekVJLDZCQUE2QixrRkFDN0IsU0FBUyw4Q0FDVCxnQkFBZ0Isb0pBS2hCLE9BQU87OzJGQU9FLG9CQUFvQjtrQkFsQmhDLFNBQVM7K0JBQ0UsY0FBYyxjQUNaLElBQUksV0FDUDt3QkFDUCw2QkFBNkI7d0JBQzdCLFNBQVM7d0JBQ1QsZ0JBQWdCO3dCQUNoQixVQUFVO3dCQUNWLGdCQUFnQjt3QkFDaEIsa0JBQWtCO3dCQUNsQixTQUFTO3dCQUNULE9BQU87cUJBQ1IsbUJBR2dCLHVCQUF1QixDQUFDLE1BQU0sYUFDcEMsQ0FBQyxjQUFjLENBQUM7d0RBTWxCLE1BQU07c0JBQWQsS0FBSztnQkFJRyxLQUFLO3NCQUFiLEtBQUs7Z0JBS0csY0FBYztzQkFBdEIsS0FBSztnQkFLRyxTQUFTO3NCQUFqQixLQUFLO2dCQU1HLEtBQUs7c0JBQWIsS0FBSztnQkFNTixvQkFBb0I7c0JBRG5CLEtBQUs7Z0JBSU4sUUFBUTtzQkFEUCxZQUFZO3VCQUFDLGVBQWUsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFPekMsUUFBUTtzQkFEUCxZQUFZO3VCQUFDLGVBQWUsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFNaEMsZUFBZTtzQkFEdkIsU0FBUzt1QkFBQyxpQkFBaUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBc3luY1BpcGUsIE5nQ2xhc3MsIE5nVGVtcGxhdGVPdXRsZXQsIFZpZXdwb3J0U2Nyb2xsZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRGVzdHJveVJlZixcbiAgRWxlbWVudFJlZixcbiAgSG9zdExpc3RlbmVyLFxuICBpbmplY3QsXG4gIElucHV0LFxuICBPbkluaXQsXG4gIFRlbXBsYXRlUmVmLFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgUm91dGVyTGluaywgUm91dGVyTGlua0FjdGl2ZSwgUm91dGVyTGlua1dpdGhIcmVmIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IGRlbGF5LCBmaWx0ZXIsIG1hcCwgdGFwLCB3aXRoTGF0ZXN0RnJvbSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgSXROYXZzY3JvbGxMaXN0SXRlbXNDb21wb25lbnQgfSBmcm9tICcuL25hdnNjcm9sbC1saXN0LWl0ZW1zLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBOYXZzY3JvbGxJdGVtIH0gZnJvbSAnLi9uYXZzY3JvbGwubW9kZWwnO1xuaW1wb3J0IHsgTmF2c2Nyb2xsU3RvcmUgfSBmcm9tICcuL25hdnNjcm9sbC5zdG9yZSc7XG5cbi8qKlxuICogTmF2c2Nyb2xsXG4gKiBAZGVzY3JpcHRpb24gU2hvdyBhIGxpc3Qgb2YgbGlua3MgdG8gYW5jaG9yIG9mIHRoZSBkb2N1bWVudC5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnaXQtbmF2c2Nyb2xsJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIEl0TmF2c2Nyb2xsTGlzdEl0ZW1zQ29tcG9uZW50LFxuICAgIEFzeW5jUGlwZSxcbiAgICBOZ1RlbXBsYXRlT3V0bGV0LFxuICAgIFJvdXRlckxpbmssXG4gICAgUm91dGVyTGlua0FjdGl2ZSxcbiAgICBSb3V0ZXJMaW5rV2l0aEhyZWYsXG4gICAgQXN5bmNQaXBlLFxuICAgIE5nQ2xhc3MsXG4gIF0sXG4gIHRlbXBsYXRlVXJsOiAnLi9uYXZzY3JvbGwuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vbmF2c2Nyb2xsLmNvbXBvbmVudC5zY3NzJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHByb3ZpZGVyczogW05hdnNjcm9sbFN0b3JlXSxcbn0pXG5leHBvcnQgY2xhc3MgSXROYXZzY3JvbGxDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICAvKipcbiAgICogSGVhZGVyIG9mIHRoZSBOYXZzY3JvbGxcbiAgICovXG4gIEBJbnB1dCgpIGhlYWRlciA9ICcnO1xuICAvKipcbiAgICogQSBsaXN0IG9mIGxpbmtzXG4gICAqL1xuICBASW5wdXQoKSBpdGVtcyE6IEFycmF5PE5hdnNjcm9sbEl0ZW0+O1xuICAvKipcbiAgICogQm9yZGVyIHBvc2l0aW9uXG4gICAqIEBkZWZhdWx0IGxlZnRcbiAgICovXG4gIEBJbnB1dCgpIGJvcmRlclBvc2l0aW9uOiAnbGVmdCcgfCAncmlnaHQnID0gJ2xlZnQnO1xuICAvKipcbiAgICogQWxpZ25tZW50XG4gICAqIEBkZWZhdWx0IHRvcFxuICAgKi9cbiAgQElucHV0KCkgYWxpZ25tZW50OiAndG9wJyB8ICdib3R0b20nID0gJ3RvcCc7XG5cbiAgLyoqXG4gICAqIFRoZW1lXG4gICAqIEBkZWZhdWx0IGxpZ2h0XG4gICAqL1xuICBASW5wdXQoKSB0aGVtZTogJ2xpZ2h0JyB8ICdkYXJrJyA9ICdsaWdodCc7XG5cbiAgLyoqXG4gICAqIEN1c3RvbSB0ZW1wbGF0ZSBmb3IgdGhlIGNvbnRlbnQgc2VjdGlvblxuICAgKi9cbiAgQElucHV0KClcbiAgcGFnZVNlY3Rpb25zVGVtcGxhdGU/OiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpzY3JvbGwnLCBbJyRldmVudCddKSAvLyBmb3Igd2luZG93IHNjcm9sbCBldmVudHNcbiAgb25TY3JvbGwoKSB7XG4gICAgY29uc3Qgc2VjdGlvbkNvbnRhaW5lciA9IHRoaXMuI2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCcuaXQtcGFnZS1zZWN0aW9ucy1jb250YWluZXInKTtcbiAgICB0aGlzLiNzdG9yZS51cGRhdGVQcm9ncmVzc0JhcihzZWN0aW9uQ29udGFpbmVyKTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpyZXNpemUnLCBbJyRldmVudCddKVxuICBvblJlc2l6ZSgpIHtcbiAgICB0aGlzLiNzZXRNb2JpbGUoKTtcbiAgfVxuXG4gIEBWaWV3Q2hpbGQoJ3RvZ2dsZUJ1dHRvblJlZicpXG4gIHJlYWRvbmx5IHRvZ2dsZUJ1dHRvblJlZiE6IEVsZW1lbnRSZWY8SFRNTEJ1dHRvbkVsZW1lbnQ+O1xuXG4gIHJlYWRvbmx5ICNzdG9yZSA9IGluamVjdChOYXZzY3JvbGxTdG9yZSk7XG5cbiAgcmVhZG9ubHkgI3Njcm9sbGVyID0gaW5qZWN0KFZpZXdwb3J0U2Nyb2xsZXIpO1xuXG4gIHJlYWRvbmx5ICNkZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuXG4gIHJlYWRvbmx5ICNlbGVtZW50UmVmID0gaW5qZWN0KEVsZW1lbnRSZWYpO1xuXG4gIHJlYWRvbmx5IHNlbGVjdGVkVGl0bGUgPSB0aGlzLiNzdG9yZS5zZWxlY3RlZC5waXBlKG1hcChzZWxlY3RlZCA9PiBzZWxlY3RlZD8udGl0bGUgPz8gJycpKTtcblxuICByZWFkb25seSBwcm9ncmVzc0JhclZhbHVlID0gdGhpcy4jc3RvcmUucHJvZ3Jlc3NCYXI7XG5cbiAgcmVhZG9ubHkgaXNNb2JpbGUgPSB0aGlzLiNzdG9yZS5pc01vYmlsZTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLiNzdG9yZS5tZW51SXRlbVNlbGVjdGVkXG4gICAgICAucGlwZShcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKCksXG4gICAgICAgIHdpdGhMYXRlc3RGcm9tKHRoaXMuaXNNb2JpbGUpLFxuICAgICAgICB0YXAodiA9PiB7XG4gICAgICAgICAgY29uc3QgaXNNb2JpbGUgPSB2WzFdO1xuICAgICAgICAgIGlmIChpc01vYmlsZSkge1xuICAgICAgICAgICAgdGhpcy50b2dnbGVCdXR0b25SZWYubmF0aXZlRWxlbWVudC5jbGljaygpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuI2luaXRWaWV3U2Nyb2xsZXJTdWJzY3JpcHRpb24oKTtcbiAgICB0aGlzLiNzdG9yZS5pbml0KHRoaXMuaXRlbXMpO1xuICAgIHRoaXMuI3NldE1vYmlsZSgpO1xuICB9XG5cbiAgI2luaXRWaWV3U2Nyb2xsZXJTdWJzY3JpcHRpb24oKSB7XG4gICAgdGhpcy4jc3RvcmUuc2VsZWN0ZWRcbiAgICAgIC5waXBlKFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy4jZGVzdHJveVJlZiksXG4gICAgICAgIGZpbHRlcihzZWxlY3RlZCA9PiBCb29sZWFuKHNlbGVjdGVkKSksXG4gICAgICAgIG1hcCh2ID0+IHYgYXMgTmF2c2Nyb2xsSXRlbSksXG4gICAgICAgIGRlbGF5KDApLCAvL1dBXG4gICAgICAgIHRhcCh7XG4gICAgICAgICAgbmV4dDogKHsgaHJlZiB9KSA9PiB7XG4gICAgICAgICAgICB0aGlzLiNzY3JvbGxlci5zY3JvbGxUb0FuY2hvcihocmVmKTtcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgpO1xuICB9XG5cbiAgI3NldE1vYmlsZSgpIHtcbiAgICB0aGlzLiNzdG9yZS5zZXRNb2JpbGUod2luZG93KTtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImNvbnRhaW5lciBweS1sZy01XCI+XG4gIDxkaXYgY2xhc3M9XCJyb3dcIj5cbiAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGNvbC1sZy00XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiaXQtbmF2c2Nyb2xsLXN0aWNreVwiIFtuZ0NsYXNzXT1cInsgJ2l0LW5hdnNjcm9sbC1zdGlja3ktbW9iaWxlJzogaXNNb2JpbGUgfCBhc3luYyB9XCIgZGF0YS1icy1zdGFja2FibGU9XCJ0cnVlXCI+XG4gICAgICAgIDxuYXZcbiAgICAgICAgICBjbGFzcz1cIm5hdmJhciBpdC1uYXZzY3JvbGwtd3JhcHBlciBuYXZiYXItZXhwYW5kLWxnXCJcbiAgICAgICAgICBbY2xhc3MuaXQtdG9wLW5hdnNjcm9sbF09XCJhbGlnbm1lbnQgPT09ICd0b3AnXCJcbiAgICAgICAgICBbY2xhc3MuaXQtYm90dG9tLW5hdnNjcm9sbF09XCJhbGlnbm1lbnQgPT09ICdib3R0b20nXCJcbiAgICAgICAgICBbY2xhc3MuaXQtbGVmdC1zaWRlXT1cImJvcmRlclBvc2l0aW9uID09PSAnbGVmdCdcIlxuICAgICAgICAgIFtjbGFzcy5pdC1yaWdodC1zaWRlXT1cImJvcmRlclBvc2l0aW9uID09PSAncmlnaHQnXCJcbiAgICAgICAgICBbY2xhc3MudGhlbWUtZGFyay1tb2JpbGVdPVwidGhlbWUgPT09ICdkYXJrJ1wiXG4gICAgICAgICAgW2NsYXNzLnRoZW1lLWRhcmstZGVza3RvcF09XCJ0aGVtZSA9PT0gJ2RhcmsnXCI+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgY2xhc3M9XCJjdXN0b20tbmF2YmFyLXRvZ2dsZXJcIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICBhcmlhLWNvbnRyb2xzPVwibmF2YmFyTmF2XCJcbiAgICAgICAgICAgIGFyaWEtZXhwYW5kZWQ9XCJmYWxzZVwiXG4gICAgICAgICAgICBhcmlhLWxhYmVsPVwiVG9nZ2xlIG5hdmlnYXRpb25cIlxuICAgICAgICAgICAgZGF0YS1icy10b2dnbGU9XCJuYXZiYXJjb2xsYXBzaWJsZVwiXG4gICAgICAgICAgICBkYXRhLWJzLXRhcmdldD1cIiNuYXZiYXJOYXZcIlxuICAgICAgICAgICAgI3RvZ2dsZUJ1dHRvblJlZj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiaXQtbGlzdFwiPjwvc3Bhbj57eyBzZWxlY3RlZFRpdGxlIHwgYXN5bmMgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3MgY3VzdG9tLW5hdmJhci1wcm9ncmVzc2JhclwiPlxuICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICBjbGFzcz1cInByb2dyZXNzLWJhciBpdC1uYXZzY3JvbGwtcHJvZ3Jlc3NiYXJcIlxuICAgICAgICAgICAgICByb2xlPVwicHJvZ3Jlc3NiYXJcIlxuICAgICAgICAgICAgICBbc3R5bGUud2lkdGguJV09XCJwcm9ncmVzc0JhclZhbHVlIHwgYXN5bmNcIlxuICAgICAgICAgICAgICBbYXR0ci5hcmlhLXZhbHVlbm93XT1cInByb2dyZXNzQmFyVmFsdWUgfCBhc3luY1wiXG4gICAgICAgICAgICAgIGFyaWEtdmFsdWVtaW49XCIwXCJcbiAgICAgICAgICAgICAgYXJpYS12YWx1ZW1heD1cIjEwMFwiPjwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJuYXZiYXItY29sbGFwc2FibGVcIiBpZD1cIm5hdmJhck5hdlwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm92ZXJsYXlcIj48L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjbG9zZS1kaXYgdmlzdWFsbHktaGlkZGVuXCI+XG4gICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gY2xvc2UtbWVudVwiIHR5cGU9XCJidXR0b25cIj48c3BhbiBjbGFzcz1cIml0LWNsb3NlXCI+PC9zcGFuPkNoaXVkaTwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cIml0LWJhY2stYnV0dG9uIGJ0biB3LTEwMCB0ZXh0LXN0YXJ0XCI+XG4gICAgICAgICAgICAgIDxzdmcgY2xhc3M9XCJpY29uIGljb24tc20gaWNvbi1wcmltYXJ5IGFsaWduLXRvcFwiPlxuICAgICAgICAgICAgICAgIDx1c2VcbiAgICAgICAgICAgICAgICAgIGhyZWY9XCIvYm9vdHN0cmFwLWl0YWxpYS9kaXN0L3N2Zy9zcHJpdGVzLnN2ZyNpdC1jaGV2cm9uLWxlZnRcIlxuICAgICAgICAgICAgICAgICAgeGxpbms6aHJlZj1cIi9ib290c3RyYXAtaXRhbGlhL2Rpc3Qvc3ZnL3Nwcml0ZXMuc3ZnI2l0LWNoZXZyb24tbGVmdFwiPjwvdXNlPlxuICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgPHNwYW4+SW5kaWV0cm88L3NwYW4+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtZW51LXdyYXBwZXJcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxpbmstbGlzdC13cmFwcGVyXCI+XG4gICAgICAgICAgICAgICAgPGgzPnt7IGhlYWRlciB9fTwvaDM+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInByb2dyZXNzXCI+XG4gICAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwicHJvZ3Jlc3MtYmFyIGl0LW5hdnNjcm9sbC1wcm9ncmVzc2JhclwiXG4gICAgICAgICAgICAgICAgICAgIHJvbGU9XCJwcm9ncmVzc2JhclwiXG4gICAgICAgICAgICAgICAgICAgIFtzdHlsZS53aWR0aC4lXT1cInByb2dyZXNzQmFyVmFsdWUgfCBhc3luY1wiXG4gICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtdmFsdWVub3ddPVwicHJvZ3Jlc3NCYXJWYWx1ZSB8IGFzeW5jXCJcbiAgICAgICAgICAgICAgICAgICAgYXJpYS12YWx1ZW1pbj1cIjBcIlxuICAgICAgICAgICAgICAgICAgICBhcmlhLXZhbHVlbWF4PVwiMTAwXCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPGl0LW5hdnNjcm9sbC1saXN0LWl0ZW1zIFtpdGVtc109XCJpdGVtc1wiPjwvaXQtbmF2c2Nyb2xsLWxpc3QtaXRlbXM+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvbmF2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImNvbC0xMiBjb2wtbGctOCBpdC1wYWdlLXNlY3Rpb25zLWNvbnRhaW5lclwiPlxuICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cInBhZ2VTZWN0aW9uc1RlbXBsYXRlID8gcGFnZVNlY3Rpb25zVGVtcGxhdGUgOiBkZWZhdWx0UGFnZVNlY3Rpb25zVGVtcGxhdGU7IGNvbnRleHQ6IHsgaXRlbXM6IGl0ZW1zIH1cIj5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48bmctdGVtcGxhdGUgI2RlZmF1bHRQYWdlU2VjdGlvbnNUZW1wbGF0ZSBsZXQtaXRlbXM9XCJpdGVtc1wiPlxuICBAZm9yIChpdGVtIG9mIGl0ZW1zOyB0cmFjayBpdGVtLmhyZWYpIHtcbiAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwicGFyYWdyYXBoVGVtcGxhdGU7IGNvbnRleHQ6IHsgaXRlbTogaXRlbSwgbGV2ZWw6IDEgfVwiPjwvbmctY29udGFpbmVyPlxuICB9XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI3BhcmFncmFwaFRlbXBsYXRlIGxldC1pdGVtPVwiaXRlbVwiIGxldC1sZXZlbD1cImxldmVsXCIgbGV0LW5leHRMZXZlbD1cImxldmVsKzFcIj5cbiAgQHN3aXRjaCAobGV2ZWwpIHtcbiAgICBAY2FzZSAoMSkge1xuICAgICAgPGgyIGNsYXNzPVwiaXQtcGFnZS1zZWN0aW9uXCIgaWQ9XCJ7eyBpdGVtLmhyZWYgfX1cIj57eyBpdGVtLnRpdGxlIH19PC9oMj5cbiAgICB9XG4gICAgQGNhc2UgKDIpIHtcbiAgICAgIDxoMyBjbGFzcz1cIml0LXBhZ2Utc2VjdGlvblwiIGlkPVwie3sgaXRlbS5ocmVmIH19XCI+e3sgaXRlbS50aXRsZSB9fTwvaDM+XG4gICAgfVxuICAgIEBjYXNlICgzKSB7XG4gICAgICA8aDQgY2xhc3M9XCJpdC1wYWdlLXNlY3Rpb25cIiBpZD1cInt7IGl0ZW0uaHJlZiB9fVwiPnt7IGl0ZW0udGl0bGUgfX08L2g0PlxuICAgIH1cbiAgICBAY2FzZSAoNCkge1xuICAgICAgPGg1IGNsYXNzPVwiaXQtcGFnZS1zZWN0aW9uXCIgaWQ9XCJ7eyBpdGVtLmhyZWYgfX1cIj57eyBpdGVtLnRpdGxlIH19PC9oNT5cbiAgICB9XG4gICAgQGRlZmF1bHQge1xuICAgICAgPGg2IGNsYXNzPVwiaXQtcGFnZS1zZWN0aW9uXCIgaWQ9XCJ7eyBpdGVtLmhyZWYgfX1cIj57eyBpdGVtLnRpdGxlIH19PC9oNj5cbiAgICB9XG4gIH1cbiAgPHA+e3sgaXRlbS50ZXh0IH19PC9wPlxuICBAZm9yIChpdGVtIG9mIGl0ZW0uY2hpbGRzOyB0cmFjayBpdGVtLmhyZWYpIHtcbiAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwicGFyYWdyYXBoVGVtcGxhdGU7IGNvbnRleHQ6IHsgaXRlbTogaXRlbSwgbGV2ZWw6IG5leHRMZXZlbCB9XCI+PC9uZy1jb250YWluZXI+XG4gIH1cbjwvbmctdGVtcGxhdGU+XG4iXX0=