UNPKG

@edugouvfr/ngx-dsfr

Version:

NgxDsfr est un portage Angular des éléments d'interface du Système de Design de l'État Français (DSFR).

144 lines 26.1 kB
import { Component, ContentChildren, EventEmitter, Input, Optional, Output, ViewEncapsulation, } from '@angular/core'; import { newUniqueId } from '../../shared'; import { DsfrTabComponent } from './tab.component'; import { BUTTON_TAB_ID_PREFIX } from './tabs.model'; import * as i0 from "@angular/core"; import * as i1 from "@angular/router"; import * as i2 from "@angular/common"; export class DsfrTabsComponent { constructor(router, activatedRoute, elRef) { this.router = router; this.activatedRoute = activatedRoute; this.elRef = elRef; /** * Attribut aria-label de la liste d'onglets. */ this.tabsAriaLabel = "Système d'onglets"; /** * Onglet sélectionné (commence à 0). * Ne peut pas être utilisé quand on utilise l'input `routes`. */ this.selectedTabIndex = 0; /** * Permet de positionner la largeur du viewport à 100% en mobile. */ this.fullViewport = false; /** * Émis lors de la sélection d'un onglet. La valeur émise correspond au `tabId` de l'onglet sélectionné. */ this.tabSelect = new EventEmitter(); this.routerTabId = newUniqueId(); } get headers() { return this.routes || this.tabComponents?.toArray(); } get tabsCount() { return this.routes ? this.routes.length : this.tabComponents ? this.tabComponents.length : 0; } /** @internal */ getHeaderValue(header, key) { return header[key]; } asRoute(header) { return header; } /** @internal */ getIconClasses(tabHeader) { return !tabHeader.icon ? '' : `${tabHeader.icon} fr-tabs__tab--icon-left`; } /** * [mode routes] Retourne l'identifiant unique du bouton de contrôle de l'onglet passé en paramètre. * * @internal */ getButtonTabId(header) { return BUTTON_TAB_ID_PREFIX + header.tabId; } /** * [mode routes] Retourne l'identifiant unique du bouton de contrôle de l'onglet courant. * * @internal */ getCurrentButtonTabId() { return this.selectedTabIndex >= 0 ? BUTTON_TAB_ID_PREFIX + this.routes[this.selectedTabIndex].tabId : null; } /** @internal */ onSelect(event, index) { event.preventDefault(); event.stopPropagation(); this.selectedTabIndex = index; this.tabSelect.emit(this.headers[this.selectedTabIndex].tabId); } /** @internal */ onRouterLinkActive(isActive, tabIndex) { if (isActive) { this.selectedTabIndex = tabIndex; } } /** * Gestion de la navigation au clavier en mode routes. * * @internal */ onButtonTabKeydown(event, index) { // just in case if (this.selectedTabIndex !== index) return; let newIndex = -1; switch (event.code) { case 'ArrowLeft': newIndex = this.isFirstTab(index) ? this.tabsCount - 1 : index - 1; break; case 'ArrowRight': newIndex = this.isLastTab(index) ? 0 : index + 1; break; case 'Home': newIndex = 0; break; case 'End': newIndex = this.tabsCount - 1; break; default: break; } if (newIndex > -1) { this.performKeyAction(newIndex); } } isFirstTab(index) { return index === 0; } isLastTab(index) { return index === this.tabsCount - 1; } performKeyAction(newIndex) { const route = this.routes[newIndex]; const extras = route.routerLinkExtras || { relativeTo: this.activatedRoute }; this.router.navigate([route.path], extras); this.elRef.nativeElement.querySelector('#' + this.getButtonTabId(route))?.focus(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DsfrTabsComponent, deps: [{ token: i1.Router, optional: true }, { token: i1.ActivatedRoute, optional: true }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DsfrTabsComponent, selector: "dsfr-tabs", inputs: { tabsAriaLabel: "tabsAriaLabel", selectedTabIndex: "selectedTabIndex", fullViewport: "fullViewport", routes: "routes" }, outputs: { tabSelect: "tabSelect" }, queries: [{ propertyName: "tabComponents", predicate: DsfrTabComponent }], ngImport: i0, template: "<div class=\"fr-tabs\" [class.fr-tabs--viewport-width]=\"fullViewport\">\n <ul class=\"fr-tabs__list\" role=\"tablist\" [attr.aria-label]=\"tabsAriaLabel\">\n <li role=\"presentation\" *ngFor=\"let header of headers; let index = index\">\n <button\n *ngIf=\"!routes\"\n [attr.id]=\"getHeaderValue(header, 'buttonId') || null\"\n type=\"button\"\n role=\"tab\"\n class=\"fr-tabs__tab\"\n [class]=\"getIconClasses(header) || null\"\n [attr.tabindex]=\"index === selectedTabIndex ? 0 : -1\"\n [attr.aria-controls]=\"header?.tabId || null\"\n [attr.aria-selected]=\"index === selectedTabIndex\"\n (click)=\"onSelect($event, index)\">\n {{ header.label }}\n </button>\n <button\n *ngIf=\"routes\"\n [attr.id]=\"getButtonTabId(header)\"\n type=\"button\"\n role=\"tab\"\n class=\"fr-tabs__tab\"\n [class]=\"getIconClasses(header) || null\"\n [attr.tabindex]=\"rla.isActive ? 0 : -1\"\n [attr.aria-controls]=\"rla.isActive ? routerTabId : null\"\n [attr.aria-selected]=\"rla.isActive\"\n [routerLink]=\"asRoute(header).path || null\"\n routerLinkActive\n [routerLinkActiveOptions]=\"asRoute(header).routerLinkActiveOptions ?? { exact: false }\"\n [queryParams]=\"asRoute(header).routerLinkExtras?.queryParams\"\n [fragment]=\"asRoute(header).routerLinkExtras?.fragment\"\n [queryParamsHandling]=\"asRoute(header).routerLinkExtras?.queryParamsHandling\"\n [preserveFragment]=\"asRoute(header).routerLinkExtras?.preserveFragment\"\n [skipLocationChange]=\"asRoute(header).routerLinkExtras?.skipLocationChange\"\n [replaceUrl]=\"asRoute(header).routerLinkExtras?.replaceUrl\"\n [state]=\"asRoute(header).routerLinkExtras?.state\"\n (isActiveChange)=\"onRouterLinkActive($event, index)\"\n #rla=\"routerLinkActive\"\n (click)=\"onSelect($event, index)\"\n (keydown)=\"onButtonTabKeydown($event, index)\">\n {{ header.label }}\n </button>\n </li>\n </ul>\n <ng-content *ngIf=\"!routes\"></ng-content>\n <ng-container *ngIf=\"routes\">\n <div\n [attr.id]=\"routerTabId\"\n role=\"tabpanel\"\n class=\"fr-tabs__panel fr-tabs__panel--selected\"\n tabindex=\"0\"\n [attr.aria-labelledby]=\"getCurrentButtonTabId()\">\n <router-outlet></router-outlet>\n </div>\n <div ngFor=\"let header of headers; let index = index\" [attr.aria-labelledby]=\"getCurrentButtonTabId()\"></div>\n </ng-container>\n</div>\n", dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DsfrTabsComponent, decorators: [{ type: Component, args: [{ selector: 'dsfr-tabs', encapsulation: ViewEncapsulation.None, template: "<div class=\"fr-tabs\" [class.fr-tabs--viewport-width]=\"fullViewport\">\n <ul class=\"fr-tabs__list\" role=\"tablist\" [attr.aria-label]=\"tabsAriaLabel\">\n <li role=\"presentation\" *ngFor=\"let header of headers; let index = index\">\n <button\n *ngIf=\"!routes\"\n [attr.id]=\"getHeaderValue(header, 'buttonId') || null\"\n type=\"button\"\n role=\"tab\"\n class=\"fr-tabs__tab\"\n [class]=\"getIconClasses(header) || null\"\n [attr.tabindex]=\"index === selectedTabIndex ? 0 : -1\"\n [attr.aria-controls]=\"header?.tabId || null\"\n [attr.aria-selected]=\"index === selectedTabIndex\"\n (click)=\"onSelect($event, index)\">\n {{ header.label }}\n </button>\n <button\n *ngIf=\"routes\"\n [attr.id]=\"getButtonTabId(header)\"\n type=\"button\"\n role=\"tab\"\n class=\"fr-tabs__tab\"\n [class]=\"getIconClasses(header) || null\"\n [attr.tabindex]=\"rla.isActive ? 0 : -1\"\n [attr.aria-controls]=\"rla.isActive ? routerTabId : null\"\n [attr.aria-selected]=\"rla.isActive\"\n [routerLink]=\"asRoute(header).path || null\"\n routerLinkActive\n [routerLinkActiveOptions]=\"asRoute(header).routerLinkActiveOptions ?? { exact: false }\"\n [queryParams]=\"asRoute(header).routerLinkExtras?.queryParams\"\n [fragment]=\"asRoute(header).routerLinkExtras?.fragment\"\n [queryParamsHandling]=\"asRoute(header).routerLinkExtras?.queryParamsHandling\"\n [preserveFragment]=\"asRoute(header).routerLinkExtras?.preserveFragment\"\n [skipLocationChange]=\"asRoute(header).routerLinkExtras?.skipLocationChange\"\n [replaceUrl]=\"asRoute(header).routerLinkExtras?.replaceUrl\"\n [state]=\"asRoute(header).routerLinkExtras?.state\"\n (isActiveChange)=\"onRouterLinkActive($event, index)\"\n #rla=\"routerLinkActive\"\n (click)=\"onSelect($event, index)\"\n (keydown)=\"onButtonTabKeydown($event, index)\">\n {{ header.label }}\n </button>\n </li>\n </ul>\n <ng-content *ngIf=\"!routes\"></ng-content>\n <ng-container *ngIf=\"routes\">\n <div\n [attr.id]=\"routerTabId\"\n role=\"tabpanel\"\n class=\"fr-tabs__panel fr-tabs__panel--selected\"\n tabindex=\"0\"\n [attr.aria-labelledby]=\"getCurrentButtonTabId()\">\n <router-outlet></router-outlet>\n </div>\n <div ngFor=\"let header of headers; let index = index\" [attr.aria-labelledby]=\"getCurrentButtonTabId()\"></div>\n </ng-container>\n</div>\n" }] }], ctorParameters: function () { return [{ type: i1.Router, decorators: [{ type: Optional }] }, { type: i1.ActivatedRoute, decorators: [{ type: Optional }] }, { type: i0.ElementRef }]; }, propDecorators: { tabsAriaLabel: [{ type: Input }], selectedTabIndex: [{ type: Input }], fullViewport: [{ type: Input }], routes: [{ type: Input }], tabSelect: [{ type: Output }], tabComponents: [{ type: ContentChildren, args: [DsfrTabComponent] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFicy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZHNmci1jb21wb25lbnRzL3NyYy9saWIvY29tcG9uZW50cy90YWJzL3RhYnMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRzZnItY29tcG9uZW50cy9zcmMvbGliL2NvbXBvbmVudHMvdGFicy90YWJzLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsZUFBZSxFQUVmLFlBQVksRUFDWixLQUFLLEVBQ0wsUUFBUSxFQUNSLE1BQU0sRUFFTixpQkFBaUIsR0FDbEIsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUMzQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsb0JBQW9CLEVBQThCLE1BQU0sY0FBYyxDQUFDOzs7O0FBT2hGLE1BQU0sT0FBTyxpQkFBaUI7SUFtQzVCLFlBQ3NCLE1BQWMsRUFDZCxjQUE4QixFQUMxQyxLQUFpQjtRQUZMLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxtQkFBYyxHQUFkLGNBQWMsQ0FBZ0I7UUFDMUMsVUFBSyxHQUFMLEtBQUssQ0FBWTtRQXJDM0I7O1dBRUc7UUFDTSxrQkFBYSxHQUFHLG1CQUFtQixDQUFDO1FBRTdDOzs7V0FHRztRQUNNLHFCQUFnQixHQUFHLENBQUMsQ0FBQztRQUU5Qjs7V0FFRztRQUNNLGlCQUFZLEdBQUcsS0FBSyxDQUFDO1FBUzlCOztXQUVHO1FBQ08sY0FBUyxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFhL0MsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLEVBQUUsQ0FBQztJQUNuQyxDQUFDO0lBRUQsSUFBSSxPQUFPO1FBQ1QsT0FBTyxJQUFJ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IHtcbiAgQ29tcG9uZW50LFxuICBDb250ZW50Q2hpbGRyZW4sXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFF1ZXJ5TGlzdCxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUsIE5hdmlnYXRpb25FeHRyYXMsIFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBuZXdVbmlxdWVJZCB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBEc2ZyVGFiQ29tcG9uZW50IH0gZnJvbSAnLi90YWIuY29tcG9uZW50JztcbmltcG9ydCB7IEJVVFRPTl9UQUJfSURfUFJFRklYLCBEc2ZyVGFiUm91dGUsIEVkdVRhYkhlYWRlciB9IGZyb20gJy4vdGFicy5tb2RlbCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2RzZnItdGFicycsXG4gIHRlbXBsYXRlVXJsOiAnLi90YWJzLmNvbXBvbmVudC5odG1sJyxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbn0pXG5leHBvcnQgY2xhc3MgRHNmclRhYnNDb21wb25lbnQge1xuICAvKipcbiAgICogQXR0cmlidXQgYXJpYS1sYWJlbCBkZSBsYSBsaXN0ZSBkJ29uZ2xldHMuXG4gICAqL1xuICBASW5wdXQoKSB0YWJzQXJpYUxhYmVsID0gXCJTeXN0w6htZSBkJ29uZ2xldHNcIjtcblxuICAvKipcbiAgICogT25nbGV0IHPDqWxlY3Rpb25uw6kgKGNvbW1lbmNlIMOgIDApLlxuICAgKiBOZSBwZXV0IHBhcyDDqnRyZSB1dGlsaXPDqSBxdWFuZCBvbiB1dGlsaXNlIGwnaW5wdXQgYHJvdXRlc2AuXG4gICAqL1xuICBASW5wdXQoKSBzZWxlY3RlZFRhYkluZGV4ID0gMDtcblxuICAvKipcbiAgICogUGVybWV0IGRlIHBvc2l0aW9ubmVyIGxhIGxhcmdldXIgZHUgdmlld3BvcnQgw6AgMTAwJSBlbiBtb2JpbGUuXG4gICAqL1xuICBASW5wdXQoKSBmdWxsVmlld3BvcnQgPSBmYWxzZTtcblxuICAvKipcbiAgICogRMOpZmluaXRpb24gZGVzIHJvdXRlcyBzaSBsJ29uIHNvdWhhaXRlIHV0aWxpc2VyIGA8cm91dGVyLW91dGxldD5gLlxuICAgKlxuICAgKiBAc2luY2UgMS45LjBcbiAgICovXG4gIEBJbnB1dCgpIHJvdXRlcyE6IERzZnJUYWJSb3V0ZVtdO1xuXG4gIC8qKlxuICAgKiDDiW1pcyBsb3JzIGRlIGxhIHPDqWxlY3Rpb24gZCd1biBvbmdsZXQuIExhIHZhbGV1ciDDqW1pc2UgY29ycmVzcG9uZCBhdSBgdGFiSWRgIGRlIGwnb25nbGV0IHPDqWxlY3Rpb25uw6kuXG4gICAqL1xuICBAT3V0cHV0KCkgdGFiU2VsZWN0ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBAQ29udGVudENoaWxkcmVuKERzZnJUYWJDb21wb25lbnQpIHRhYkNvbXBvbmVudHMhOiBRdWVyeUxpc3Q8RHNmclRhYkNvbXBvbmVudD47XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICByb3V0ZXJUYWJJZDogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXG4gICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSBhY3RpdmF0ZWRSb3V0ZTogQWN0aXZhdGVkUm91dGUsXG4gICAgcHJpdmF0ZSBlbFJlZjogRWxlbWVudFJlZixcbiAgKSB7XG4gICAgdGhpcy5yb3V0ZXJUYWJJZCA9IG5ld1VuaXF1ZUlkKCk7XG4gIH1cblxuICBnZXQgaGVhZGVycygpOiBFZHVUYWJIZWFkZXJbXSB7XG4gICAgcmV0dXJuIHRoaXMucm91dGVzIHx8IHRoaXMudGFiQ29tcG9uZW50cz8udG9BcnJheSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgdGFic0NvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucm91dGVzID8gdGhpcy5yb3V0ZXMubGVuZ3RoIDogdGhpcy50YWJDb21wb25lbnRzID8gdGhpcy50YWJDb21wb25lbnRzLmxlbmd0aCA6IDA7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIGdldEhlYWRlclZhbHVlKGhlYWRlcjogRWR1VGFiSGVhZGVyLCBrZXk6IHN0cmluZyk6IGFueSB7XG4gICAgcmV0dXJuIGhlYWRlcls8bmV2ZXI+a2V5XTtcbiAgfVxuXG4gIGFzUm91dGUoaGVhZGVyOiBFZHVUYWJIZWFkZXIpOiBEc2ZyVGFiUm91dGUge1xuICAgIHJldHVybiA8RHNmclRhYlJvdXRlPmhlYWRlcjtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgZ2V0SWNvbkNsYXNzZXModGFiSGVhZGVyOiBFZHVUYWJIZWFkZXIpOiBzdHJpbmcge1xuICAgIHJldHVybiAhdGFiSGVhZGVyLmljb24gPyAnJyA6IGAke3RhYkhlYWRlci5pY29ufSBmci10YWJzX190YWItLWljb24tbGVmdGA7XG4gIH1cblxuICAvKipcbiAgICogW21vZGUgcm91dGVzXSBSZXRvdXJuZSBsJ2lkZW50aWZpYW50IHVuaXF1ZSBkdSBib3V0b24gZGUgY29udHLDtGxlIGRlIGwnb25nbGV0IHBhc3PDqSBlbiBwYXJhbcOodHJlLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIGdldEJ1dHRvblRhYklkKGhlYWRlcjogRWR1VGFiSGVhZGVyKSB7XG4gICAgcmV0dXJuIEJVVFRPTl9UQUJfSURfUFJFRklYICsgaGVhZGVyLnRhYklkO1xuICB9XG5cbiAgLyoqXG4gICAqIFttb2RlIHJvdXRlc10gUmV0b3VybmUgbCdpZGVudGlmaWFudCB1bmlxdWUgZHUgYm91dG9uIGRlIGNvbnRyw7RsZSBkZSBsJ29uZ2xldCBjb3VyYW50LlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIGdldEN1cnJlbnRCdXR0b25UYWJJZCgpIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZFRhYkluZGV4ID49IDAgPyBCVVRUT05fVEFCX0lEX1BSRUZJWCArIHRoaXMucm91dGVzW3RoaXMuc2VsZWN0ZWRUYWJJbmRleF0udGFiSWQgOiBudWxsO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBvblNlbGVjdChldmVudDogTW91c2VFdmVudCwgaW5kZXg6IG51bWJlcikge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgdGhpcy5zZWxlY3RlZFRhYkluZGV4ID0gaW5kZXg7XG4gICAgdGhpcy50YWJTZWxlY3QuZW1pdCh0aGlzLmhlYWRlcnNbdGhpcy5zZWxlY3RlZFRhYkluZGV4XS50YWJJZCk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIG9uUm91dGVyTGlua0FjdGl2ZShpc0FjdGl2ZTogYm9vbGVhbiwgdGFiSW5kZXg6IG51bWJlcikge1xuICAgIGlmIChpc0FjdGl2ZSkge1xuICAgICAgdGhpcy5zZWxlY3RlZFRhYkluZGV4ID0gdGFiSW5kZXg7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdlc3Rpb24gZGUgbGEgbmF2aWdhdGlvbiBhdSBjbGF2aWVyIGVuIG1vZGUgcm91dGVzLlxuICAgKlxuICAgKiAgQGludGVybmFsXG4gICAqL1xuICBvbkJ1dHRvblRhYktleWRvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAvLyBqdXN0IGluIGNhc2VcbiAgICBpZiAodGhpcy5zZWxlY3RlZFRhYkluZGV4ICE9PSBpbmRleCkgcmV0dXJuO1xuXG4gICAgbGV0IG5ld0luZGV4ID0gLTE7XG5cbiAgICBzd2l0Y2ggKGV2ZW50LmNvZGUpIHtcbiAgICAgIGNhc2UgJ0Fycm93TGVmdCc6XG4gICAgICAgIG5ld0luZGV4ID0gdGhpcy5pc0ZpcnN0VGFiKGluZGV4KSA/IHRoaXMudGFic0NvdW50IC0gMSA6IGluZGV4IC0gMTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ0Fycm93UmlnaHQnOlxuICAgICAgICBuZXdJbmRleCA9IHRoaXMuaXNMYXN0VGFiKGluZGV4KSA/IDAgOiBpbmRleCArIDE7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdIb21lJzpcbiAgICAgICAgbmV3SW5kZXggPSAwO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnRW5kJzpcbiAgICAgICAgbmV3SW5kZXggPSB0aGlzLnRhYnNDb3VudCAtIDE7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBpZiAobmV3SW5kZXggPiAtMSkge1xuICAgICAgdGhpcy5wZXJmb3JtS2V5QWN0aW9uKG5ld0luZGV4KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzRmlyc3RUYWIoaW5kZXg6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgIHJldHVybiBpbmRleCA9PT0gMDtcbiAgfVxuXG4gIHByaXZhdGUgaXNMYXN0VGFiKGluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICByZXR1cm4gaW5kZXggPT09IHRoaXMudGFic0NvdW50IC0gMTtcbiAgfVxuXG4gIHByaXZhdGUgcGVyZm9ybUtleUFjdGlvbihuZXdJbmRleDogbnVtYmVyKSB7XG4gICAgY29uc3Qgcm91dGUgPSB0aGlzLnJvdXRlc1tuZXdJbmRleF07XG4gICAgY29uc3QgZXh0cmFzOiBOYXZpZ2F0aW9uRXh0cmFzID0gcm91dGUucm91dGVyTGlua0V4dHJhcyB8fCB7IHJlbGF0aXZlVG86IHRoaXMuYWN0aXZhdGVkUm91dGUgfTtcbiAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbcm91dGUucGF0aF0sIGV4dHJhcyk7XG4gICAgdGhpcy5lbFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJyMnICsgdGhpcy5nZXRCdXR0b25UYWJJZChyb3V0ZSkpPy5mb2N1cygpO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwiZnItdGFic1wiIFtjbGFzcy5mci10YWJzLS12aWV3cG9ydC13aWR0aF09XCJmdWxsVmlld3BvcnRcIj5cbiAgPHVsIGNsYXNzPVwiZnItdGFic19fbGlzdFwiIHJvbGU9XCJ0YWJsaXN0XCIgW2F0dHIuYXJpYS1sYWJlbF09XCJ0YWJzQXJpYUxhYmVsXCI+XG4gICAgPGxpIHJvbGU9XCJwcmVzZW50YXRpb25cIiAqbmdGb3I9XCJsZXQgaGVhZGVyIG9mIGhlYWRlcnM7IGxldCBpbmRleCA9IGluZGV4XCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgICpuZ0lmPVwiIXJvdXRlc1wiXG4gICAgICAgIFthdHRyLmlkXT1cImdldEhlYWRlclZhbHVlKGhlYWRlciwgJ2J1dHRvbklkJykgfHwgbnVsbFwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICByb2xlPVwidGFiXCJcbiAgICAgICAgY2xhc3M9XCJmci10YWJzX190YWJcIlxuICAgICAgICBbY2xhc3NdPVwiZ2V0SWNvbkNsYXNzZXMoaGVhZGVyKSB8fCBudWxsXCJcbiAgICAgICAgW2F0dHIudGFiaW5kZXhdPVwiaW5kZXggPT09IHNlbGVjdGVkVGFiSW5kZXggPyAwIDogLTFcIlxuICAgICAgICBbYXR0ci5hcmlhLWNvbnRyb2xzXT1cImhlYWRlcj8udGFiSWQgfHwgbnVsbFwiXG4gICAgICAgIFthdHRyLmFyaWEtc2VsZWN0ZWRdPVwiaW5kZXggPT09IHNlbGVjdGVkVGFiSW5kZXhcIlxuICAgICAgICAoY2xpY2spPVwib25TZWxlY3QoJGV2ZW50LCBpbmRleClcIj5cbiAgICAgICAge3sgaGVhZGVyLmxhYmVsIH19XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxidXR0b25cbiAgICAgICAgKm5nSWY9XCJyb3V0ZXNcIlxuICAgICAgICBbYXR0ci5pZF09XCJnZXRCdXR0b25UYWJJZChoZWFkZXIpXCJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIHJvbGU9XCJ0YWJcIlxuICAgICAgICBjbGFzcz1cImZyLXRhYnNfX3RhYlwiXG4gICAgICAgIFtjbGFzc109XCJnZXRJY29uQ2xhc3NlcyhoZWFkZXIpIHx8IG51bGxcIlxuICAgICAgICBbYXR0ci50YWJpbmRleF09XCJybGEuaXNBY3RpdmUgPyAwIDogLTFcIlxuICAgICAgICBbYXR0ci5hcmlhLWNvbnRyb2xzXT1cInJsYS5pc0FjdGl2ZSA/IHJvdXRlclRhYklkIDogbnVsbFwiXG4gICAgICAgIFthdHRyLmFyaWEtc2VsZWN0ZWRdPVwicmxhLmlzQWN0aXZlXCJcbiAgICAgICAgW3JvdXRlckxpbmtdPVwiYXNSb3V0ZShoZWFkZXIpLnBhdGggfHwgbnVsbFwiXG4gICAgICAgIHJvdXRlckxpbmtBY3RpdmVcbiAgICAgICAgW3JvdXRlckxpbmtBY3RpdmVPcHRpb25zXT1cImFzUm91dGUoaGVhZGVyKS5yb3V0ZXJMaW5rQWN0aXZlT3B0aW9ucyA/PyB7IGV4YWN0OiBmYWxzZSB9XCJcbiAgICAgICAgW3F1ZXJ5UGFyYW1zXT1cImFzUm91dGUoaGVhZGVyKS5yb3V0ZXJMaW5rRXh0cmFzPy5xdWVyeVBhcmFtc1wiXG4gICAgICAgIFtmcmFnbWVudF09XCJhc1JvdXRlKGhlYWRlcikucm91dGVyTGlua0V4dHJhcz8uZnJhZ21lbnRcIlxuICAgICAgICBbcXVlcnlQYXJhbXNIYW5kbGluZ109XCJhc1JvdXRlKGhlYWRlcikucm91dGVyTGlua0V4dHJhcz8ucXVlcnlQYXJhbXNIYW5kbGluZ1wiXG4gICAgICAgIFtwcmVzZXJ2ZUZyYWdtZW50XT1cImFzUm91dGUoaGVhZGVyKS5yb3V0ZXJMaW5rRXh0cmFzPy5wcmVzZXJ2ZUZyYWdtZW50XCJcbiAgICAgICAgW3NraXBMb2NhdGlvbkNoYW5nZV09XCJhc1JvdXRlKGhlYWRlcikucm91dGVyTGlua0V4dHJhcz8uc2tpcExvY2F0aW9uQ2hhbmdlXCJcbiAgICAgICAgW3JlcGxhY2VVcmxdPVwiYXNSb3V0ZShoZWFkZXIpLnJvdXRlckxpbmtFeHRyYXM/LnJlcGxhY2VVcmxcIlxuICAgICAgICBbc3RhdGVdPVwiYXNSb3V0ZShoZWFkZXIpLnJvdXRlckxpbmtFeHRyYXM/LnN0YXRlXCJcbiAgICAgICAgKGlzQWN0aXZlQ2hhbmdlKT1cIm9uUm91dGVyTGlua0FjdGl2ZSgkZXZlbnQsIGluZGV4KVwiXG4gICAgICAgICNybGE9XCJyb3V0ZXJMaW5rQWN0aXZlXCJcbiAgICAgICAgKGNsaWNrKT1cIm9uU2VsZWN0KCRldmVudCwgaW5kZXgpXCJcbiAgICAgICAgKGtleWRvd24pPVwib25CdXR0b25UYWJLZXlkb3duKCRldmVudCwgaW5kZXgpXCI+XG4gICAgICAgIHt7IGhlYWRlci5sYWJlbCB9fVxuICAgICAgPC9idXR0b24+XG4gICAgPC9saT5cbiAgPC91bD5cbiAgPG5nLWNvbnRlbnQgKm5nSWY9XCIhcm91dGVzXCI+PC9uZy1jb250ZW50PlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwicm91dGVzXCI+XG4gICAgPGRpdlxuICAgICAgW2F0dHIuaWRdPVwicm91dGVyVGFiSWRcIlxuICAgICAgcm9sZT1cInRhYnBhbmVsXCJcbiAgICAgIGNsYXNzPVwiZnItdGFic19fcGFuZWwgZnItdGFic19fcGFuZWwtLXNlbGVjdGVkXCJcbiAgICAgIHRhYmluZGV4PVwiMFwiXG4gICAgICBbYXR0ci5hcmlhLWxhYmVsbGVkYnldPVwiZ2V0Q3VycmVudEJ1dHRvblRhYklkKClcIj5cbiAgICAgIDxyb3V0ZXItb3V0bGV0Pjwvcm91dGVyLW91dGxldD5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IG5nRm9yPVwibGV0IGhlYWRlciBvZiBoZWFkZXJzOyBsZXQgaW5kZXggPSBpbmRleFwiIFthdHRyLmFyaWEtbGFiZWxsZWRieV09XCJnZXRDdXJyZW50QnV0dG9uVGFiSWQoKVwiPjwvZGl2PlxuICA8L25nLWNvbnRhaW5lcj5cbjwvZGl2PlxuIl19