juvo-rafa-library
Version:
A comprehensive Angular component library featuring real-world components and validators extracted from the Juvo Rafa backoffice application. Now with improved select components and bug fixes.
116 lines • 18.5 kB
JavaScript
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { CommonModule } from '@angular/common';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
/**
* Tab Menu Component
*
* @description
* A horizontal tab navigation component for organizing content into tabs.
* Originally designed for backoffice applications with multiple content sections.
* Supports icons, badges, disabled states, and router integration.
*
* @example
* ```html
* <!-- Basic tab menu -->
* <juvo-tab-menu
* [items]="tabItems"
* [activeItemId]="activeTab"
* (tabChange)="onTabChange($event)">
* </juvo-tab-menu>
*
* <!-- Tab menu with icons and badges -->
* <juvo-tab-menu
* [items]="[
* { id: 'overview', label: 'Overview', icon: '📊' },
* { id: 'users', label: 'Users', icon: '👥', badge: '12' },
* { id: 'settings', label: 'Settings', icon: '⚙️', disabled: true }
* ]"
* [activeItemId]="currentTab"
* (tabChange)="handleTabChange($event)">
* </juvo-tab-menu>
* ```
*
* @selector juvo-tab-menu
* @since 2.1.0
* @author Juvo Rafa Team
*/
export class JuvoTabMenuComponent {
constructor() {
/** Array of tab menu items */
this.items = [];
/** Tab menu style variant @default "line" */
this.variant = 'line';
/** Tab menu size @default "medium" */
this.size = 'medium';
/** Whether tabs are scrollable on overflow @default false */
this.scrollable = false;
/** Emitted when a tab is clicked */
this.tabChange = new EventEmitter();
/** Emitted when active tab changes */
this.activeItemChange = new EventEmitter();
}
/**
* Gets CSS classes for the tab menu container
* @returns Combined CSS classes
*/
get containerClasses() {
let classes = `tab-menu tab-menu-${this.variant} tab-menu-${this.size}`;
if (this.scrollable)
classes += ' scrollable';
return classes;
}
/**
* Gets CSS classes for a specific tab item
* @param item Tab menu item
* @returns Combined CSS classes
*/
getTabClasses(item) {
let classes = 'tab-item';
if (item.id === this.activeItemId)
classes += ' active';
if (item.disabled)
classes += ' disabled';
return classes;
}
/**
* Handles tab click
* @param item Clicked tab item
*/
onTabClick(item) {
if (item.disabled)
return;
this.activeItemId = item.id;
this.tabChange.emit(item);
this.activeItemChange.emit(item);
}
/**
* Checks if a tab is active
* @param item Tab menu item
* @returns Whether the tab is active
*/
isActive(item) {
return item.id === this.activeItemId;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JuvoTabMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: JuvoTabMenuComponent, isStandalone: true, selector: "juvo-tab-menu", inputs: { items: "items", activeItemId: "activeItemId", variant: "variant", size: "size", scrollable: "scrollable" }, outputs: { tabChange: "tabChange", activeItemChange: "activeItemChange" }, ngImport: i0, template: "<div [class]=\"containerClasses\">\n <div class=\"tab-list\" role=\"tablist\">\n <button\n *ngFor=\"let item of items\"\n [class]=\"getTabClasses(item)\"\n [disabled]=\"item.disabled\"\n [attr.aria-selected]=\"isActive(item)\"\n [attr.aria-controls]=\"item.id + '-panel'\"\n role=\"tab\"\n type=\"button\"\n (click)=\"onTabClick(item)\">\n \n <!-- Icon -->\n <span class=\"tab-icon\" *ngIf=\"item.icon\">\n {{ item.icon }}\n </span>\n \n <!-- Label -->\n <span class=\"tab-label\">\n {{ item.label }}\n </span>\n \n <!-- Badge -->\n <span class=\"tab-badge\" *ngIf=\"item.badge\">\n {{ item.badge }}\n </span>\n </button>\n </div>\n</div> ", styles: [".tab-menu{width:100%}.tab-list{display:flex;gap:.25rem;border-bottom:1px solid #e5e7eb}.tab-menu.scrollable .tab-list{overflow-x:auto;scrollbar-width:thin}.tab-menu.scrollable .tab-list::-webkit-scrollbar{height:4px}.tab-menu.scrollable .tab-list::-webkit-scrollbar-track{background:#f1f5f9}.tab-menu.scrollable .tab-list::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}.tab-item{display:flex;align-items:center;gap:.5rem;background:none;border:none;cursor:pointer;transition:all .15s;font-weight:500;white-space:nowrap;position:relative}.tab-item:disabled{opacity:.5;cursor:not-allowed}.tab-item:focus{outline:none;box-shadow:0 0 0 2px #3b82f633}.tab-menu-small .tab-item{padding:.5rem 1rem;font-size:.8125rem}.tab-menu-medium .tab-item{padding:.75rem 1.25rem;font-size:.875rem}.tab-menu-large .tab-item{padding:1rem 1.5rem;font-size:1rem}.tab-menu-line .tab-item{color:#6b7280;border-bottom:2px solid transparent}.tab-menu-line .tab-item:hover:not(:disabled){color:#374151;border-bottom-color:#d1d5db}.tab-menu-line .tab-item.active{color:#3b82f6;border-bottom-color:#3b82f6}.tab-menu-pills .tab-list{border-bottom:none}.tab-menu-pills .tab-item{color:#6b7280;border-radius:.375rem}.tab-menu-pills .tab-item:hover:not(:disabled){color:#374151;background:#f3f4f6}.tab-menu-pills .tab-item.active{color:#fff;background:#3b82f6}.tab-menu-cards .tab-list{border-bottom:none;gap:.5rem}.tab-menu-cards .tab-item{color:#6b7280;background:#fff;border:1px solid #e5e7eb;border-radius:.375rem}.tab-menu-cards .tab-item:hover:not(:disabled){color:#374151;border-color:#d1d5db;box-shadow:0 1px 3px #0000001a}.tab-menu-cards .tab-item.active{color:#3b82f6;background:#eff6ff;border-color:#3b82f6}.tab-icon{font-size:1em;flex-shrink:0}.tab-label{flex:1}.tab-badge{background:#ef4444;color:#fff;font-size:.75em;font-weight:600;padding:.125rem .375rem;border-radius:9999px;min-width:1.25rem;text-align:center;line-height:1.2}.tab-item.active .tab-badge{background:#fff3}.tab-menu-line .tab-item .tab-badge,.tab-menu-cards .tab-item .tab-badge{background:#ef4444;color:#fff}@media (max-width: 640px){.tab-menu:not(.scrollable) .tab-list{flex-wrap:wrap;gap:.5rem}.tab-menu.scrollable .tab-list{flex-wrap:nowrap}.tab-menu-large .tab-item{padding:.75rem 1rem;font-size:.875rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JuvoTabMenuComponent, decorators: [{
type: Component,
args: [{ selector: 'juvo-tab-menu', standalone: true, imports: [CommonModule], template: "<div [class]=\"containerClasses\">\n <div class=\"tab-list\" role=\"tablist\">\n <button\n *ngFor=\"let item of items\"\n [class]=\"getTabClasses(item)\"\n [disabled]=\"item.disabled\"\n [attr.aria-selected]=\"isActive(item)\"\n [attr.aria-controls]=\"item.id + '-panel'\"\n role=\"tab\"\n type=\"button\"\n (click)=\"onTabClick(item)\">\n \n <!-- Icon -->\n <span class=\"tab-icon\" *ngIf=\"item.icon\">\n {{ item.icon }}\n </span>\n \n <!-- Label -->\n <span class=\"tab-label\">\n {{ item.label }}\n </span>\n \n <!-- Badge -->\n <span class=\"tab-badge\" *ngIf=\"item.badge\">\n {{ item.badge }}\n </span>\n </button>\n </div>\n</div> ", styles: [".tab-menu{width:100%}.tab-list{display:flex;gap:.25rem;border-bottom:1px solid #e5e7eb}.tab-menu.scrollable .tab-list{overflow-x:auto;scrollbar-width:thin}.tab-menu.scrollable .tab-list::-webkit-scrollbar{height:4px}.tab-menu.scrollable .tab-list::-webkit-scrollbar-track{background:#f1f5f9}.tab-menu.scrollable .tab-list::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}.tab-item{display:flex;align-items:center;gap:.5rem;background:none;border:none;cursor:pointer;transition:all .15s;font-weight:500;white-space:nowrap;position:relative}.tab-item:disabled{opacity:.5;cursor:not-allowed}.tab-item:focus{outline:none;box-shadow:0 0 0 2px #3b82f633}.tab-menu-small .tab-item{padding:.5rem 1rem;font-size:.8125rem}.tab-menu-medium .tab-item{padding:.75rem 1.25rem;font-size:.875rem}.tab-menu-large .tab-item{padding:1rem 1.5rem;font-size:1rem}.tab-menu-line .tab-item{color:#6b7280;border-bottom:2px solid transparent}.tab-menu-line .tab-item:hover:not(:disabled){color:#374151;border-bottom-color:#d1d5db}.tab-menu-line .tab-item.active{color:#3b82f6;border-bottom-color:#3b82f6}.tab-menu-pills .tab-list{border-bottom:none}.tab-menu-pills .tab-item{color:#6b7280;border-radius:.375rem}.tab-menu-pills .tab-item:hover:not(:disabled){color:#374151;background:#f3f4f6}.tab-menu-pills .tab-item.active{color:#fff;background:#3b82f6}.tab-menu-cards .tab-list{border-bottom:none;gap:.5rem}.tab-menu-cards .tab-item{color:#6b7280;background:#fff;border:1px solid #e5e7eb;border-radius:.375rem}.tab-menu-cards .tab-item:hover:not(:disabled){color:#374151;border-color:#d1d5db;box-shadow:0 1px 3px #0000001a}.tab-menu-cards .tab-item.active{color:#3b82f6;background:#eff6ff;border-color:#3b82f6}.tab-icon{font-size:1em;flex-shrink:0}.tab-label{flex:1}.tab-badge{background:#ef4444;color:#fff;font-size:.75em;font-weight:600;padding:.125rem .375rem;border-radius:9999px;min-width:1.25rem;text-align:center;line-height:1.2}.tab-item.active .tab-badge{background:#fff3}.tab-menu-line .tab-item .tab-badge,.tab-menu-cards .tab-item .tab-badge{background:#ef4444;color:#fff}@media (max-width: 640px){.tab-menu:not(.scrollable) .tab-list{flex-wrap:wrap;gap:.5rem}.tab-menu.scrollable .tab-list{flex-wrap:nowrap}.tab-menu-large .tab-item{padding:.75rem 1rem;font-size:.875rem}}\n"] }]
}], propDecorators: { items: [{
type: Input
}], activeItemId: [{
type: Input
}], variant: [{
type: Input
}], size: [{
type: Input
}], scrollable: [{
type: Input
}], tabChange: [{
type: Output
}], activeItemChange: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianV2by10YWItbWVudS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS1jb21wb25lbnRzL3NyYy9saWIvanV2by10YWItbWVudS9qdXZvLXRhYi1tZW51LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3VpLWNvbXBvbmVudHMvc3JjL2xpYi9qdXZvLXRhYi1tZW51L2p1dm8tdGFiLW1lbnUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7OztBQWdCL0M7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBZ0NHO0FBUUgsTUFBTSxPQUFPLG9CQUFvQjtJQVBqQztRQVFFLDhCQUE4QjtRQUNyQixVQUFLLEdBQWtCLEVBQUUsQ0FBQztRQUtuQyw2Q0FBNkM7UUFDcEMsWUFBTyxHQUErQixNQUFNLENBQUM7UUFFdEQsc0NBQXNDO1FBQzdCLFNBQUksR0FBaUMsUUFBUSxDQUFDO1FBRXZELDZEQUE2RDtRQUNwRCxlQUFVLEdBQVksS0FBSyxDQUFDO1FBRXJDLG9DQUFvQztRQUMxQixjQUFTLEdBQUcsSUFBSSxZQUFZLEVBQWUsQ0FBQztRQUV0RCxzQ0FBc0M7UUFDNUIscUJBQWdCLEdBQUcsSUFBSSxZQUFZLEVBQWUsQ0FBQztLQTRDOUQ7SUExQ0M7OztPQUdHO0lBQ0gsSUFBSSxnQkFBZ0I7UUFDbEIsSUFBSSxPQUFPLEdBQUcscUJBQXFCLElBQUksQ0FBQyxPQUFPLGFBQWEsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hFLElBQUksSUFBSSxDQUFDLFVBQVU7WUFBRSxPQUFPLElBQUksYUFBYSxDQUFDO1FBQzlDLE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsYUFBYSxDQUFDLElBQWlCO1FBQzdCLElBQUksT0FBTyxHQUFHLFVBQVUsQ0FBQztRQUN6QixJQUFJLElBQUksQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLFlBQVk7WUFBRSxPQUFPLElBQUksU0FBUyxDQUFDO1FBQ3hELElBQUksSUFBSSxDQUFDLFFBQVE7WUFBRSxPQUFPLElBQUksV0FBVyxDQUFDO1FBQzFDLE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxVQUFVLENBQUMsSUFBaUI7UUFDMUIsSUFBSSxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU87UUFFMUIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzFCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxRQUFRLENBQUMsSUFBaUI7UUFDeEIsT0FBTyxJQUFJLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDdkMsQ0FBQzsrR0EvRFUsb0JBQW9CO21HQUFwQixvQkFBb0IsMFFDekRqQyxrd0JBNEJPLDZ4RUR5QkssWUFBWTs7NEZBSVgsb0JBQW9CO2tCQVBoQyxTQUFTOytCQUNFLGVBQWUsY0FDYixJQUFJLFdBQ1AsQ0FBQyxZQUFZLENBQUM7OEJBTWQsS0FBSztzQkFBYixLQUFLO2dCQUdHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBR0csT0FBTztzQkFBZixLQUFLO2dCQUdHLElBQUk7c0JBQVosS0FBSztnQkFHRyxVQUFVO3NCQUFsQixLQUFLO2dCQUdJLFNBQVM7c0JBQWxCLE1BQU07Z0JBR0csZ0JBQWdCO3NCQUF6QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5cbi8qKlxuICogVGFiIG1lbnUgaXRlbSBpbnRlcmZhY2VcbiAqIEBpbnRlcmZhY2UgVGFiTWVudUl0ZW1cbiAqIEBzaW5jZSAyLjEuMFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRhYk1lbnVJdGVtIHtcbiAgaWQ6IHN0cmluZztcbiAgbGFiZWw6IHN0cmluZztcbiAgaWNvbj86IHN0cmluZztcbiAgZGlzYWJsZWQ/OiBib29sZWFuO1xuICBiYWRnZT86IHN0cmluZyB8IG51bWJlcjtcbiAgcm91dGVyTGluaz86IHN0cmluZztcbn1cblxuLyoqXG4gKiBUYWIgTWVudSBDb21wb25lbnRcbiAqIFxuICogQGRlc2NyaXB0aW9uXG4gKiBBIGhvcml6b250YWwgdGFiIG5hdmlnYXRpb24gY29tcG9uZW50IGZvciBvcmdhbml6aW5nIGNvbnRlbnQgaW50byB0YWJzLlxuICogT3JpZ2luYWxseSBkZXNpZ25lZCBmb3IgYmFja29mZmljZSBhcHBsaWNhdGlvbnMgd2l0aCBtdWx0aXBsZSBjb250ZW50IHNlY3Rpb25zLlxuICogU3VwcG9ydHMgaWNvbnMsIGJhZGdlcywgZGlzYWJsZWQgc3RhdGVzLCBhbmQgcm91dGVyIGludGVncmF0aW9uLlxuICogXG4gKiBAZXhhbXBsZVxuICogYGBgaHRtbFxuICogPCEtLSBCYXNpYyB0YWIgbWVudSAtLT5cbiAqIDxqdXZvLXRhYi1tZW51XG4gKiAgIFtpdGVtc109XCJ0YWJJdGVtc1wiXG4gKiAgIFthY3RpdmVJdGVtSWRdPVwiYWN0aXZlVGFiXCJcbiAqICAgKHRhYkNoYW5nZSk9XCJvblRhYkNoYW5nZSgkZXZlbnQpXCI+XG4gKiA8L2p1dm8tdGFiLW1lbnU+XG4gKiBcbiAqIDwhLS0gVGFiIG1lbnUgd2l0aCBpY29ucyBhbmQgYmFkZ2VzIC0tPlxuICogPGp1dm8tdGFiLW1lbnVcbiAqICAgW2l0ZW1zXT1cIltcbiAqICAgICB7IGlkOiAnb3ZlcnZpZXcnLCBsYWJlbDogJ092ZXJ2aWV3JywgaWNvbjogJ/Cfk4onIH0sXG4gKiAgICAgeyBpZDogJ3VzZXJzJywgbGFiZWw6ICdVc2VycycsIGljb246ICfwn5GlJywgYmFkZ2U6ICcxMicgfSxcbiAqICAgICB7IGlkOiAnc2V0dGluZ3MnLCBsYWJlbDogJ1NldHRpbmdzJywgaWNvbjogJ+Kame+4jycsIGRpc2FibGVkOiB0cnVlIH1cbiAqICAgXVwiXG4gKiAgIFthY3RpdmVJdGVtSWRdPVwiY3VycmVudFRhYlwiXG4gKiAgICh0YWJDaGFuZ2UpPVwiaGFuZGxlVGFiQ2hhbmdlKCRldmVudClcIj5cbiAqIDwvanV2by10YWItbWVudT5cbiAqIGBgYFxuICogXG4gKiBAc2VsZWN0b3IganV2by10YWItbWVudVxuICogQHNpbmNlIDIuMS4wXG4gKiBAYXV0aG9yIEp1dm8gUmFmYSBUZWFtXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2p1dm8tdGFiLW1lbnUnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2p1dm8tdGFiLW1lbnUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vanV2by10YWItbWVudS5jb21wb25lbnQuY3NzJ1xufSlcbmV4cG9ydCBjbGFzcyBKdXZvVGFiTWVudUNvbXBvbmVudCB7XG4gIC8qKiBBcnJheSBvZiB0YWIgbWVudSBpdGVtcyAqL1xuICBASW5wdXQoKSBpdGVtczogVGFiTWVudUl0ZW1bXSA9IFtdO1xuICBcbiAgLyoqIElEIG9mIHRoZSBjdXJyZW50bHkgYWN0aXZlIHRhYiAqL1xuICBASW5wdXQoKSBhY3RpdmVJdGVtSWQ/OiBzdHJpbmc7XG4gIFxuICAvKiogVGFiIG1lbnUgc3R5bGUgdmFyaWFudCBAZGVmYXVsdCBcImxpbmVcIiAqL1xuICBASW5wdXQoKSB2YXJpYW50OiAnbGluZScgfCAncGlsbHMnIHwgJ2NhcmRzJyA9ICdsaW5lJztcbiAgXG4gIC8qKiBUYWIgbWVudSBzaXplIEBkZWZhdWx0IFwibWVkaXVtXCIgKi9cbiAgQElucHV0KCkgc2l6ZTogJ3NtYWxsJyB8ICdtZWRpdW0nIHwgJ2xhcmdlJyA9ICdtZWRpdW0nO1xuICBcbiAgLyoqIFdoZXRoZXIgdGFicyBhcmUgc2Nyb2xsYWJsZSBvbiBvdmVyZmxvdyBAZGVmYXVsdCBmYWxzZSAqL1xuICBASW5wdXQoKSBzY3JvbGxhYmxlOiBib29sZWFuID0gZmFsc2U7XG4gIFxuICAvKiogRW1pdHRlZCB3aGVuIGEgdGFiIGlzIGNsaWNrZWQgKi9cbiAgQE91dHB1dCgpIHRhYkNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8VGFiTWVudUl0ZW0+KCk7XG4gIFxuICAvKiogRW1pdHRlZCB3aGVuIGFjdGl2ZSB0YWIgY2hhbmdlcyAqL1xuICBAT3V0cHV0KCkgYWN0aXZlSXRlbUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8VGFiTWVudUl0ZW0+KCk7XG5cbiAgLyoqXG4gICAqIEdldHMgQ1NTIGNsYXNzZXMgZm9yIHRoZSB0YWIgbWVudSBjb250YWluZXJcbiAgICogQHJldHVybnMgQ29tYmluZWQgQ1NTIGNsYXNzZXNcbiAgICovXG4gIGdldCBjb250YWluZXJDbGFzc2VzKCk6IHN0cmluZyB7XG4gICAgbGV0IGNsYXNzZXMgPSBgdGFiLW1lbnUgdGFiLW1lbnUtJHt0aGlzLnZhcmlhbnR9IHRhYi1tZW51LSR7dGhpcy5zaXplfWA7XG4gICAgaWYgKHRoaXMuc2Nyb2xsYWJsZSkgY2xhc3NlcyArPSAnIHNjcm9sbGFibGUnO1xuICAgIHJldHVybiBjbGFzc2VzO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgQ1NTIGNsYXNzZXMgZm9yIGEgc3BlY2lmaWMgdGFiIGl0ZW1cbiAgICogQHBhcmFtIGl0ZW0gVGFiIG1lbnUgaXRlbVxuICAgKiBAcmV0dXJucyBDb21iaW5lZCBDU1MgY2xhc3Nlc1xuICAgKi9cbiAgZ2V0VGFiQ2xhc3NlcyhpdGVtOiBUYWJNZW51SXRlbSk6IHN0cmluZyB7XG4gICAgbGV0IGNsYXNzZXMgPSAndGFiLWl0ZW0nO1xuICAgIGlmIChpdGVtLmlkID09PSB0aGlzLmFjdGl2ZUl0ZW1JZCkgY2xhc3NlcyArPSAnIGFjdGl2ZSc7XG4gICAgaWYgKGl0ZW0uZGlzYWJsZWQpIGNsYXNzZXMgKz0gJyBkaXNhYmxlZCc7XG4gICAgcmV0dXJuIGNsYXNzZXM7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyB0YWIgY2xpY2tcbiAgICogQHBhcmFtIGl0ZW0gQ2xpY2tlZCB0YWIgaXRlbVxuICAgKi9cbiAgb25UYWJDbGljayhpdGVtOiBUYWJNZW51SXRlbSk6IHZvaWQge1xuICAgIGlmIChpdGVtLmRpc2FibGVkKSByZXR1cm47XG4gICAgXG4gICAgdGhpcy5hY3RpdmVJdGVtSWQgPSBpdGVtLmlkO1xuICAgIHRoaXMudGFiQ2hhbmdlLmVtaXQoaXRlbSk7XG4gICAgdGhpcy5hY3RpdmVJdGVtQ2hhbmdlLmVtaXQoaXRlbSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgdGFiIGlzIGFjdGl2ZVxuICAgKiBAcGFyYW0gaXRlbSBUYWIgbWVudSBpdGVtXG4gICAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIHRhYiBpcyBhY3RpdmVcbiAgICovXG4gIGlzQWN0aXZlKGl0ZW06IFRhYk1lbnVJdGVtKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGl0ZW0uaWQgPT09IHRoaXMuYWN0aXZlSXRlbUlkO1xuICB9XG59ICIsIjxkaXYgW2NsYXNzXT1cImNvbnRhaW5lckNsYXNzZXNcIj5cbiAgPGRpdiBjbGFzcz1cInRhYi1saXN0XCIgcm9sZT1cInRhYmxpc3RcIj5cbiAgICA8YnV0dG9uXG4gICAgICAqbmdGb3I9XCJsZXQgaXRlbSBvZiBpdGVtc1wiXG4gICAgICBbY2xhc3NdPVwiZ2V0VGFiQ2xhc3NlcyhpdGVtKVwiXG4gICAgICBbZGlzYWJsZWRdPVwiaXRlbS5kaXNhYmxlZFwiXG4gICAgICBbYXR0ci5hcmlhLXNlbGVjdGVkXT1cImlzQWN0aXZlKGl0ZW0pXCJcbiAgICAgIFthdHRyLmFyaWEtY29udHJvbHNdPVwiaXRlbS5pZCArICctcGFuZWwnXCJcbiAgICAgIHJvbGU9XCJ0YWJcIlxuICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAoY2xpY2spPVwib25UYWJDbGljayhpdGVtKVwiPlxuICAgICAgXG4gICAgICA8IS0tIEljb24gLS0+XG4gICAgICA8c3BhbiBjbGFzcz1cInRhYi1pY29uXCIgKm5nSWY9XCJpdGVtLmljb25cIj5cbiAgICAgICAge3sgaXRlbS5pY29uIH19XG4gICAgICA8L3NwYW4+XG4gICAgICBcbiAgICAgIDwhLS0gTGFiZWwgLS0+XG4gICAgICA8c3BhbiBjbGFzcz1cInRhYi1sYWJlbFwiPlxuICAgICAgICB7eyBpdGVtLmxhYmVsIH19XG4gICAgICA8L3NwYW4+XG4gICAgICBcbiAgICAgIDwhLS0gQmFkZ2UgLS0+XG4gICAgICA8c3BhbiBjbGFzcz1cInRhYi1iYWRnZVwiICpuZ0lmPVwiaXRlbS5iYWRnZVwiPlxuICAgICAgICB7eyBpdGVtLmJhZGdlIH19XG4gICAgICA8L3NwYW4+XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuPC9kaXY+ICJdfQ==