UNPKG

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.

118 lines 17 kB
import { Component, Input } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Observable, combineLatest, map } from 'rxjs'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; /** * Screen Loading Component * * @description * A screen-wide loading overlay component for blocking UI interactions during operations. * Originally designed for backoffice applications to handle multiple loading states. * Can combine multiple observables to show loading when any operation is in progress. * * @example * ```html * <!-- Single loading state --> * <juvo-screen-loading * [loading$]="dataLoading$" * message="Loading data..."> * </juvo-screen-loading> * * <!-- Multiple loading states --> * <juvo-screen-loading * [loadingList$]="[saveLoading$, deleteLoading$, updateLoading$]" * message="Processing operations..." * [backdrop]="true"> * </juvo-screen-loading> * * <!-- Custom styled loading --> * <juvo-screen-loading * [loading$]="criticalOperation$" * message="Critical operation in progress. Please do not refresh the page." * color="#dc2626" * size="large"> * </juvo-screen-loading> * ``` * * @selector juvo-screen-loading * @since 2.1.0 * @author Juvo Rafa Team */ export class JuvoScreenLoadingComponent { constructor() { /** Array of loading observables to combine */ this.loadingList$ = []; /** Loading message to display @default "Loading..." */ this.message = 'Loading...'; /** Size of the loading spinner @default "large" */ this.size = 'large'; /** Color of the spinner @default "#3b82f6" */ this.color = '#3b82f6'; /** Whether to show backdrop @default true */ this.backdrop = true; /** Backdrop opacity @default 0.8 */ this.backdropOpacity = 0.8; /** Whether to show the loading message @default true */ this.showMessage = true; } /** * Gets the combined loading state from all sources * @returns Observable<boolean> indicating if any loading is in progress */ get combinedLoading$() { const observables = []; if (this.loading$) { observables.push(this.loading$); } if (this.loadingList$ && this.loadingList$.length > 0) { observables.push(...this.loadingList$); } if (observables.length === 0) { return new Observable(subscriber => subscriber.next(false)); } if (observables.length === 1) { return observables[0]; } return combineLatest(observables).pipe(map(loadingStates => loadingStates.some(loading => loading))); } /** * Gets the CSS class for the spinner size * @returns CSS class name for the current size */ get sizeClass() { return `spinner-${this.size}`; } /** * Gets the backdrop style * @returns CSS style object for backdrop */ get backdropStyle() { return { 'background-color': `rgba(255, 255, 255, ${this.backdropOpacity})` }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JuvoScreenLoadingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: JuvoScreenLoadingComponent, isStandalone: true, selector: "juvo-screen-loading", inputs: { loading$: "loading$", loadingList$: "loadingList$", message: "message", size: "size", color: "color", backdrop: "backdrop", backdropOpacity: "backdropOpacity", showMessage: "showMessage" }, ngImport: i0, template: "<div class=\"screen-loading-overlay\" \n *ngIf=\"combinedLoading$ | async\"\n [class.with-backdrop]=\"backdrop\"\n [ngStyle]=\"backdrop ? backdropStyle : null\">\n \n <div class=\"screen-loading-content\">\n <div class=\"spinner-container\">\n <div [class]=\"sizeClass\" \n class=\"loading-spinner\">\n <div class=\"spinner-circle\" \n [style.border-top-color]=\"color\"\n [style.border-right-color]=\"color\">\n </div>\n </div>\n </div>\n \n <div class=\"loading-message\" \n *ngIf=\"showMessage && message\">\n {{ message }}\n </div>\n </div>\n</div> ", styles: [".screen-loading-overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:9999}.screen-loading-overlay.with-backdrop{background-color:#fffc;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.screen-loading-content{display:flex;flex-direction:column;align-items:center;gap:1.5rem;text-align:center;padding:2rem;border-radius:.5rem;background:#fffffff2;box-shadow:0 4px 12px #0000001a;min-width:200px}.spinner-container,.loading-spinner{display:flex;align-items:center;justify-content:center}.spinner-circle{border:4px solid #f3f4f6;border-top:4px solid #3b82f6;border-right:4px solid #3b82f6;border-radius:50%;animation:spin 1s linear infinite}.spinner-small .spinner-circle{width:2rem;height:2rem;border-width:3px}.spinner-medium .spinner-circle{width:3rem;height:3rem;border-width:4px}.spinner-large .spinner-circle{width:4rem;height:4rem;border-width:5px}.loading-message{color:#374151;font-size:1rem;font-weight:500;max-width:300px;line-height:1.5}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (max-width: 640px){.screen-loading-content{margin:1rem;padding:1.5rem;min-width:auto;max-width:calc(100vw - 2rem)}.loading-message{font-size:.875rem;max-width:250px}.spinner-large .spinner-circle{width:3rem;height:3rem;border-width:4px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JuvoScreenLoadingComponent, decorators: [{ type: Component, args: [{ selector: 'juvo-screen-loading', standalone: true, imports: [CommonModule], template: "<div class=\"screen-loading-overlay\" \n *ngIf=\"combinedLoading$ | async\"\n [class.with-backdrop]=\"backdrop\"\n [ngStyle]=\"backdrop ? backdropStyle : null\">\n \n <div class=\"screen-loading-content\">\n <div class=\"spinner-container\">\n <div [class]=\"sizeClass\" \n class=\"loading-spinner\">\n <div class=\"spinner-circle\" \n [style.border-top-color]=\"color\"\n [style.border-right-color]=\"color\">\n </div>\n </div>\n </div>\n \n <div class=\"loading-message\" \n *ngIf=\"showMessage && message\">\n {{ message }}\n </div>\n </div>\n</div> ", styles: [".screen-loading-overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:9999}.screen-loading-overlay.with-backdrop{background-color:#fffc;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.screen-loading-content{display:flex;flex-direction:column;align-items:center;gap:1.5rem;text-align:center;padding:2rem;border-radius:.5rem;background:#fffffff2;box-shadow:0 4px 12px #0000001a;min-width:200px}.spinner-container,.loading-spinner{display:flex;align-items:center;justify-content:center}.spinner-circle{border:4px solid #f3f4f6;border-top:4px solid #3b82f6;border-right:4px solid #3b82f6;border-radius:50%;animation:spin 1s linear infinite}.spinner-small .spinner-circle{width:2rem;height:2rem;border-width:3px}.spinner-medium .spinner-circle{width:3rem;height:3rem;border-width:4px}.spinner-large .spinner-circle{width:4rem;height:4rem;border-width:5px}.loading-message{color:#374151;font-size:1rem;font-weight:500;max-width:300px;line-height:1.5}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (max-width: 640px){.screen-loading-content{margin:1rem;padding:1.5rem;min-width:auto;max-width:calc(100vw - 2rem)}.loading-message{font-size:.875rem;max-width:250px}.spinner-large .spinner-circle{width:3rem;height:3rem;border-width:4px}}\n"] }] }], propDecorators: { loading$: [{ type: Input }], loadingList$: [{ type: Input }], message: [{ type: Input }], size: [{ type: Input }], color: [{ type: Input }], backdrop: [{ type: Input }], backdropOpacity: [{ type: Input }], showMessage: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianV2by1zY3JlZW4tbG9hZGluZy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS1jb21wb25lbnRzL3NyYy9saWIvanV2by1zY3JlZW4tbG9hZGluZy9qdXZvLXNjcmVlbi1sb2FkaW5nLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3VpLWNvbXBvbmVudHMvc3JjL2xpYi9qdXZvLXNjcmVlbi1sb2FkaW5nL2p1dm8tc2NyZWVuLWxvYWRpbmcuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxVQUFVLEVBQUUsYUFBYSxFQUFFLEdBQUcsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7O0FBRXREOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1DRztBQVFILE1BQU0sT0FBTywwQkFBMEI7SUFQdkM7UUFXRSw4Q0FBOEM7UUFDckMsaUJBQVksR0FBMEIsRUFBRSxDQUFDO1FBRWxELHVEQUF1RDtRQUM5QyxZQUFPLEdBQVcsWUFBWSxDQUFDO1FBRXhDLG1EQUFtRDtRQUMxQyxTQUFJLEdBQWlDLE9BQU8sQ0FBQztRQUV0RCw4Q0FBOEM7UUFDckMsVUFBSyxHQUFXLFNBQVMsQ0FBQztRQUVuQyw2Q0FBNkM7UUFDcEMsYUFBUSxHQUFZLElBQUksQ0FBQztRQUVsQyxvQ0FBb0M7UUFDM0Isb0JBQWUsR0FBVyxHQUFHLENBQUM7UUFFdkMsd0RBQXdEO1FBQy9DLGdCQUFXLEdBQVksSUFBSSxDQUFDO0tBK0N0QztJQTdDQzs7O09BR0c7SUFDSCxJQUFJLGdCQUFnQjtRQUNsQixNQUFNLFdBQVcsR0FBMEIsRUFBRSxDQUFDO1FBRTlDLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2xCLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2xDLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDdEQsV0FBVyxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN6QyxDQUFDO1FBRUQsSUFBSSxXQUFXLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzdCLE9BQU8sSUFBSSxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDOUQsQ0FBQztRQUVELElBQUksV0FBVyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUM3QixPQUFPLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4QixDQUFDO1FBRUQsT0FBTyxhQUFhLENBQUMsV0FBVyxDQUFDLENBQUMsSUFBSSxDQUNwQyxHQUFHLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FDN0QsQ0FBQztJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSCxJQUFJLFNBQVM7UUFDWCxPQUFPLFdBQVcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxJQUFJLGFBQWE7UUFDZixPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsdUJBQXVCLElBQUksQ0FBQyxlQUFlLEdBQUc7U0FDbkUsQ0FBQztJQUNKLENBQUM7K0dBckVVLDBCQUEwQjttR0FBMUIsMEJBQTBCLHVSQy9DdkMsZ3BCQXFCTyx3MUNEc0JLLFlBQVk7OzRGQUlYLDBCQUEwQjtrQkFQdEMsU0FBUzsrQkFDRSxxQkFBcUIsY0FDbkIsSUFBSSxXQUNQLENBQUMsWUFBWSxDQUFDOzhCQU1kLFFBQVE7c0JBQWhCLEtBQUs7Z0JBR0csWUFBWTtzQkFBcEIsS0FBSztnQkFHRyxPQUFPO3NCQUFmLEtBQUs7Z0JBR0csSUFBSTtzQkFBWixLQUFLO2dCQUdHLEtBQUs7c0JBQWIsS0FBSztnQkFHRyxRQUFRO3NCQUFoQixLQUFLO2dCQUdHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBR0csV0FBVztzQkFBbkIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBjb21iaW5lTGF0ZXN0LCBtYXAgfSBmcm9tICdyeGpzJztcblxuLyoqXG4gKiBTY3JlZW4gTG9hZGluZyBDb21wb25lbnRcbiAqIFxuICogQGRlc2NyaXB0aW9uXG4gKiBBIHNjcmVlbi13aWRlIGxvYWRpbmcgb3ZlcmxheSBjb21wb25lbnQgZm9yIGJsb2NraW5nIFVJIGludGVyYWN0aW9ucyBkdXJpbmcgb3BlcmF0aW9ucy5cbiAqIE9yaWdpbmFsbHkgZGVzaWduZWQgZm9yIGJhY2tvZmZpY2UgYXBwbGljYXRpb25zIHRvIGhhbmRsZSBtdWx0aXBsZSBsb2FkaW5nIHN0YXRlcy5cbiAqIENhbiBjb21iaW5lIG11bHRpcGxlIG9ic2VydmFibGVzIHRvIHNob3cgbG9hZGluZyB3aGVuIGFueSBvcGVyYXRpb24gaXMgaW4gcHJvZ3Jlc3MuXG4gKiBcbiAqIEBleGFtcGxlXG4gKiBgYGBodG1sXG4gKiA8IS0tIFNpbmdsZSBsb2FkaW5nIHN0YXRlIC0tPlxuICogPGp1dm8tc2NyZWVuLWxvYWRpbmdcbiAqICAgW2xvYWRpbmckXT1cImRhdGFMb2FkaW5nJFwiXG4gKiAgIG1lc3NhZ2U9XCJMb2FkaW5nIGRhdGEuLi5cIj5cbiAqIDwvanV2by1zY3JlZW4tbG9hZGluZz5cbiAqIFxuICogPCEtLSBNdWx0aXBsZSBsb2FkaW5nIHN0YXRlcyAtLT5cbiAqIDxqdXZvLXNjcmVlbi1sb2FkaW5nXG4gKiAgIFtsb2FkaW5nTGlzdCRdPVwiW3NhdmVMb2FkaW5nJCwgZGVsZXRlTG9hZGluZyQsIHVwZGF0ZUxvYWRpbmckXVwiXG4gKiAgIG1lc3NhZ2U9XCJQcm9jZXNzaW5nIG9wZXJhdGlvbnMuLi5cIlxuICogICBbYmFja2Ryb3BdPVwidHJ1ZVwiPlxuICogPC9qdXZvLXNjcmVlbi1sb2FkaW5nPlxuICogXG4gKiA8IS0tIEN1c3RvbSBzdHlsZWQgbG9hZGluZyAtLT5cbiAqIDxqdXZvLXNjcmVlbi1sb2FkaW5nXG4gKiAgIFtsb2FkaW5nJF09XCJjcml0aWNhbE9wZXJhdGlvbiRcIlxuICogICBtZXNzYWdlPVwiQ3JpdGljYWwgb3BlcmF0aW9uIGluIHByb2dyZXNzLiBQbGVhc2UgZG8gbm90IHJlZnJlc2ggdGhlIHBhZ2UuXCJcbiAqICAgY29sb3I9XCIjZGMyNjI2XCJcbiAqICAgc2l6ZT1cImxhcmdlXCI+XG4gKiA8L2p1dm8tc2NyZWVuLWxvYWRpbmc+XG4gKiBgYGBcbiAqIFxuICogQHNlbGVjdG9yIGp1dm8tc2NyZWVuLWxvYWRpbmdcbiAqIEBzaW5jZSAyLjEuMFxuICogQGF1dGhvciBKdXZvIFJhZmEgVGVhbVxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdqdXZvLXNjcmVlbi1sb2FkaW5nJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIHRlbXBsYXRlVXJsOiAnLi9qdXZvLXNjcmVlbi1sb2FkaW5nLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL2p1dm8tc2NyZWVuLWxvYWRpbmcuY29tcG9uZW50LmNzcydcbn0pXG5leHBvcnQgY2xhc3MgSnV2b1NjcmVlbkxvYWRpbmdDb21wb25lbnQge1xuICAvKiogU2luZ2xlIGxvYWRpbmcgb2JzZXJ2YWJsZSAqL1xuICBASW5wdXQoKSBsb2FkaW5nJD86IE9ic2VydmFibGU8Ym9vbGVhbj47XG4gIFxuICAvKiogQXJyYXkgb2YgbG9hZGluZyBvYnNlcnZhYmxlcyB0byBjb21iaW5lICovXG4gIEBJbnB1dCgpIGxvYWRpbmdMaXN0JDogT2JzZXJ2YWJsZTxib29sZWFuPltdID0gW107XG4gIFxuICAvKiogTG9hZGluZyBtZXNzYWdlIHRvIGRpc3BsYXkgQGRlZmF1bHQgXCJMb2FkaW5nLi4uXCIgKi9cbiAgQElucHV0KCkgbWVzc2FnZTogc3RyaW5nID0gJ0xvYWRpbmcuLi4nO1xuICBcbiAgLyoqIFNpemUgb2YgdGhlIGxvYWRpbmcgc3Bpbm5lciBAZGVmYXVsdCBcImxhcmdlXCIgKi9cbiAgQElucHV0KCkgc2l6ZTogJ3NtYWxsJyB8ICdtZWRpdW0nIHwgJ2xhcmdlJyA9ICdsYXJnZSc7XG4gIFxuICAvKiogQ29sb3Igb2YgdGhlIHNwaW5uZXIgQGRlZmF1bHQgXCIjM2I4MmY2XCIgKi9cbiAgQElucHV0KCkgY29sb3I6IHN0cmluZyA9ICcjM2I4MmY2JztcbiAgXG4gIC8qKiBXaGV0aGVyIHRvIHNob3cgYmFja2Ryb3AgQGRlZmF1bHQgdHJ1ZSAqL1xuICBASW5wdXQoKSBiYWNrZHJvcDogYm9vbGVhbiA9IHRydWU7XG4gIFxuICAvKiogQmFja2Ryb3Agb3BhY2l0eSBAZGVmYXVsdCAwLjggKi9cbiAgQElucHV0KCkgYmFja2Ryb3BPcGFjaXR5OiBudW1iZXIgPSAwLjg7XG4gIFxuICAvKiogV2hldGhlciB0byBzaG93IHRoZSBsb2FkaW5nIG1lc3NhZ2UgQGRlZmF1bHQgdHJ1ZSAqL1xuICBASW5wdXQoKSBzaG93TWVzc2FnZTogYm9vbGVhbiA9IHRydWU7XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGNvbWJpbmVkIGxvYWRpbmcgc3RhdGUgZnJvbSBhbGwgc291cmNlc1xuICAgKiBAcmV0dXJucyBPYnNlcnZhYmxlPGJvb2xlYW4+IGluZGljYXRpbmcgaWYgYW55IGxvYWRpbmcgaXMgaW4gcHJvZ3Jlc3NcbiAgICovXG4gIGdldCBjb21iaW5lZExvYWRpbmckKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IG9ic2VydmFibGVzOiBPYnNlcnZhYmxlPGJvb2xlYW4+W10gPSBbXTtcbiAgICBcbiAgICBpZiAodGhpcy5sb2FkaW5nJCkge1xuICAgICAgb2JzZXJ2YWJsZXMucHVzaCh0aGlzLmxvYWRpbmckKTtcbiAgICB9XG4gICAgXG4gICAgaWYgKHRoaXMubG9hZGluZ0xpc3QkICYmIHRoaXMubG9hZGluZ0xpc3QkLmxlbmd0aCA+IDApIHtcbiAgICAgIG9ic2VydmFibGVzLnB1c2goLi4udGhpcy5sb2FkaW5nTGlzdCQpO1xuICAgIH1cbiAgICBcbiAgICBpZiAob2JzZXJ2YWJsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoc3Vic2NyaWJlciA9PiBzdWJzY3JpYmVyLm5leHQoZmFsc2UpKTtcbiAgICB9XG4gICAgXG4gICAgaWYgKG9ic2VydmFibGVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgcmV0dXJuIG9ic2VydmFibGVzWzBdO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gY29tYmluZUxhdGVzdChvYnNlcnZhYmxlcykucGlwZShcbiAgICAgIG1hcChsb2FkaW5nU3RhdGVzID0+IGxvYWRpbmdTdGF0ZXMuc29tZShsb2FkaW5nID0+IGxvYWRpbmcpKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgQ1NTIGNsYXNzIGZvciB0aGUgc3Bpbm5lciBzaXplXG4gICAqIEByZXR1cm5zIENTUyBjbGFzcyBuYW1lIGZvciB0aGUgY3VycmVudCBzaXplXG4gICAqL1xuICBnZXQgc2l6ZUNsYXNzKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGBzcGlubmVyLSR7dGhpcy5zaXplfWA7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgYmFja2Ryb3Agc3R5bGVcbiAgICogQHJldHVybnMgQ1NTIHN0eWxlIG9iamVjdCBmb3IgYmFja2Ryb3BcbiAgICovXG4gIGdldCBiYWNrZHJvcFN0eWxlKCk6IGFueSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICdiYWNrZ3JvdW5kLWNvbG9yJzogYHJnYmEoMjU1LCAyNTUsIDI1NSwgJHt0aGlzLmJhY2tkcm9wT3BhY2l0eX0pYFxuICAgIH07XG4gIH1cbn0gIiwiPGRpdiBjbGFzcz1cInNjcmVlbi1sb2FkaW5nLW92ZXJsYXlcIiBcbiAgICAgKm5nSWY9XCJjb21iaW5lZExvYWRpbmckIHwgYXN5bmNcIlxuICAgICBbY2xhc3Mud2l0aC1iYWNrZHJvcF09XCJiYWNrZHJvcFwiXG4gICAgIFtuZ1N0eWxlXT1cImJhY2tkcm9wID8gYmFja2Ryb3BTdHlsZSA6IG51bGxcIj5cbiAgXG4gIDxkaXYgY2xhc3M9XCJzY3JlZW4tbG9hZGluZy1jb250ZW50XCI+XG4gICAgPGRpdiBjbGFzcz1cInNwaW5uZXItY29udGFpbmVyXCI+XG4gICAgICA8ZGl2IFtjbGFzc109XCJzaXplQ2xhc3NcIiBcbiAgICAgICAgICAgY2xhc3M9XCJsb2FkaW5nLXNwaW5uZXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInNwaW5uZXItY2lyY2xlXCIgXG4gICAgICAgICAgICAgW3N0eWxlLmJvcmRlci10b3AtY29sb3JdPVwiY29sb3JcIlxuICAgICAgICAgICAgIFtzdHlsZS5ib3JkZXItcmlnaHQtY29sb3JdPVwiY29sb3JcIj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICBcbiAgICA8ZGl2IGNsYXNzPVwibG9hZGluZy1tZXNzYWdlXCIgXG4gICAgICAgICAqbmdJZj1cInNob3dNZXNzYWdlICYmIG1lc3NhZ2VcIj5cbiAgICAgIHt7IG1lc3NhZ2UgfX1cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj4gIl19