UNPKG

carbon-components-angular

Version:
322 lines 25.9 kB
import { Component, forwardRef, HostBinding, Input, ViewChild } from "@angular/core"; import { TabHeaderBase } from "./tab-header.directive"; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "carbon-components-angular/tooltip"; /** * Tab header with template for label, optional icon, secondary label, badge, and dismissable close. * * ```html * <cds-tab-header-group> * <cds-tab-header [paneReference]="c1">Dashboard</cds-tab-header> * <cds-tab-header [paneReference]="c2" [icon]="iconTpl" secondaryLabel="(1/4)"> * Monitoring * </cds-tab-header> * </cds-tab-header-group> * <cds-tab #c1>...</cds-tab> * <cds-tab #c2>...</cds-tab> * ``` */ export class TabHeaderComponent extends TabHeaderBase { constructor() { super(...arguments); /** * Icon-only tab: set `icon` and `iconLabel`. */ this.iconOnly = false; /** * **Preview**: Icon-only tabs — show a notification dot on the icon. */ this.badgeIndicator = false; /** * Icon-only tabs: icon size `default` (16px) or `lg` (20px); usually set on the parent group. */ this.iconSize = "default"; /** * `aria-label` for the dismissable close button. */ this.closeButtonAriaLabel = "Press delete to remove tab"; /** * Icon-only tabs: open the tooltip on first render. */ this.isTooltipOpen = false; this.displayContents = "contents"; } ngAfterViewInit() { // Mirror the deprecated directive's title-fallback behavior, but read // from the inner rendered button rather than the `display: contents` host. setTimeout(() => { if (!this.title && this.tabButton?.nativeElement) { const text = this.tabButton.nativeElement.textContent?.trim(); if (text) { this.title = text; } } }); } /** * Focus the rendered tab button (not the host). */ focus() { this.tabButton?.nativeElement?.focus(); } onTabButtonClick() { this.selectTab(); } /** * `Delete` closes dismissable tabs when focus is on the tab. */ onTabButtonKeyDown(event) { if (this.dismissable && event.key === "Delete") { event.stopPropagation(); this.tabClose.emit(); } } /** * Close button click; stops propagation so the tab does not activate. */ onClose(event) { event.stopPropagation(); if (this.disabled) { return; } this.tabClose.emit(); } get resolvedTitle() { if (this.iconOnly) { return this.iconLabel || null; } return this.title || null; } get closeButtonTitle() { const label = this.tabButton?.nativeElement?.textContent?.trim(); return label ? `Remove ${label} tab` : "Remove tab"; } } TabHeaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TabHeaderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); TabHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: TabHeaderComponent, selector: "cds-tab-header, ibm-tab-header", inputs: { iconOnly: "iconOnly", iconLabel: "iconLabel", badgeIndicator: "badgeIndicator", iconSize: "iconSize", closeButtonAriaLabel: "closeButtonAriaLabel", enterDelayMs: "enterDelayMs", leaveDelayMs: "leaveDelayMs", isTooltipOpen: "isTooltipOpen" }, host: { properties: { "style.display": "this.displayContents" } }, providers: [ // tslint:disable-next-line:no-forward-ref { provide: TabHeaderBase, useExisting: forwardRef(() => TabHeaderComponent) } ], viewQueries: [{ propertyName: "tabButton", first: true, predicate: ["tabButton"], descendants: true }], usesInheritance: true, ngImport: i0, template: ` <cds-tooltip *ngIf="iconOnly; else plainButton" align="bottom" [autoAlign]="true" class="cds--icon-tooltip" [description]="iconLabel" [enterDelayMs]="enterDelayMs" [leaveDelayMs]="leaveDelayMs" [isOpen]="isTooltipOpen" [disabled]="disabled"> <ng-container *ngTemplateOutlet="tabButtonTemplate"></ng-container> </cds-tooltip> <ng-template #plainButton> <ng-container *ngTemplateOutlet="tabButtonTemplate"></ng-container> </ng-template> <ng-template #tabButtonTemplate> <button #tabButton type="button" role="tab" class="cds--tabs__nav-item cds--tabs__nav-link" [ngClass]="{ 'cds--tabs__nav-item--selected': active, 'cds--tabs__nav-item--disabled': disabled, 'cds--tabs__nav-item--icon-only': iconOnly, 'cds--tabs__nav-item--icon-only__20': iconOnly && iconSize === 'lg' }" [attr.aria-selected]="active" [attr.aria-disabled]="disabled" [attr.aria-controls]="paneReference?.id || null" [attr.aria-label]="iconOnly ? iconLabel : null" [attr.tabindex]="active ? 0 : -1" [attr.title]="resolvedTitle" [disabled]="disabled" (click)="onTabButtonClick()" (keydown)="onTabButtonKeyDown($event)"> <ng-container *ngIf="iconOnly; else labeledTab"> <ng-container [ngTemplateOutlet]="icon"></ng-container> <span *ngIf="!disabled && badgeIndicator" class="cds--badge-indicator" aria-hidden="true"> </span> </ng-container> <ng-template #labeledTab> <div class="cds--tabs__nav-item-label-wrapper"> <div *ngIf="dismissable && icon" class="cds--tabs__nav-item--icon-left"> <ng-container [ngTemplateOutlet]="icon"></ng-container> </div> <span class="cds--tabs__nav-item-label"> <ng-content></ng-content> </span> <div *ngIf="!dismissable && icon" class="cds--tabs__nav-item--icon"> <ng-container [ngTemplateOutlet]="icon"></ng-container> </div> </div> <div *ngIf="secondaryLabel" class="cds--tabs__nav-item-secondary-label" [attr.title]="secondaryLabel"> {{ secondaryLabel }} </div> </ng-template> </button> </ng-template> <div *ngIf="dismissable" class="cds--tabs__nav-item--close"> <button type="button" class="cds--tabs__nav-item--close-icon" [attr.tabindex]="-1" [attr.aria-disabled]="disabled" [attr.aria-hidden]="!(active && !disabled)" [ngClass]="{ 'cds--tabs__nav-item--close-icon--selected': active, 'cds--tabs__nav-item--close-icon--disabled': disabled }" [disabled]="disabled" [attr.title]="closeButtonTitle" (click)="onClose($event)"> <svg focusable="false" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="16" height="16" viewBox="0 0 32 32" [attr.aria-label]="closeButtonAriaLabel" [attr.aria-hidden]="!(active && !disabled)"> <path d="M17.4141 16L24 9.4141 22.5859 8 16 14.5859 9.4143 8 8 9.4141 14.5859 16 8 22.5859 9.4143 24 16 17.4141 22.5859 24 24 22.5859 17.4141 16z"></path> </svg> </button> </div> `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.Tooltip, selector: "cds-tooltip, ibm-tooltip", inputs: ["id", "enterDelayMs", "leaveDelayMs", "disabled", "description", "templateContext"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TabHeaderComponent, decorators: [{ type: Component, args: [{ selector: "cds-tab-header, ibm-tab-header", providers: [ // tslint:disable-next-line:no-forward-ref { provide: TabHeaderBase, useExisting: forwardRef(() => TabHeaderComponent) } ], template: ` <cds-tooltip *ngIf="iconOnly; else plainButton" align="bottom" [autoAlign]="true" class="cds--icon-tooltip" [description]="iconLabel" [enterDelayMs]="enterDelayMs" [leaveDelayMs]="leaveDelayMs" [isOpen]="isTooltipOpen" [disabled]="disabled"> <ng-container *ngTemplateOutlet="tabButtonTemplate"></ng-container> </cds-tooltip> <ng-template #plainButton> <ng-container *ngTemplateOutlet="tabButtonTemplate"></ng-container> </ng-template> <ng-template #tabButtonTemplate> <button #tabButton type="button" role="tab" class="cds--tabs__nav-item cds--tabs__nav-link" [ngClass]="{ 'cds--tabs__nav-item--selected': active, 'cds--tabs__nav-item--disabled': disabled, 'cds--tabs__nav-item--icon-only': iconOnly, 'cds--tabs__nav-item--icon-only__20': iconOnly && iconSize === 'lg' }" [attr.aria-selected]="active" [attr.aria-disabled]="disabled" [attr.aria-controls]="paneReference?.id || null" [attr.aria-label]="iconOnly ? iconLabel : null" [attr.tabindex]="active ? 0 : -1" [attr.title]="resolvedTitle" [disabled]="disabled" (click)="onTabButtonClick()" (keydown)="onTabButtonKeyDown($event)"> <ng-container *ngIf="iconOnly; else labeledTab"> <ng-container [ngTemplateOutlet]="icon"></ng-container> <span *ngIf="!disabled && badgeIndicator" class="cds--badge-indicator" aria-hidden="true"> </span> </ng-container> <ng-template #labeledTab> <div class="cds--tabs__nav-item-label-wrapper"> <div *ngIf="dismissable && icon" class="cds--tabs__nav-item--icon-left"> <ng-container [ngTemplateOutlet]="icon"></ng-container> </div> <span class="cds--tabs__nav-item-label"> <ng-content></ng-content> </span> <div *ngIf="!dismissable && icon" class="cds--tabs__nav-item--icon"> <ng-container [ngTemplateOutlet]="icon"></ng-container> </div> </div> <div *ngIf="secondaryLabel" class="cds--tabs__nav-item-secondary-label" [attr.title]="secondaryLabel"> {{ secondaryLabel }} </div> </ng-template> </button> </ng-template> <div *ngIf="dismissable" class="cds--tabs__nav-item--close"> <button type="button" class="cds--tabs__nav-item--close-icon" [attr.tabindex]="-1" [attr.aria-disabled]="disabled" [attr.aria-hidden]="!(active && !disabled)" [ngClass]="{ 'cds--tabs__nav-item--close-icon--selected': active, 'cds--tabs__nav-item--close-icon--disabled': disabled }" [disabled]="disabled" [attr.title]="closeButtonTitle" (click)="onClose($event)"> <svg focusable="false" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="16" height="16" viewBox="0 0 32 32" [attr.aria-label]="closeButtonAriaLabel" [attr.aria-hidden]="!(active && !disabled)"> <path d="M17.4141 16L24 9.4141 22.5859 8 16 14.5859 9.4143 8 8 9.4141 14.5859 16 8 22.5859 9.4143 24 16 17.4141 22.5859 24 24 22.5859 17.4141 16z"></path> </svg> </button> </div> ` }] }], propDecorators: { iconOnly: [{ type: Input }], iconLabel: [{ type: Input }], badgeIndicator: [{ type: Input }], iconSize: [{ type: Input }], closeButtonAriaLabel: [{ type: Input }], enterDelayMs: [{ type: Input }], leaveDelayMs: [{ type: Input }], isTooltipOpen: [{ type: Input }], displayContents: [{ type: HostBinding, args: ["style.display"] }], tabButton: [{ type: ViewChild, args: ["tabButton"] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFiLWhlYWRlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGFicy90YWItaGVhZGVyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRU4sU0FBUyxFQUVULFVBQVUsRUFDVixXQUFXLEVBQ1gsS0FBSyxFQUNMLFNBQVMsRUFDVCxNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7Ozs7QUFFdkQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQXVHSCxNQUFNLE9BQU8sa0JBQW1CLFNBQVEsYUFBYTtJQXRHckQ7O1FBdUdDOztXQUVHO1FBQ00sYUFBUSxHQUFHLEtBQUssQ0FBQztRQUsxQjs7V0FFRztRQUNNLG1CQUFjLEdBQUcsS0FBSyxDQUFDO1FBQ2hDOztXQUVHO1FBQ00sYUFBUSxHQUFxQixTQUFTLENBQUM7UUFDaEQ7O1dBRUc7UUFDTSx5QkFBb0IsR0FBRyw0QkFBNEIsQ0FBQztRQVM3RDs7V0FFRztRQUNNLGtCQUFhLEdBQUcsS0FBSyxDQUFDO1FBRUQsb0JBQWUsR0FBRyxVQUFVLENBQUM7S0E0RDNEO0lBeERBLGVBQWU7UUFDZCxzRUFBc0U7UUFDdEUsMkVBQTJFO1FBQzNFLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLGFBQWEsRUFBRTtnQkFDakQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLElBQUksRUFBRSxDQUFDO2dCQUM5RCxJQUFJLElBQUksRUFBRTtvQkFDVCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQztpQkFDbEI7YUFDRDtRQUNGLENBQUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSztRQUNKLElBQUksQ0FBQyxTQUFTLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQ3hDLENBQUM7SUFFRCxnQkFBZ0I7UUFDZixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDbEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsa0JBQWtCLENBQUMsS0FBb0I7UUFDdEMsSUFBSSxJQUFJLENBQUMsV0FBVyxJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssUUFBUSxFQUFFO1lBQy9DLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1NBQ3JCO0lBQ0YsQ0FBQztJQUVEOztPQUVHO0lBQ0gsT0FBTyxDQUFDLEtBQVk7UUFDbkIsS0FBSyxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3hCLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNsQixPQUFPO1NBQ1A7UUFDRCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFRCxJQUFJLGFBQWE7UUFDaEIsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2xCLE9BQU8sSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUM7U0FDOUI7UUFDRCxPQUFPLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDO0lBQzNCLENBQUM7SUFFRCxJQUFJLGdCQUFnQjtRQUNuQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFDakUsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLFVBQVUsS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQztJQUNyRCxDQUFDOzsrR0E3Rlcsa0JBQWtCO21HQUFsQixrQkFBa0Isd1hBcEduQjtRQUNWLDBDQUEwQztRQUMxQyxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFO0tBQzdFLHlKQUNTOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBOEZUOzJGQUVXLGtCQUFrQjtrQkF0RzlCLFNBQVM7bUJBQUM7b0JBQ1YsUUFBUSxFQUFFLGdDQUFnQztvQkFDMUMsU0FBUyxFQUFFO3dCQUNWLDBDQUEwQzt3QkFDMUMsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLG1CQUFtQixDQUFDLEVBQUU7cUJBQzdFO29CQUNELFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQThGVDtpQkFDRDs4QkFLUyxRQUFRO3NCQUFoQixLQUFLO2dCQUlHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBSUcsY0FBYztzQkFBdEIsS0FBSztnQkFJRyxRQUFRO3NCQUFoQixLQUFLO2dCQUlHLG9CQUFvQjtzQkFBNUIsS0FBSztnQkFJRyxZQUFZO3NCQUFwQixLQUFLO2dCQUlHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBSUcsYUFBYTtzQkFBckIsS0FBSztnQkFFd0IsZUFBZTtzQkFBNUMsV0FBVzt1QkFBQyxlQUFlO2dCQUVKLFNBQVM7c0JBQWhDLFNBQVM7dUJBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcblx0QWZ0ZXJWaWV3SW5pdCxcclxuXHRDb21wb25lbnQsXHJcblx0RWxlbWVudFJlZixcclxuXHRmb3J3YXJkUmVmLFxyXG5cdEhvc3RCaW5kaW5nLFxyXG5cdElucHV0LFxyXG5cdFZpZXdDaGlsZFxyXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcblxyXG5pbXBvcnQgeyBUYWJIZWFkZXJCYXNlIH0gZnJvbSBcIi4vdGFiLWhlYWRlci5kaXJlY3RpdmVcIjtcclxuXHJcbi8qKlxyXG4gKiBUYWIgaGVhZGVyIHdpdGggdGVtcGxhdGUgZm9yIGxhYmVsLCBvcHRpb25hbCBpY29uLCBzZWNvbmRhcnkgbGFiZWwsIGJhZGdlLCBhbmQgZGlzbWlzc2FibGUgY2xvc2UuXHJcbiAqXHJcbiAqIGBgYGh0bWxcclxuICogPGNkcy10YWItaGVhZGVyLWdyb3VwPlxyXG4gKiAgIDxjZHMtdGFiLWhlYWRlciBbcGFuZVJlZmVyZW5jZV09XCJjMVwiPkRhc2hib2FyZDwvY2RzLXRhYi1oZWFkZXI+XHJcbiAqICAgPGNkcy10YWItaGVhZGVyIFtwYW5lUmVmZXJlbmNlXT1cImMyXCIgW2ljb25dPVwiaWNvblRwbFwiIHNlY29uZGFyeUxhYmVsPVwiKDEvNClcIj5cclxuICogICAgIE1vbml0b3JpbmdcclxuICogICA8L2Nkcy10YWItaGVhZGVyPlxyXG4gKiA8L2Nkcy10YWItaGVhZGVyLWdyb3VwPlxyXG4gKiA8Y2RzLXRhYiAjYzE+Li4uPC9jZHMtdGFiPlxyXG4gKiA8Y2RzLXRhYiAjYzI+Li4uPC9jZHMtdGFiPlxyXG4gKiBgYGBcclxuICovXHJcbkBDb21wb25lbnQoe1xyXG5cdHNlbGVjdG9yOiBcImNkcy10YWItaGVhZGVyLCBpYm0tdGFiLWhlYWRlclwiLFxyXG5cdHByb3ZpZGVyczogW1xyXG5cdFx0Ly8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWZvcndhcmQtcmVmXHJcblx0XHR7IHByb3ZpZGU6IFRhYkhlYWRlckJhc2UsIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IFRhYkhlYWRlckNvbXBvbmVudCkgfVxyXG5cdF0sXHJcblx0dGVtcGxhdGU6IGBcclxuXHRcdDxjZHMtdG9vbHRpcFxyXG5cdFx0XHQqbmdJZj1cImljb25Pbmx5OyBlbHNlIHBsYWluQnV0dG9uXCJcclxuXHRcdFx0YWxpZ249XCJib3R0b21cIlxyXG5cdFx0XHRbYXV0b0FsaWduXT1cInRydWVcIlxyXG5cdFx0XHRjbGFzcz1cImNkcy0taWNvbi10b29sdGlwXCJcclxuXHRcdFx0W2Rlc2NyaXB0aW9uXT1cImljb25MYWJlbFwiXHJcblx0XHRcdFtlbnRlckRlbGF5TXNdPVwiZW50ZXJEZWxheU1zXCJcclxuXHRcdFx0W2xlYXZlRGVsYXlNc109XCJsZWF2ZURlbGF5TXNcIlxyXG5cdFx0XHRbaXNPcGVuXT1cImlzVG9vbHRpcE9wZW5cIlxyXG5cdFx0XHRbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIj5cclxuXHRcdFx0PG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRhYkJ1dHRvblRlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XHJcblx0XHQ8L2Nkcy10b29sdGlwPlxyXG5cdFx0PG5nLXRlbXBsYXRlICNwbGFpbkJ1dHRvbj5cclxuXHRcdFx0PG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRhYkJ1dHRvblRlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XHJcblx0XHQ8L25nLXRlbXBsYXRlPlxyXG5cdFx0PG5nLXRlbXBsYXRlICN0YWJCdXR0b25UZW1wbGF0ZT5cclxuXHRcdFx0PGJ1dHRvblxyXG5cdFx0XHRcdCN0YWJCdXR0b25cclxuXHRcdFx0XHR0eXBlPVwiYnV0dG9uXCJcclxuXHRcdFx0XHRyb2xlPVwidGFiXCJcclxuXHRcdFx0XHRjbGFzcz1cImNkcy0tdGFic19fbmF2LWl0ZW0gY2RzLS10YWJzX19uYXYtbGlua1wiXHJcblx0XHRcdFx0W25nQ2xhc3NdPVwie1xyXG5cdFx0XHRcdFx0J2Nkcy0tdGFic19fbmF2LWl0ZW0tLXNlbGVjdGVkJzogYWN0aXZlLFxyXG5cdFx0XHRcdFx0J2Nkcy0tdGFic19fbmF2LWl0ZW0tLWRpc2FibGVkJzogZGlzYWJsZWQsXHJcblx0XHRcdFx0XHQnY2RzLS10YWJzX19uYXYtaXRlbS0taWNvbi1vbmx5JzogaWNvbk9ubHksXHJcblx0XHRcdFx0XHQnY2RzLS10YWJzX19uYXYtaXRlbS0taWNvbi1vbmx5X18yMCc6IGljb25Pbmx5ICYmIGljb25TaXplID09PSAnbGcnXHJcblx0XHRcdFx0fVwiXHJcblx0XHRcdFx0W2F0dHIuYXJpYS1zZWxlY3RlZF09XCJhY3RpdmVcIlxyXG5cdFx0XHRcdFthdHRyLmFyaWEtZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxyXG5cdFx0XHRcdFthdHRyLmFyaWEtY29udHJvbHNdPVwicGFuZVJlZmVyZW5jZT8uaWQgfHwgbnVsbFwiXHJcblx0XHRcdFx0W2F0dHIuYXJpYS1sYWJlbF09XCJpY29uT25seSA/IGljb25MYWJlbCA6IG51bGxcIlxyXG5cdFx0XHRcdFthdHRyLnRhYmluZGV4XT1cImFjdGl2ZSA/IDAgOiAtMVwiXHJcblx0XHRcdFx0W2F0dHIudGl0bGVdPVwicmVzb2x2ZWRUaXRsZVwiXHJcblx0XHRcdFx0W2Rpc2FibGVkXT1cImRpc2FibGVkXCJcclxuXHRcdFx0XHQoY2xpY2spPVwib25UYWJCdXR0b25DbGljaygpXCJcclxuXHRcdFx0XHQoa2V5ZG93bik9XCJvblRhYkJ1dHRvbktleURvd24oJGV2ZW50KVwiPlxyXG5cdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCJpY29uT25seTsgZWxzZSBsYWJlbGVkVGFiXCI+XHJcblx0XHRcdFx0XHQ8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImljb25cIj48L25nLWNvbnRhaW5lcj5cclxuXHRcdFx0XHRcdDxzcGFuXHJcblx0XHRcdFx0XHRcdCpuZ0lmPVwiIWRpc2FibGVkICYmIGJhZGdlSW5kaWNhdG9yXCJcclxuXHRcdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLWJhZGdlLWluZGljYXRvclwiXHJcblx0XHRcdFx0XHRcdGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxyXG5cdFx0XHRcdFx0PC9zcGFuPlxyXG5cdFx0XHRcdDwvbmctY29udGFpbmVyPlxyXG5cdFx0XHRcdDxuZy10ZW1wbGF0ZSAjbGFiZWxlZFRhYj5cclxuXHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJjZHMtLXRhYnNfX25hdi1pdGVtLWxhYmVsLXdyYXBwZXJcIj5cclxuXHRcdFx0XHRcdFx0PGRpdiAqbmdJZj1cImRpc21pc3NhYmxlICYmIGljb25cIiBjbGFzcz1cImNkcy0tdGFic19fbmF2LWl0ZW0tLWljb24tbGVmdFwiPlxyXG5cdFx0XHRcdFx0XHRcdDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwiaWNvblwiPjwvbmctY29udGFpbmVyPlxyXG5cdFx0XHRcdFx0XHQ8L2Rpdj5cclxuXHRcdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJjZHMtLXRhYnNfX25hdi1pdGVtLWxhYmVsXCI+XHJcblx0XHRcdFx0XHRcdFx0PG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG5cdFx0XHRcdFx0XHQ8L3NwYW4+XHJcblx0XHRcdFx0XHRcdDxkaXYgKm5nSWY9XCIhZGlzbWlzc2FibGUgJiYgaWNvblwiIGNsYXNzPVwiY2RzLS10YWJzX19uYXYtaXRlbS0taWNvblwiPlxyXG5cdFx0XHRcdFx0XHRcdDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwiaWNvblwiPjwvbmctY29udGFpbmVyPlxyXG5cdFx0XHRcdFx0XHQ8L2Rpdj5cclxuXHRcdFx0XHRcdDwvZGl2PlxyXG5cdFx0XHRcdFx0PGRpdlxyXG5cdFx0XHRcdFx0XHQqbmdJZj1cInNlY29uZGFyeUxhYmVsXCJcclxuXHRcdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLXRhYnNfX25hdi1pdGVtLXNlY29uZGFyeS1sYWJlbFwiXHJcblx0XHRcdFx0XHRcdFthdHRyLnRpdGxlXT1cInNlY29uZGFyeUxhYmVsXCI+XHJcblx0XHRcdFx0XHRcdHt7IHNlY29uZGFyeUxhYmVsIH19XHJcblx0XHRcdFx0XHQ8L2Rpdj5cclxuXHRcdFx0XHQ8L25nLXRlbXBsYXRlPlxyXG5cdFx0XHQ8L2J1dHRvbj5cclxuXHRcdDwvbmctdGVtcGxhdGU+XHJcblx0XHQ8ZGl2ICpuZ0lmPVwiZGlzbWlzc2FibGVcIiBjbGFzcz1cImNkcy0tdGFic19fbmF2LWl0ZW0tLWNsb3NlXCI+XHJcblx0XHRcdDxidXR0b25cclxuXHRcdFx0XHR0eXBlPVwiYnV0dG9uXCJcclxuXHRcdFx0XHRjbGFzcz1cImNkcy0tdGFic19fbmF2LWl0ZW0tLWNsb3NlLWljb25cIlxyXG5cdFx0XHRcdFthdHRyLnRhYmluZGV4XT1cIi0xXCJcclxuXHRcdFx0XHRbYXR0ci5hcmlhLWRpc2FibGVkXT1cImRpc2FibGVkXCJcclxuXHRcdFx0XHRbYXR0ci5hcmlhLWhpZGRlbl09XCIhKGFjdGl2ZSAmJiAhZGlzYWJsZWQpXCJcclxuXHRcdFx0XHRbbmdDbGFzc109XCJ7XHJcblx0XHRcdFx0XHQnY2RzLS10YWJzX19uYXYtaXRlbS0tY2xvc2UtaWNvbi0tc2VsZWN0ZWQnOiBhY3RpdmUsXHJcblx0XHRcdFx0XHQnY2RzLS10YWJzX19uYXYtaXRlbS0tY2xvc2UtaWNvbi0tZGlzYWJsZWQnOiBkaXNhYmxlZFxyXG5cdFx0XHRcdH1cIlxyXG5cdFx0XHRcdFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXHJcblx0XHRcdFx0W2F0dHIudGl0bGVdPVwiY2xvc2VCdXR0b25UaXRsZVwiXHJcblx0XHRcdFx0KGNsaWNrKT1cIm9uQ2xvc2UoJGV2ZW50KVwiPlxyXG5cdFx0XHRcdDxzdmdcclxuXHRcdFx0XHRcdGZvY3VzYWJsZT1cImZhbHNlXCJcclxuXHRcdFx0XHRcdHByZXNlcnZlQXNwZWN0UmF0aW89XCJ4TWlkWU1pZCBtZWV0XCJcclxuXHRcdFx0XHRcdHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIlxyXG5cdFx0XHRcdFx0ZmlsbD1cImN1cnJlbnRDb2xvclwiXHJcblx0XHRcdFx0XHR3aWR0aD1cIjE2XCJcclxuXHRcdFx0XHRcdGhlaWdodD1cIjE2XCJcclxuXHRcdFx0XHRcdHZpZXdCb3g9XCIwIDAgMzIgMzJcIlxyXG5cdFx0XHRcdFx0W2F0dHIuYXJpYS1sYWJlbF09XCJjbG9zZUJ1dHRvbkFyaWFMYWJlbFwiXHJcblx0XHRcdFx0XHRbYXR0ci5hcmlhLWhpZGRlbl09XCIhKGFjdGl2ZSAmJiAhZGlzYWJsZWQpXCI+XHJcblx0XHRcdFx0XHQ8cGF0aCBkPVwiTTE3LjQxNDEgMTZMMjQgOS40MTQxIDIyLjU4NTkgOCAxNiAxNC41ODU5IDkuNDE0MyA4IDggOS40MTQxIDE0LjU4NTkgMTYgOCAyMi41ODU5IDkuNDE0MyAyNCAxNiAxNy40MTQxIDIyLjU4NTkgMjQgMjQgMjIuNTg1OSAxNy40MTQxIDE2elwiPjwvcGF0aD5cclxuXHRcdFx0XHQ8L3N2Zz5cclxuXHRcdFx0PC9idXR0b24+XHJcblx0XHQ8L2Rpdj5cclxuXHRgXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBUYWJIZWFkZXJDb21wb25lbnQgZXh0ZW5kcyBUYWJIZWFkZXJCYXNlIGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCB7XHJcblx0LyoqXHJcblx0ICogSWNvbi1vbmx5IHRhYjogc2V0IGBpY29uYCBhbmQgYGljb25MYWJlbGAuXHJcblx0ICovXHJcblx0QElucHV0KCkgaWNvbk9ubHkgPSBmYWxzZTtcclxuXHQvKipcclxuXHQgKiBJY29uLW9ubHkgdGFiczogYWNjZXNzaWJsZSBuYW1lIChgYXJpYS1sYWJlbGAgLyBgdGl0bGVgKS5cclxuXHQgKi9cclxuXHRASW5wdXQoKSBpY29uTGFiZWw6IHN0cmluZztcclxuXHQvKipcclxuXHQgKiAqKlByZXZpZXcqKjogSWNvbi1vbmx5IHRhYnMg4oCUIHNob3cgYSBub3RpZmljYXRpb24gZG90IG9uIHRoZSBpY29uLlxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIGJhZGdlSW5kaWNhdG9yID0gZmFsc2U7XHJcblx0LyoqXHJcblx0ICogSWNvbi1vbmx5IHRhYnM6IGljb24gc2l6ZSBgZGVmYXVsdGAgKDE2cHgpIG9yIGBsZ2AgKDIwcHgpOyB1c3VhbGx5IHNldCBvbiB0aGUgcGFyZW50IGdyb3VwLlxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIGljb25TaXplOiBcImRlZmF1bHRcIiB8IFwibGdcIiA9IFwiZGVmYXVsdFwiO1xyXG5cdC8qKlxyXG5cdCAqIGBhcmlhLWxhYmVsYCBmb3IgdGhlIGRpc21pc3NhYmxlIGNsb3NlIGJ1dHRvbi5cclxuXHQgKi9cclxuXHRASW5wdXQoKSBjbG9zZUJ1dHRvbkFyaWFMYWJlbCA9IFwiUHJlc3MgZGVsZXRlIHRvIHJlbW92ZSB0YWJcIjtcclxuXHQvKipcclxuXHQgKiBJY29uLW9ubHkgdGFiczogdG9vbHRpcCBzaG93IGRlbGF5IChtcykuXHJcblx0ICovXHJcblx0QElucHV0KCkgZW50ZXJEZWxheU1zOiBudW1iZXI7XHJcblx0LyoqXHJcblx0ICogSWNvbi1vbmx5IHRhYnM6IHRvb2x0aXAgaGlkZSBkZWxheSAobXMpLlxyXG5cdCAqL1xyXG5cdEBJbnB1dCgpIGxlYXZlRGVsYXlNczogbnVtYmVyO1xyXG5cdC8qKlxyXG5cdCAqIEljb24tb25seSB0YWJzOiBvcGVuIHRoZSB0b29sdGlwIG9uIGZpcnN0IHJlbmRlci5cclxuXHQgKi9cclxuXHRASW5wdXQoKSBpc1Rvb2x0aXBPcGVuID0gZmFsc2U7XHJcblxyXG5cdEBIb3N0QmluZGluZyhcInN0eWxlLmRpc3BsYXlcIikgZGlzcGxheUNvbnRlbnRzID0gXCJjb250ZW50c1wiO1xyXG5cclxuXHRAVmlld0NoaWxkKFwidGFiQnV0dG9uXCIpIHRhYkJ1dHRvbjogRWxlbWVudFJlZjxIVE1MQnV0dG9uRWxlbWVudD47XHJcblxyXG5cdG5nQWZ0ZXJWaWV3SW5pdCgpIHtcclxuXHRcdC8vIE1pcnJvciB0aGUgZGVwcmVjYXRlZCBkaXJlY3RpdmUncyB0aXRsZS1mYWxsYmFjayBiZWhhdmlvciwgYnV0IHJlYWRcclxuXHRcdC8vIGZyb20gdGhlIGlubmVyIHJlbmRlcmVkIGJ1dHRvbiByYXRoZXIgdGhhbiB0aGUgYGRpc3BsYXk6IGNvbnRlbnRzYCBob3N0LlxyXG5cdFx0c2V0VGltZW91dCgoKSA9PiB7XHJcblx0XHRcdGlmICghdGhpcy50aXRsZSAmJiB0aGlzLnRhYkJ1dHRvbj8ubmF0aXZlRWxlbWVudCkge1xyXG5cdFx0XHRcdGNvbnN0IHRleHQgPSB0aGlzLnRhYkJ1dHRvbi5uYXRpdmVFbGVtZW50LnRleHRDb250ZW50Py50cmltKCk7XHJcblx0XHRcdFx0aWYgKHRleHQpIHtcclxuXHRcdFx0XHRcdHRoaXMudGl0bGUgPSB0ZXh0O1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBGb2N1cyB0aGUgcmVuZGVyZWQgdGFiIGJ1dHRvbiAobm90IHRoZSBob3N0KS5cclxuXHQgKi9cclxuXHRmb2N1cygpIHtcclxuXHRcdHRoaXMudGFiQnV0dG9uPy5uYXRpdmVFbGVtZW50Py5mb2N1cygpO1xyXG5cdH1cclxuXHJcblx0b25UYWJCdXR0b25DbGljaygpIHtcclxuXHRcdHRoaXMuc2VsZWN0VGFiKCk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBgRGVsZXRlYCBjbG9zZXMgZGlzbWlzc2FibGUgdGFicyB3aGVuIGZvY3VzIGlzIG9uIHRoZSB0YWIuXHJcblx0ICovXHJcblx0b25UYWJCdXR0b25LZXlEb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XHJcblx0XHRpZiAodGhpcy5kaXNtaXNzYWJsZSAmJiBldmVudC5rZXkgPT09IFwiRGVsZXRlXCIpIHtcclxuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcblx0XHRcdHRoaXMudGFiQ2xvc2UuZW1pdCgpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogQ2xvc2UgYnV0dG9uIGNsaWNrOyBzdG9wcyBwcm9wYWdhdGlvbiBzbyB0aGUgdGFiIGRvZXMgbm90IGFjdGl2YXRlLlxyXG5cdCAqL1xyXG5cdG9uQ2xvc2UoZXZlbnQ6IEV2ZW50KSB7XHJcblx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuXHRcdGlmICh0aGlzLmRpc2FibGVkKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHRcdHRoaXMudGFiQ2xvc2UuZW1pdCgpO1xyXG5cdH1cclxuXHJcblx0Z2V0IHJlc29sdmVkVGl0bGUoKTogc3RyaW5nIHwgbnVsbCB7XHJcblx0XHRpZiAodGhpcy5pY29uT25seSkge1xyXG5cdFx0XHRyZXR1cm4gdGhpcy5pY29uTGFiZWwgfHwgbnVsbDtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzLnRpdGxlIHx8IG51bGw7XHJcblx0fVxyXG5cclxuXHRnZXQgY2xvc2VCdXR0b25UaXRsZSgpOiBzdHJpbmcge1xyXG5cdFx0Y29uc3QgbGFiZWwgPSB0aGlzLnRhYkJ1dHRvbj8ubmF0aXZlRWxlbWVudD8udGV4dENvbnRlbnQ/LnRyaW0oKTtcclxuXHRcdHJldHVybiBsYWJlbCA/IGBSZW1vdmUgJHtsYWJlbH0gdGFiYCA6IFwiUmVtb3ZlIHRhYlwiO1xyXG5cdH1cclxufVxyXG4iXX0=