carbon-components-angular
Version:
Next generation components
322 lines • 25.9 kB
JavaScript
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=