UNPKG

carbon-components-angular

Version:
657 lines 62 kB
import { Component, Input, Output, EventEmitter, HostListener, HostBinding, ViewChild, ContentChildren, ViewChildren } from "@angular/core"; import { BaseTabHeader } from "./base-tab-header.component"; import { Tab } from "./tab.component"; import * as i0 from "@angular/core"; import * as i1 from "carbon-components-angular/utils"; import * as i2 from "carbon-components-angular/i18n"; import * as i3 from "@angular/common"; import * as i4 from "carbon-components-angular/tooltip"; /** * The `TabHeaders` component contains the `Tab` items and controls scroll functionality * if content has overflow. */ export class TabHeaders extends BaseTabHeader { constructor(elementRef, changeDetectorRef, eventService, renderer, i18n) { super(elementRef, changeDetectorRef, eventService, renderer); this.elementRef = elementRef; this.changeDetectorRef = changeDetectorRef; this.eventService = eventService; this.renderer = renderer; this.i18n = i18n; /** * i18n strings for overflow controls and the tab list `aria-label` fallback. */ this.translations = this.i18n.get().TABS; /** * Emits when a tab close control is used (with `dismissable`). * The emitted value is the tab index. */ this.tabClose = new EventEmitter(); /** * The index of the first visible tab. */ this.firstVisibleTab = 0; /** * Focused tab index when `followFocus` is false (manual activation). */ this.activeIndex = null; } get tallClass() { return this.hasSecondaryLabelTabs; } get fullWidthClass() { return this.distributeWidth; } get hasSecondaryLabelTabs() { if (!this.tabs || this.type !== "contained") { return false; } return this.tabs.toArray().some(tab => typeof tab.secondaryLabel !== "undefined" && tab.secondaryLabel !== null); } /** * True when `fullWidth` applies (contained, fewer than 9 tabs). */ get distributeWidth() { return (this.fullWidth && this.type === "contained" && (this.tabs ? this.tabs.length < 9 : false)); } // keyboard accessibility /** * Controls the keydown events used for tabbing through the headings. */ keyboardInput(event) { const tabsArray = this.tabs.toArray(); const enabledTabs = tabsArray.filter(tab => !tab.disabled); if (enabledTabs.length === 0) { return; } const referenceIndex = this.followFocus ? this.currentSelectedTab : (this.activeIndex !== null ? this.activeIndex : this.currentSelectedTab); const currentEnabledIndex = Math.max(0, enabledTabs.indexOf(tabsArray[referenceIndex])); let nextEnabledIndex = currentEnabledIndex; let handled = false; if (event.key === "ArrowRight") { nextEnabledIndex = (currentEnabledIndex + 1) % enabledTabs.length; handled = true; } else if (event.key === "ArrowLeft") { nextEnabledIndex = (enabledTabs.length + currentEnabledIndex - 1) % enabledTabs.length; handled = true; } else if (event.key === "Home") { nextEnabledIndex = 0; handled = true; } else if (event.key === "End") { nextEnabledIndex = enabledTabs.length - 1; handled = true; } if (handled) { event.preventDefault(); const nextTab = enabledTabs[nextEnabledIndex]; const nextIndex = tabsArray.indexOf(nextTab); if (this.followFocus) { this.selectTab(this.allTabHeaders.toArray()[nextIndex].nativeElement, nextTab, nextIndex); } else { this.activeIndex = nextIndex; } this.allTabHeaders.toArray()[nextIndex].nativeElement.focus(); return; } if ((event.key === " " || event.key === "Spacebar") && !this.followFocus) { const focusIndex = this.activeIndex !== null ? this.activeIndex : this.currentSelectedTab; this.selectTab(this.allTabHeaders.toArray()[focusIndex].nativeElement, tabsArray[focusIndex], focusIndex); } } handleBlur(event) { const relatedTarget = event.relatedTarget; const container = this.headerContainer?.nativeElement; if (container && relatedTarget && container.contains(relatedTarget)) { return; } // Reset active index to selected tab index when followFocus is false if (!this.followFocus) { this.activeIndex = this.currentSelectedTab; } } /** * `Delete` closes dismissable tabs. */ handleTabKeyDown(event, tab, index) { if (this.dismissable && event.key === "Delete") { this.handleClose(event, tab, index); } } ngOnInit() { // Update scroll on resize this.resizeObserver = new ResizeObserver(() => { // Need to explicitly trigger change detection since this runs outside Angular zone this.changeDetectorRef.detectChanges(); }); this.resizeObserver.observe(this.headerContainer.nativeElement); } ngOnDestroy() { this.resizeObserver?.unobserve(this.headerContainer.nativeElement); clearTimeout(this.scrollDebounceTimer); } ngAfterContentInit() { if (!this.tabInput) { this.tabs = this.tabQuery; } else { this.tabs = this.tabInput; } this.tabs.forEach(tab => tab.cacheActive = this.cacheActive); this.tabs.changes.subscribe(() => { this.setFirstTab(); this.changeDetectorRef.markForCheck(); }); this.setFirstTab(); } ngOnChanges(changes) { if (this.tabs && changes.cacheActive) { this.tabs.forEach(tab => tab.cacheActive = this.cacheActive); } } /** * Controls manually focusing tabs. */ onTabFocus(ref, index) { if (this.followFocus) { this.currentSelectedTab = index; } else { this.activeIndex = index; } // reset scroll left because we're already handling it this.headerContainer.nativeElement.parentElement.scrollLeft = 0; if (this.scrollIntoView) { this.scrollTabIntoView(this.allTabHeaders.toArray()[index]?.nativeElement); } } getSelectedTab() { const selected = this.tabs.find(tab => tab.active); if (selected) { return selected; } return { headingIsTemplate: false, heading: "" }; } /** * Selects `Tab` 'tab' and moves it into view on the view DOM if it is not already. */ selectTab(ref, tab, tabIndex) { if (tab.disabled) { return; } this.currentSelectedTab = tabIndex; this.activeIndex = tabIndex; this.tabs.forEach(_tab => _tab.active = false); tab.active = true; tab.doSelect(); if (this.scrollIntoView) { this.scrollTabIntoView(this.allTabHeaders.toArray()[tabIndex]?.nativeElement); } } /** * Emit close index and move focus to a nearby enabled tab. */ handleClose(event, tab, tabIndex) { event.stopPropagation(); if (tab.disabled) { return; } tab.tabClose.emit(); this.tabClose.emit(tabIndex); // Move focus to a neighboring enabled tab (next-then-previous). const headers = this.allTabHeaders?.toArray() ?? []; const findNextEnabled = (start, step) => { let i = start; while (i >= 0 && i < headers.length) { const candidate = this.tabs.toArray()[i]; if (candidate && !candidate.disabled && i !== tabIndex) { return headers[i]?.nativeElement; } i += step; } return null; }; const nextEl = findNextEnabled(tabIndex + 1, 1) || findNextEnabled(tabIndex - 1, -1); if (nextEl) { nextEl.focus(); } } getCloseTitle(tab) { const label = !tab.headingIsTemplate && typeof tab.heading === "string" ? ` ${tab.heading}` : ""; return `Remove${label} tab`; } /** * Scroll the given tab element into view if it is not already visible. */ scrollTabIntoView(tabEl) { if (!tabEl || !this.headerContainer?.nativeElement) { return; } const container = this.headerContainer.nativeElement; if (container.scrollWidth <= container.clientWidth) { return; } const buttonWidth = this.OVERFLOW_BUTTON_OFFSET; const tabWidth = tabEl.getBoundingClientRect().width; const start = tabEl.offsetLeft; const end = start + tabWidth; const visibleStart = container.scrollLeft + buttonWidth; const visibleEnd = container.scrollLeft + container.clientWidth - buttonWidth; if (start < visibleStart) { container.scrollLeft = start - buttonWidth; } else if (end > visibleEnd) { container.scrollLeft = end + buttonWidth - container.clientWidth; } } /** * Determines which `Tab` is initially selected. */ setFirstTab() { setTimeout(() => { let firstTab = this.tabs.find(tab => tab.active); if (!firstTab && this.tabs.first) { firstTab = this.tabs.first; firstTab.active = true; } if (firstTab) { this.currentSelectedTab = this.tabs.toArray().indexOf(firstTab); this.activeIndex = this.currentSelectedTab; firstTab.doSelect(); } }); } } TabHeaders.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TabHeaders, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i1.EventService }, { token: i0.Renderer2 }, { token: i2.I18n }], target: i0.ɵɵFactoryTarget.Component }); TabHeaders.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: TabHeaders, selector: "cds-tab-headers, ibm-tab-headers", inputs: { tabInput: ["tabs", "tabInput"], translations: "translations" }, outputs: { tabClose: "tabClose" }, host: { listeners: { "keydown": "keyboardInput($event)", "blur": "handleBlur($event)" }, properties: { "class.cds--tabs--tall": "this.tallClass", "class.cds--tabs--full-width": "this.fullWidthClass" } }, queries: [{ propertyName: "tabQuery", predicate: Tab }], viewQueries: [{ propertyName: "headerContainer", first: true, predicate: ["tabList"], descendants: true, static: true }, { propertyName: "allTabHeaders", predicate: ["tabItem"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: ` <button type="button" (click)="handleOverflowNavClick(-1, tabs.length)" (pointerdown)="handleOverflowNavMouseDown(-1)" (pointerup)="handleOverflowNavMouseUp()" (pointerleave)="handleOverflowNavMouseUp()" (pointerout)="handleOverflowNavMouseUp()" class="cds--tab--overflow-nav-button cds--tab--overflow-nav-button--previous" [ngClass]="{ 'cds--tab--overflow-nav-button--hidden': leftOverflowNavButtonHidden }" [attr.aria-hidden]="leftOverflowNavButtonHidden" [attr.tabindex]="-1" [attr.aria-label]="translations.BUTTON_ARIA_LEFT" [attr.title]="translations.BUTTON_ARIA_LEFT"> <svg focusable="false" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"> <path d="M5 8L10 3 10.7 3.7 6.4 8 10.7 12.3 10 13z"></path> </svg> </button> <div #tabList class="cds--tab--list" role="tablist" [attr.aria-label]="ariaLabel || translations.HEADER_ARIA_LABEL" [attr.aria-labelledby]="ariaLabelledby || null" (scroll)="handleScroll()"> <ng-container [ngTemplateOutlet]="contentBefore"></ng-container> <ng-container *ngFor="let tab of tabs; let i = index;"> <cds-tooltip *ngIf="tab.iconOnly; else inlineTabItem" align="bottom" [autoAlign]="true" class="cds--icon-tooltip" [description]="tab.iconLabel" [enterDelayMs]="tab.enterDelayMs ?? 100" [leaveDelayMs]="tab.leaveDelayMs ?? 300" [isOpen]="tab.isTooltipOpen" [disabled]="tab.disabled"> <ng-container *ngTemplateOutlet="tabItemTpl; context: { tab: tab, i: i }"></ng-container> </cds-tooltip> <ng-template #inlineTabItem> <ng-container *ngTemplateOutlet="tabItemTpl; context: { tab: tab, i: i }"></ng-container> </ng-template> <div *ngIf="dismissable" class="cds--tabs__nav-item--close"> <button type="button" [attr.tabindex]="-1" [attr.aria-disabled]="tab.disabled" [attr.aria-hidden]="!(tab.active && !tab.disabled)" [disabled]="tab.disabled" class="cds--tabs__nav-item--close-icon" [ngClass]="{ 'cds--tabs__nav-item--close-icon--selected': tab.active, 'cds--tabs__nav-item--close-icon--disabled': tab.disabled }" [attr.title]="getCloseTitle(tab)" (click)="handleClose($event, tab, i)"> <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]="tab.closeButtonAriaLabel" [attr.aria-hidden]="!(tab.active && !tab.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> </ng-container> <ng-container [ngTemplateOutlet]="contentAfter"></ng-container> </div> <ng-template #tabItemTpl let-tab="tab" let-i="i"> <button #tabItem role="tab" [attr.aria-selected]="tab.active" [attr.tabindex]="(tab.active?0:-1)" [attr.aria-controls]="tab.id" [attr.aria-disabled]="tab.disabled" [attr.aria-label]="tab.iconOnly ? tab.iconLabel : null" [disabled]="tab.disabled" [ngClass]="{ 'cds--tabs__nav-item--selected': tab.active, 'cds--tabs__nav-item--disabled': tab.disabled, 'cds--tabs__nav-item--icon-only': tab.iconOnly, 'cds--tabs__nav-item--icon-only__20': tab.iconOnly && iconSize === 'lg' }" class="cds--tabs__nav-item cds--tabs__nav-link" type="button" draggable="false" id="{{tab.id}}-header" [attr.title]="tab.iconOnly ? tab.iconLabel : (tab.title || (!tab.headingIsTemplate ? tab.heading : null))" (focus)="onTabFocus(tabItem, i)" (keydown)="handleTabKeyDown($event, tab, i)" (click)="selectTab(tabItem, tab, i)"> <ng-container *ngIf="tab.iconOnly; else labeledTab"> <ng-container [ngTemplateOutlet]="tab.icon"></ng-container> <span *ngIf="!tab.disabled && tab.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 && tab.icon" class="cds--tabs__nav-item--icon-left"> <ng-container [ngTemplateOutlet]="tab.icon"></ng-container> </div> <span class="cds--tabs__nav-item-label"> <ng-container *ngIf="!tab.headingIsTemplate"> {{ tab.heading }} </ng-container> <ng-template *ngIf="tab.headingIsTemplate" [ngTemplateOutlet]="tab.heading" [ngTemplateOutletContext]="{$implicit: tab.context}"> </ng-template> </span> <div *ngIf="!dismissable && tab.icon" class="cds--tabs__nav-item--icon"> <ng-container [ngTemplateOutlet]="tab.icon"></ng-container> </div> </div> <div *ngIf="hasSecondaryLabelTabs && tab.secondaryLabel" class="cds--tabs__nav-item-secondary-label" [attr.title]="tab.secondaryLabel"> {{ tab.secondaryLabel }} </div> </ng-template> </button> </ng-template> <button type="button" (click)="handleOverflowNavClick(1, tabs.length)" (pointerdown)="handleOverflowNavMouseDown(1)" (pointerup)="handleOverflowNavMouseUp()" (pointerleave)="handleOverflowNavMouseUp()" (pointerout)="handleOverflowNavMouseUp()" class="cds--tab--overflow-nav-button cds--tab--overflow-nav-button--next" [ngClass]="{ 'cds--tab--overflow-nav-button--hidden': rightOverflowNavButtonHidden }" [attr.aria-hidden]="rightOverflowNavButtonHidden" [attr.tabindex]="-1" [attr.aria-label]="translations.BUTTON_ARIA_RIGHT" [attr.title]="translations.BUTTON_ARIA_RIGHT"> <svg focusable="false" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"> <path d="M11 8L6 13 5.3 12.3 9.6 8 5.3 3.7 6 3z"></path> </svg> </button> `, isInline: true, dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.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: TabHeaders, decorators: [{ type: Component, args: [{ selector: "cds-tab-headers, ibm-tab-headers", template: ` <button type="button" (click)="handleOverflowNavClick(-1, tabs.length)" (pointerdown)="handleOverflowNavMouseDown(-1)" (pointerup)="handleOverflowNavMouseUp()" (pointerleave)="handleOverflowNavMouseUp()" (pointerout)="handleOverflowNavMouseUp()" class="cds--tab--overflow-nav-button cds--tab--overflow-nav-button--previous" [ngClass]="{ 'cds--tab--overflow-nav-button--hidden': leftOverflowNavButtonHidden }" [attr.aria-hidden]="leftOverflowNavButtonHidden" [attr.tabindex]="-1" [attr.aria-label]="translations.BUTTON_ARIA_LEFT" [attr.title]="translations.BUTTON_ARIA_LEFT"> <svg focusable="false" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"> <path d="M5 8L10 3 10.7 3.7 6.4 8 10.7 12.3 10 13z"></path> </svg> </button> <div #tabList class="cds--tab--list" role="tablist" [attr.aria-label]="ariaLabel || translations.HEADER_ARIA_LABEL" [attr.aria-labelledby]="ariaLabelledby || null" (scroll)="handleScroll()"> <ng-container [ngTemplateOutlet]="contentBefore"></ng-container> <ng-container *ngFor="let tab of tabs; let i = index;"> <cds-tooltip *ngIf="tab.iconOnly; else inlineTabItem" align="bottom" [autoAlign]="true" class="cds--icon-tooltip" [description]="tab.iconLabel" [enterDelayMs]="tab.enterDelayMs ?? 100" [leaveDelayMs]="tab.leaveDelayMs ?? 300" [isOpen]="tab.isTooltipOpen" [disabled]="tab.disabled"> <ng-container *ngTemplateOutlet="tabItemTpl; context: { tab: tab, i: i }"></ng-container> </cds-tooltip> <ng-template #inlineTabItem> <ng-container *ngTemplateOutlet="tabItemTpl; context: { tab: tab, i: i }"></ng-container> </ng-template> <div *ngIf="dismissable" class="cds--tabs__nav-item--close"> <button type="button" [attr.tabindex]="-1" [attr.aria-disabled]="tab.disabled" [attr.aria-hidden]="!(tab.active && !tab.disabled)" [disabled]="tab.disabled" class="cds--tabs__nav-item--close-icon" [ngClass]="{ 'cds--tabs__nav-item--close-icon--selected': tab.active, 'cds--tabs__nav-item--close-icon--disabled': tab.disabled }" [attr.title]="getCloseTitle(tab)" (click)="handleClose($event, tab, i)"> <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]="tab.closeButtonAriaLabel" [attr.aria-hidden]="!(tab.active && !tab.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> </ng-container> <ng-container [ngTemplateOutlet]="contentAfter"></ng-container> </div> <ng-template #tabItemTpl let-tab="tab" let-i="i"> <button #tabItem role="tab" [attr.aria-selected]="tab.active" [attr.tabindex]="(tab.active?0:-1)" [attr.aria-controls]="tab.id" [attr.aria-disabled]="tab.disabled" [attr.aria-label]="tab.iconOnly ? tab.iconLabel : null" [disabled]="tab.disabled" [ngClass]="{ 'cds--tabs__nav-item--selected': tab.active, 'cds--tabs__nav-item--disabled': tab.disabled, 'cds--tabs__nav-item--icon-only': tab.iconOnly, 'cds--tabs__nav-item--icon-only__20': tab.iconOnly && iconSize === 'lg' }" class="cds--tabs__nav-item cds--tabs__nav-link" type="button" draggable="false" id="{{tab.id}}-header" [attr.title]="tab.iconOnly ? tab.iconLabel : (tab.title || (!tab.headingIsTemplate ? tab.heading : null))" (focus)="onTabFocus(tabItem, i)" (keydown)="handleTabKeyDown($event, tab, i)" (click)="selectTab(tabItem, tab, i)"> <ng-container *ngIf="tab.iconOnly; else labeledTab"> <ng-container [ngTemplateOutlet]="tab.icon"></ng-container> <span *ngIf="!tab.disabled && tab.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 && tab.icon" class="cds--tabs__nav-item--icon-left"> <ng-container [ngTemplateOutlet]="tab.icon"></ng-container> </div> <span class="cds--tabs__nav-item-label"> <ng-container *ngIf="!tab.headingIsTemplate"> {{ tab.heading }} </ng-container> <ng-template *ngIf="tab.headingIsTemplate" [ngTemplateOutlet]="tab.heading" [ngTemplateOutletContext]="{$implicit: tab.context}"> </ng-template> </span> <div *ngIf="!dismissable && tab.icon" class="cds--tabs__nav-item--icon"> <ng-container [ngTemplateOutlet]="tab.icon"></ng-container> </div> </div> <div *ngIf="hasSecondaryLabelTabs && tab.secondaryLabel" class="cds--tabs__nav-item-secondary-label" [attr.title]="tab.secondaryLabel"> {{ tab.secondaryLabel }} </div> </ng-template> </button> </ng-template> <button type="button" (click)="handleOverflowNavClick(1, tabs.length)" (pointerdown)="handleOverflowNavMouseDown(1)" (pointerup)="handleOverflowNavMouseUp()" (pointerleave)="handleOverflowNavMouseUp()" (pointerout)="handleOverflowNavMouseUp()" class="cds--tab--overflow-nav-button cds--tab--overflow-nav-button--next" [ngClass]="{ 'cds--tab--overflow-nav-button--hidden': rightOverflowNavButtonHidden }" [attr.aria-hidden]="rightOverflowNavButtonHidden" [attr.tabindex]="-1" [attr.aria-label]="translations.BUTTON_ARIA_RIGHT" [attr.title]="translations.BUTTON_ARIA_RIGHT"> <svg focusable="false" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"> <path d="M11 8L6 13 5.3 12.3 9.6 8 5.3 3.7 6 3z"></path> </svg> </button> ` }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i1.EventService }, { type: i0.Renderer2 }, { type: i2.I18n }]; }, propDecorators: { tabInput: [{ type: Input, args: ["tabs"] }], translations: [{ type: Input }], tabClose: [{ type: Output }], headerContainer: [{ type: ViewChild, args: ["tabList", { static: true }] }], tabQuery: [{ type: ContentChildren, args: [Tab] }], allTabHeaders: [{ type: ViewChildren, args: ["tabItem"] }], tallClass: [{ type: HostBinding, args: ["class.cds--tabs--tall"] }], fullWidthClass: [{ type: HostBinding, args: ["class.cds--tabs--full-width"] }], keyboardInput: [{ type: HostListener, args: ["keydown", ["$event"]] }], handleBlur: [{ type: HostListener, args: ["blur", ["$event"]] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFiLWhlYWRlcnMuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RhYnMvdGFiLWhlYWRlcnMuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTixTQUFTLEVBRVQsS0FBSyxFQUNMLE1BQU0sRUFDTixZQUFZLEVBQ1osWUFBWSxFQUNaLFdBQVcsRUFDWCxTQUFTLEVBQ1QsZUFBZSxFQUVmLFlBQVksRUFRWixNQUFNLGVBQWUsQ0FBQztBQUl2QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDNUQsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7Ozs7QUFFdEM7OztHQUdHO0FBb0xILE1BQU0sT0FBTyxVQUFXLFNBQVEsYUFBYTtJQXVENUMsWUFDVyxVQUFzQixFQUN0QixpQkFBb0MsRUFDcEMsWUFBMEIsRUFDMUIsUUFBbUIsRUFDbkIsSUFBVTtRQUVwQixLQUFLLENBQUMsVUFBVSxFQUFFLGlCQUFpQixFQUFFLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQztRQU5uRCxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBQ3RCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDMUIsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQUNuQixTQUFJLEdBQUosSUFBSSxDQUFNO1FBcERyQjs7V0FFRztRQUNNLGlCQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUM7UUFFN0M7OztXQUdHO1FBQ08sYUFBUSxHQUF5QixJQUFJLFlBQVksRUFBVSxDQUFDO1FBY3RFOztXQUVHO1FBQ0gsb0JBQWUsR0FBRyxDQUFDLENBQUM7UUFNcEI7O1dBRUc7UUFDSCxnQkFBVyxHQUFrQixJQUFJLENBQUM7SUFvQmxDLENBQUM7SUFsQkQsSUFBMEMsU0FBUztRQUNsRCxP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QVM7Z0JBT21CLFNBQVM7c0JBQWxELFdBQVc7dUJBQUMsdUJBQXVCO2dCQUlZLGNBQWM7c0JBQTdELFdBQVc7dUJBQUMsNkJBQTZCO2dCQXVDMUMsYUFBYTtzQkFEWixZQUFZO3VCQUFDLFNBQVMsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFtRG5DLFVBQVU7c0JBRFQsWUFBWTt1QkFBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuXHRDb21wb25lbnQsXG5cdFF1ZXJ5TGlzdCxcblx0SW5wdXQsXG5cdE91dHB1dCxcblx0RXZlbnRFbWl0dGVyLFxuXHRIb3N0TGlzdGVuZXIsXG5cdEhvc3RCaW5kaW5nLFxuXHRWaWV3Q2hpbGQsXG5cdENvbnRlbnRDaGlsZHJlbixcblx0QWZ0ZXJDb250ZW50SW5pdCxcblx0Vmlld0NoaWxkcmVuLFxuXHRFbGVtZW50UmVmLFxuXHRPbkNoYW5nZXMsXG5cdFNpbXBsZUNoYW5nZXMsXG5cdE9uRGVzdHJveSxcblx0T25Jbml0LFxuXHRDaGFuZ2VEZXRlY3RvclJlZixcblx0UmVuZGVyZXIyXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBFdmVudFNlcnZpY2UgfSBmcm9tIFwiY2FyYm9uLWNvbXBvbmVudHMtYW5ndWxhci91dGlsc1wiO1xuaW1wb3J0IHsgSTE4biB9IGZyb20gXCJjYXJib24tY29tcG9uZW50cy1hbmd1bGFyL2kxOG5cIjtcblxuaW1wb3J0IHsgQmFzZVRhYkhlYWRlciB9IGZyb20gXCIuL2Jhc2UtdGFiLWhlYWRlci5jb21wb25lbnRcIjtcbmltcG9ydCB7IFRhYiB9IGZyb20gXCIuL3RhYi5jb21wb25lbnRcIjtcblxuLyoqXG4gKiBUaGUgYFRhYkhlYWRlcnNgIGNvbXBvbmVudCBjb250YWlucyB0aGUgYFRhYmAgaXRlbXMgYW5kIGNvbnRyb2xzIHNjcm9sbCBmdW5jdGlvbmFsaXR5XG4gKiBpZiBjb250ZW50IGhhcyBvdmVyZmxvdy5cbiAqL1xuQENvbXBvbmVudCh7XG5cdHNlbGVjdG9yOiBcImNkcy10YWItaGVhZGVycywgaWJtLXRhYi1oZWFkZXJzXCIsXG5cdHRlbXBsYXRlOiBgXG5cdFx0PGJ1dHRvblxuXHRcdFx0dHlwZT1cImJ1dHRvblwiXG5cdFx0XHQoY2xpY2spPVwiaGFuZGxlT3ZlcmZsb3dOYXZDbGljaygtMSwgdGFicy5sZW5ndGgpXCJcblx0XHRcdChwb2ludGVyZG93bik9XCJoYW5kbGVPdmVyZmxvd05hdk1vdXNlRG93bigtMSlcIlxuXHRcdFx0KHBvaW50ZXJ1cCk9XCJoYW5kbGVPdmVyZmxvd05hdk1vdXNlVXAoKVwiXG5cdFx0XHQocG9pbnRlcmxlYXZlKT1cImhhbmRsZU92ZXJmbG93TmF2TW91c2VVcCgpXCJcblx0XHRcdChwb2ludGVyb3V0KT1cImhhbmRsZU92ZXJmbG93TmF2TW91c2VVcCgpXCJcblx0XHRcdGNsYXNzPVwiY2RzLS10YWItLW92ZXJmbG93LW5hdi1idXR0b24gY2RzLS10YWItLW92ZXJmbG93LW5hdi1idXR0b24tLXByZXZpb3VzXCJcblx0XHRcdFtuZ0NsYXNzXT1cIntcblx0XHRcdFx0J2Nkcy0tdGFiLS1vdmVyZmxvdy1uYXYtYnV0dG9uLS1oaWRkZW4nOiBsZWZ0T3ZlcmZsb3dOYXZCdXR0b25IaWRkZW5cblx0XHRcdH1cIlxuXHRcdFx0W2F0dHIuYXJpYS1oaWRkZW5dPVwibGVmdE92ZXJmbG93TmF2QnV0dG9uSGlkZGVuXCJcblx0XHRcdFthdHRyLnRhYmluZGV4XT1cIi0xXCJcblx0XHRcdFthdHRyLmFyaWEtbGFiZWxdPVwidHJhbnNsYXRpb25zLkJVVFRPTl9BUklBX0xFRlRcIlxuXHRcdFx0W2F0dHIudGl0bGVdPVwidHJhbnNsYXRpb25zLkJVVFRPTl9BUklBX0xFRlRcIj5cblx0XHRcdDxzdmdcblx0XHRcdFx0Zm9jdXNhYmxlPVwiZmFsc2VcIlxuXHRcdFx0XHRwcmVzZXJ2ZUFzcGVjdFJhdGlvPVwieE1pZFlNaWQgbWVldFwiXG5cdFx0XHRcdHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIlxuXHRcdFx0XHRmaWxsPVwiY3VycmVudENvbG9yXCJcblx0XHRcdFx0d2lkdGg9XCIxNlwiXG5cdFx0XHRcdGhlaWdodD1cIjE2XCJcblx0XHRcdFx0dmlld0JveD1cIjAgMCAxNiAxNlwiXG5cdFx0XHRcdGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuXHRcdFx0XHQ8cGF0aCBkPVwiTTUgOEwxMCAzIDEwLjcgMy43IDYuNCA4IDEwLjcgMTIuMyAxMCAxM3pcIj48L3BhdGg+XG5cdFx0XHQ8L3N2Zz5cblx0XHQ8L2J1dHRvbj5cblx0XHQ8ZGl2XG5cdFx0XHQjdGFiTGlzdFxuXHRcdFx0Y2xhc3M9XCJjZHMtLXRhYi0tbGlzdFwiXG5cdFx0XHRyb2xlPVwidGFibGlzdFwiXG5cdFx0XHRbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbCB8fCB0cmFuc2xhdGlvbnMuSEVBREVSX0FSSUFfTEFCRUxcIlxuXHRcdFx0W2F0dHIuYXJpYS1sYWJlbGxlZGJ5XT1cImFyaWFMYWJlbGxlZGJ5IHx8IG51bGxcIlxuXHRcdFx0KHNjcm9sbCk9XCJoYW5kbGVTY3JvbGwoKVwiPlxuXHRcdFx0PG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJjb250ZW50QmVmb3JlXCI+PC9uZy1jb250YWluZXI+XG5cdFx0XHQ8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCB0YWIgb2YgdGFiczsgbGV0IGkgPSBpbmRleDtcIj5cblx0XHRcdFx0PGNkcy10b29sdGlwXG5cdFx0XHRcdFx0Km5nSWY9XCJ0YWIuaWNvbk9ubHk7IGVsc2UgaW5saW5lVGFiSXRlbVwiXG5cdFx0XHRcdFx0YWxpZ249XCJib3R0b21cIlxuXHRcdFx0XHRcdFthdXRvQWxpZ25dPVwidHJ1ZVwiXG5cdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLWljb24tdG9vbHRpcFwiXG5cdFx0XHRcdFx0W2Rlc2NyaXB0aW9uXT1cInRhYi5pY29uTGFiZWxcIlxuXHRcdFx0XHRcdFtlbnRlckRlbGF5TXNdPVwidGFiLmVudGVyRGVsYXlNcyA/PyAxMDBcIlxuXHRcdFx0XHRcdFtsZWF2ZURlbGF5TXNdPVwidGFiLmxlYXZlRGVsYXlNcyA/PyAzMDBcIlxuXHRcdFx0XHRcdFtpc09wZW5dPVwidGFiLmlzVG9vbHRpcE9wZW5cIlxuXHRcdFx0XHRcdFtkaXNhYmxlZF09XCJ0YWIuZGlzYWJsZWRcIj5cblx0XHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGFiSXRlbVRwbDsgY29udGV4dDogeyB0YWI6IHRhYiwgaTogaSB9XCI+PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdDwvY2RzLXRvb2x0aXA+XG5cdFx0XHRcdDxuZy10ZW1wbGF0ZSAjaW5saW5lVGFiSXRlbT5cblx0XHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGFiSXRlbVRwbDsgY29udGV4dDogeyB0YWI6IHRhYiwgaTogaSB9XCI+PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdDwvbmctdGVtcGxhdGU+XG5cdFx0XHRcdDxkaXZcblx0XHRcdFx0XHQqbmdJZj1cImRpc21pc3NhYmxlXCJcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tdGFic19fbmF2LWl0ZW0tLWNsb3NlXCI+XG5cdFx0XHRcdFx0PGJ1dHRvblxuXHRcdFx0XHRcdFx0dHlwZT1cImJ1dHRvblwiXG5cdFx0XHRcdFx0XHRbYXR0ci50YWJpbmRleF09XCItMVwiXG5cdFx0XHRcdFx0XHRbYXR0ci5hcmlhLWRpc2FibGVkXT1cInRhYi5kaXNhYmxlZFwiXG5cdFx0XHRcdFx0XHRbYXR0ci5hcmlhLWhpZGRlbl09XCIhKHRhYi5hY3RpdmUgJiYgIXRhYi5kaXNhYmxlZClcIlxuXHRcdFx0XHRcdFx0W2Rpc2FibGVkXT1cInRhYi5kaXNhYmxlZFwiXG5cdFx0XHRcdFx0XHRjbGFzcz1cImNkcy0tdGFic19fbmF2LWl0ZW0tLWNsb3NlLWljb25cIlxuXHRcdFx0XHRcdFx0W25nQ2xhc3NdPVwie1xuXHRcdFx0XHRcdFx0XHQnY2RzLS10YWJzX19uYXYtaXRlbS0tY2xvc2UtaWNvbi0tc2VsZWN0ZWQnOiB0YWIuYWN0aXZlLFxuXHRcdFx0XHRcdFx0XHQnY2RzLS10YWJzX19uYXYtaXRlbS0tY2xvc2UtaWNvbi0tZGlzYWJsZWQnOiB0YWIuZGlzYWJsZWRcblx0XHRcdFx0XHRcdH1cIlxuXHRcdFx0XHRcdFx0W2F0dHIudGl0bGVdPVwiZ2V0Q2xvc2VUaXRsZSh0YWIpXCJcblx0XHRcdFx0XHRcdChjbGljayk9XCJoYW5kbGVDbG9zZSgkZXZlbnQsIHRhYiwgaSlcIj5cblx0XHRcdFx0XHRcdDxzdmdcblx0XHRcdFx0XHRcdFx0Zm9jdXNhYmxlPVwiZmFsc2VcIlxuXHRcdFx0XHRcdFx0XHRwcmVzZXJ2ZUFzcGVjdFJhdGlvPVwieE1pZFlNaWQgbWVldFwiXG5cdFx0XHRcdFx0XHRcdHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIlxuXHRcdFx0XHRcdFx0XHRmaWxsPVwiY3VycmVudENvbG9yXCJcblx0XHRcdFx0XHRcdFx0d2lkdGg9XCIxNlwiXG5cdFx0XHRcdFx0XHRcdGhlaWdodD1cIjE2XCJcblx0XHRcdFx0XHRcdFx0dmlld0JveD1cIjAgMCAzMiAzMlwiXG5cdFx0XHRcdFx0XHRcdFthdHRyLmFyaWEtbGFiZWxdPVwidGFiLmNsb3NlQnV0dG9uQXJpYUxhYmVsXCJcblx0XHRcdFx0XHRcdFx0W2F0dHIuYXJpYS1oaWRkZW5dPVwiISh0YWIuYWN0aXZlICYmICF0YWIuZGlzYWJsZWQpXCI+XG5cdFx0XHRcdFx0XHRcdDxwYXRoIGQ9XCJNMTcuNDE0MSAxNkwyNCA5LjQxNDEgMjIuNTg1OSA4IDE2IDE0LjU4NTkgOS40MTQzIDggOCA5LjQxNDEgMTQuNTg1OSAxNiA4IDIyLjU4NTkgOS40MTQzIDI0IDE2IDE3LjQxNDEgMjIuNTg1OSAyNCAyNCAyMi41ODU5IDE3LjQxNDEgMTZ6XCI+PC9wYXRoPlxuXHRcdFx0XHRcdFx0PC9zdmc+XG5cdFx0XHRcdFx0PC9idXR0b24+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0PC9uZy1jb250YWluZXI+XG5cdFx0XHQ8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImNvbnRlbnRBZnRlclwiPjwvbmctY29udGFpbmVyPlxuXHRcdDwvZGl2PlxuXHRcdDxuZy10ZW1wbGF0ZSAjdGFiSXRlbVRwbCBsZXQtdGFiPVwidGFiXCIgbGV0LWk9XCJpXCI+XG5cdFx0XHQ8YnV0dG9uXG5cdFx0XHRcdCN0YWJJdGVtXG5cdFx0XHRcdHJvbGU9XCJ0YWJcIlxuXHRcdFx0XHRbYXR0ci5hcmlhLXNlbGVjdGVkXT1cInRhYi5hY3RpdmVcIlxuXHRcdFx0XHRbYXR0ci50YWJpbmRleF09XCIodGFiLmFjdGl2ZT8wOi0xKVwiXG5cdFx0XHRcdFthdHRyLmFyaWEtY29udHJvbHNdPVwidGFiLmlkXCJcblx0XHRcdFx0W2F0dHIuYXJpYS1kaXNhYmxlZF09XCJ0YWIuZGlzYWJsZWRcIlxuXHRcdFx0XHRbYXR0ci5hcmlhLWxhYmVsXT1cInRhYi5pY29uT25seSA/IHRhYi5pY29uTGFiZWwgOiBudWxsXCJcblx0XHRcdFx0W2Rpc2FibGVkXT1cInRhYi5kaXNhYmxlZFwiXG5cdFx0XHRcdFtuZ0NsYXNzXT1cIntcblx0XHRcdFx0XHQnY2RzLS10YWJzX19uYXYtaXRlbS0tc2VsZWN0ZWQnOiB0YWIuYWN0aXZlLFxuXHRcdFx0XHRcdCdjZHMtLXRhYnNfX25hdi1pdGVtLS1kaXNhYmxlZCc6IHRhYi5kaXNhYmxlZCxcblx0XHRcdFx0XHQnY2RzLS10YWJzX19uYXYtaXRlbS0taWNvbi1vbmx5JzogdGFiLmljb25Pbmx5LFxuXHRcdFx0XHRcdCdjZHMtLXRhYnNfX25hdi1pdGVtLS1pY29uLW9ubHlfXzIwJzogdGFiLmljb25Pbmx5ICYmIGljb25TaXplID09PSAnbGcnXG5cdFx0XHRcdH1cIlxuXHRcdFx0XHRjbGFzcz1cImNkcy0tdGFic19fbmF2LWl0ZW0gY2RzLS10YWJzX19uYXYtbGlua1wiXG5cdFx0XHRcdHR5cGU9XCJidXR0b25cIlxuXHRcdFx0XHRkcmFnZ2FibGU9XCJmYWxzZVwiXG5cdFx0XHRcdGlkPVwie3t0YWIuaWR9fS1oZWFkZXJcIlxuXHRcdFx0XHRbYXR0ci50aXRsZV09XCJ0YWIuaWNvbk9ubHkgPyB0YWIuaWNvbkxhYmVsIDogKHRhYi50aXRsZSB8fCAoIXRhYi5oZWFkaW5nSXNUZW1wbGF0ZSA/IHRhYi5oZWFkaW5nIDogbnVsbCkpXCJcblx0XHRcdFx0KGZvY3VzKT1cIm9uVGFiRm9jdXModGFiSXRlbSwgaSlcIlxuXHRcdFx0XHQoa2V5ZG93bik9XCJoYW5kbGVUYWJLZXlEb3duKCRldmVudCwgdGFiLCBpKVwiXG5cdFx0XHRcdChjbGljayk9XCJzZWxlY3RUYWIodGFiSXRlbSwgdGFiLCBpKVwiPlxuXHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwidGFiLmljb25Pbmx5OyBlbHNlIGxhYmVsZWRUYWJcIj5cblx0XHRcdFx0XHQ8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cInRhYi5pY29uXCI+PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdFx0PHNwYW5cblx0XHRcdFx0XHRcdCpuZ0lmPVwiIXRhYi5kaXNhYmxlZCAmJiB0YWIuYmFkZ2VJbmRpY2F0b3JcIlxuXHRcdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLWJhZGdlLWluZGljYXRvclwiXG5cdFx0XHRcdFx0XHRhcmlhLWhpZGRlbj1cInRydWVcIj5cblx0XHRcdFx0XHQ8L3NwYW4+XG5cdFx0XHRcdDwvbmctY29udGFpbmVyPlxuXHRcdFx0XHQ8bmctdGVtcGxhdGUgI2xhYmVsZWRUYWI+XG5cdFx0XHRcdFx0PGRpdiBjbGFzcz1cImNkcy0tdGFic19fbmF2LWl0ZW0tbGFiZWwtd3JhcHBlclwiPlxuXHRcdFx0XHRcdFx0PGRpdiAqbmdJZj1cImRpc21pc3NhYmxlICYmIHRhYi5pY29uXCIgY2xhc3M9XCJjZHMtLXRhYnNfX25hdi1pdGVtLS1pY29uLWxlZnRcIj5cblx0XHRcdFx0XHRcdFx0PG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJ0YWIuaWNvblwiPjwvbmctY29udGFpbmVyPlxuXHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cImNkcy0tdGFic19fbmF2LWl0ZW0tbGFiZWxcIj5cblx0XHRcdFx0XHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cIiF0YWIuaGVhZGluZ0lzVGVtcGxhdGVcIj5cblx0XHRcdFx0XHRcdFx0XHR7eyB0YWIuaGVhZGluZyB9fVxuXHRcdFx0XHRcdFx0XHQ8L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0XHRcdFx0PG5nLXRlbXBsYXRlXG5cdFx0XHRcdFx0XHRcdFx0Km5nSWY9XCJ0YWIuaGVhZGluZ0lzVGVtcGxhdGVcIlxuXHRcdFx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0XT1cInRhYi5oZWFkaW5nXCJcblx0XHRcdFx0XHRcdFx0XHRbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyRpbXBsaWNpdDogdGFiLmNvbnRleHR9XCI+XG5cdFx0XHRcdFx0XHRcdDwvbmctdGVtcGxhdGU+XG5cdFx0XHRcdFx0XHQ8L3NwYW4+XG5cdFx0XHRcdFx0XHQ8ZGl2XG5cdFx0XHRcdFx0XHRcdCpuZ0lmPVwiIWRpc21pc3NhYmxlICYmIHRhYi5pY29uXCJcblx0XHRcdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLXRhYnNfX25hdi1pdGVtLS1pY29uXCI+XG5cdFx0XHRcdFx0XHRcdDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwidGFiLmljb25cIj48L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdDxkaXZcblx0XHRcdFx0XHRcdCpuZ0lmPVwiaGFzU2Vjb25kYXJ5TGFiZWxUYWJzICYmIHRhYi5zZWNvbmRhcnlMYWJlbFwiXG5cdFx0XHRcdFx0XHRjbGFzcz1cImNkcy0tdGFic19fbmF2LWl0ZW0tc2Vjb25kYXJ5LWxhYmVsXCJcblx0XHRcdFx0XHRcdFthdHRyLnRpdGxlXT1cInRhYi5zZWNvbmRhcnlMYWJlbFwiPlxuXHRcdFx0XHRcdFx0e3sgdGFiLnNlY29uZGFyeUxhYmVsIH19XG5cdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdDwvbmctdGVtcGxhdGU+XG5cdFx0XHQ8L2J1dHRvbj5cblx0XHQ8L25nLXRlbXBsYXRlPlxuXHRcdDxidXR0b25cblx0XHRcdHR5cGU9XCJidXR0b25cIlxuXHRcdFx0KGNsaWNrKT1cImhhbmRsZU92ZXJmbG93TmF2Q2xpY2soMSwgdGFicy5sZW5ndGgpXCJcblx0XHRcdChwb2ludGVyZG93bik9XCJoYW5kbGVPdmVyZmxvd05hdk1vdXNlRG93bigxKVwiXG5cdFx0XHQocG9pbnRlcnVwKT1cImhhbmRsZU92ZXJmbG93TmF2TW91c2VVcCgpXCJcblx0XHRcdChwb2ludGVybGVhdmUpPVwiaGFuZGxlT3ZlcmZsb3dOYXZNb3VzZVVwKClcIlxuXHRcdFx0KHBvaW50ZXJvdXQpPVwiaGFuZGxlT3ZlcmZsb3dOYXZNb3VzZVVwKClcIlxuXHRcdFx0Y2xhc3M9XCJjZHMtLXRhYi0tb3ZlcmZsb3ctbmF2LWJ1dHRvbiBjZHMtLXRhYi0tb3ZlcmZsb3ctbmF2LWJ1dHRvbi0tbmV4dFwiXG5cdFx0XHRbbmdDbGFzc109XCJ7XG5cdFx0XHRcdCdjZHMtLXRhYi0tb3ZlcmZsb3ctbmF2LWJ1dHRvbi0taGlkZGVuJzogcmlnaHRPdmVyZmxvd05hdkJ1dHRvbkhpZGRlblxuXHRcdFx0fVwiXG5cdFx0XHRbYXR0ci5hcmlhLWhpZGRlbl09XCJyaWdodE92ZXJmbG93TmF2QnV0dG9uSGlkZGVuXCJcblx0XHRcdFthdHRyLnRhYmluZGV4XT1cIi0xXCJcblx0XHRcdFthdHRyLmFyaWEtbGFiZWxdPVwidHJhbnNsYXRpb25zLkJVVFRPTl9BUklBX1JJR0hUXCJcblx0XHRcdFthdHRyLnRpdGxlXT1cInRyYW5zbGF0aW9ucy5CVVRUT05fQVJJQV9SSUdIVFwiPlxuXHRcdFx0PHN2Z1xuXHRcdFx0XHRmb2N1c2FibGU9XCJmYWxzZVwiXG5cdFx0XHRcdHByZXNlcnZlQXNwZWN0UmF0aW89XCJ4TWlkWU1pZCBtZWV0XCJcblx0XHRcdFx0eG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiXG5cdFx0XHRcdGZpbGw9XCJjdXJyZW50Q29sb3JcIlxuXHRcdFx0XHR3aWR0aD1cIjE2XCJcblx0XHRcdFx0aGVpZ2h0PVwiMTZcIlxuXHRcdFx0XHR2aWV3Qm94PVwiMCAwIDE2IDE2XCJcblx0XHRcdFx0YXJpYS1oaWRkZW49XCJ0cnVlXCI+XG5cdFx0XHRcdDxwYXRoIGQ9XCJNMTEgOEw2IDEzIDUuMyAxMi4zIDkuNiA4IDUuMyAzLjcgNiAzelwiPjwvcGF0aD5cblx0XHRcdDwvc3ZnPlxuXHRcdDwvYnV0dG9uPlxuXHRgXG59KVxuXG5leHBvcnQgY2xhc3MgVGFiSGVhZGVycyBleHRlbmRzIEJhc2VUYWJIZWFkZXIgaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgT25Jbml0IHtcblx0LyoqXG5cdCAqIExpc3Qgb2YgYFRhYmAgY29tcG9uZW50cy5cblx0ICovXG5cdC8vIGRpc2FibGUgdGhlIG5leHQgbGluZSBiZWNhdXNlIHdlIG5lZWQgdG8gcmVuYW1lIHRoZSBpbnB1dFxuXHQvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmVcblx0QElucHV0KFwidGFic1wiKSB0YWJJbnB1dDogUXVlcnlMaXN0PFRhYj47XG5cblx0LyoqXG5cdCAqIGkxOG4gc3RyaW5ncyBmb3Igb3ZlcmZsb3cgY29udHJvbHMgYW5kIHRoZSB0YWIgbGlzdCBgYXJpYS1sYWJlbGAgZmFsbGJhY2suXG5cdCAqL1xuXHRASW5wdXQoKSB0cmFuc2xhdGlvbnMgPSB0aGlzLmkxOG4uZ2V0KCkuVEFCUztcblxuXHQvKipcblx0ICogRW1pdHMgd2hlbiBhIHRhYiBjbG9zZSBjb250cm9sIGlzIHVzZWQgKHdpdGggYGRpc21pc3NhYmxlYCkuXG5cdCAqIFRoZSBlbWl0dGVkIHZhbHVlIGlzIHRoZSB0YWIgaW5kZXguXG5cdCAqL1xuXHRAT3V0cHV0KCkgdGFiQ2xvc2U6IEV2ZW50RW1pdHRlcjxudW1iZXI+ID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIFVub3JkZXJlZCBMaXN0IGVsZW1lbnQgdGhhdCBob2xkcyB0aGUgYFRhYmAgaGVhZGluZ3MgZnJvbSB0aGUgdmlldyBET00uXG5cdCAqL1xuXHRAVmlld0NoaWxkKFwidGFiTGlzdFwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBoZWFkZXJDb250YWluZXI6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+O1xuXHQvKipcblx0ICogQ29udGVudENoaWxkIG9mIGFsbCB0aGUgdGFic1xuX