UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

89 lines 17.4 kB
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, inject, Input, Output } from '@angular/core'; import { Subject } from 'rxjs'; import { filter as rxFilter, takeUntil } from 'rxjs/operators'; import { FilterRemoveAllEvent } from '../events/filter-remove-all-event'; import { FilterService } from '../filter.service'; import * as i0 from "@angular/core"; import * as i1 from "../../icon/icon.component"; import * as i2 from "../../menu/menu/menu.component"; import * as i3 from "../../menu/menu-trigger/menu-trigger.directive"; import * as i4 from "../../menu/menu-item/menu-item.component"; let uniqueId = 0; export class FilterDropdownComponent { /** Defined the closeOnBlur state for the ux-menu trigger */ set closeOnBlur(value) { this._closeOnBlur = coerceBooleanProperty(value); } get closeOnBlur() { return this._closeOnBlur; } get filterId() { return this.id ?? `ux-filter-dropdown-${this._uniqueId}`; } constructor() { this._filterService = inject(FilterService); this._changeDetector = inject(ChangeDetectorRef); /** Store the unique id so we only increment the counter once per instance */ this._uniqueId = uniqueId++; /** The list of items to display in the dropdown */ this.filters = []; /** Emit when the filter menu is closed */ this.closed = new EventEmitter(); this._onDestroy = new Subject(); this._closeOnBlur = false; this._filterService.events$.pipe(rxFilter(event => event instanceof FilterRemoveAllEvent), takeUntil(this._onDestroy)) .subscribe(() => this.removeFilter()); // ensure that the current selected filter is still selected when the active filters change this._filterService.filters$.pipe(takeUntil(this._onDestroy)).subscribe(filters => { if (this.selected && filters.indexOf(this.selected) === -1) { this.removeFilter(); } }); } ngOnInit() { this.selected = this.initial; // check to see if any of the filters have been preselected or changes to selected filters this._filterService.filters$.pipe(takeUntil(this._onDestroy)).subscribe(filters => { filters.forEach(filter => { if (this.filters.indexOf(filter) !== -1) { this.selected = filter; } }); this._changeDetector.markForCheck(); }); } ngOnDestroy() { this._onDestroy.next(); this._onDestroy.complete(); } selectFilter(filter, event) { this.removeFilter(); this.selected = filter; this._filterService.add(this.selected); event.stopPropagation(); event.preventDefault(); } removeFilter() { this._filterService.remove(this.selected); this.selected = this.initial; this._changeDetector.markForCheck(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: FilterDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: FilterDropdownComponent, selector: "ux-filter-dropdown", inputs: { id: "id", filters: "filters", initial: "initial", closeOnBlur: "closeOnBlur" }, outputs: { closed: "closed" }, ngImport: i0, template: "<div class=\"btn-group\">\n <button\n type=\"button\"\n class=\"filter-dropdown btn dropdown-toggle\"\n [id]=\"filterId + '-trigger'\"\n [class.active]=\"selected !== initial\"\n [uxMenuTriggerFor]=\"menu\"\n [closeOnBlur]=\"closeOnBlur\"\n (closed)=\"closed.emit()\">\n {{ selected?.group }}\n @if (selected !== initial) {\n <span class=\"filter-header\">\n ({{ selected?.name }})\n </span>\n }\n <ux-icon name=\"down\"></ux-icon>\n </button>\n\n <ux-menu #menu menuClass=\"ux-filter-menu\">\n @for (filter of filters; track filter; let index = $index) {\n <button\n type=\"button\"\n uxMenuItem\n [id]=\"filter.id || filterId + '-item-' + index\"\n [attr.aria-selected]=\"filter === selected\"\n (click)=\"selectFilter(filter, $event)\"\n (keydown.enter)=\"selectFilter(filter, $event)\">\n <ux-icon\n name=\"checkmark\"\n [style.visibility]=\"filter === selected ? 'visible' : 'hidden'\">\n </ux-icon>\n <span class=\"filter-dropdown-title\">{{ filter.name }}</span>\n </button>\n }\n </ux-menu>\n</div>\n", dependencies: [{ kind: "component", type: i1.IconComponent, selector: "ux-icon", inputs: ["name", "size", "rotate", "flipHorizontal", "flipVertical"] }, { kind: "component", type: i2.MenuComponent, selector: "ux-menu", inputs: ["id", "placement", "alignment", "animate", "menuClass"], outputs: ["opening", "opened", "closing", "closed"] }, { kind: "directive", type: i3.MenuTriggerDirective, selector: "[uxMenuTriggerFor]", inputs: ["uxMenuTriggerFor", "disabled", "uxMenuParent", "closeOnBlur"], outputs: ["closed"], exportAs: ["ux-menu-trigger"] }, { kind: "component", type: i4.MenuItemComponent, selector: "[uxMenuItem]", inputs: ["disabled", "closeOnSelect", "role"], outputs: ["activate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: FilterDropdownComponent, decorators: [{ type: Component, args: [{ selector: 'ux-filter-dropdown', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"btn-group\">\n <button\n type=\"button\"\n class=\"filter-dropdown btn dropdown-toggle\"\n [id]=\"filterId + '-trigger'\"\n [class.active]=\"selected !== initial\"\n [uxMenuTriggerFor]=\"menu\"\n [closeOnBlur]=\"closeOnBlur\"\n (closed)=\"closed.emit()\">\n {{ selected?.group }}\n @if (selected !== initial) {\n <span class=\"filter-header\">\n ({{ selected?.name }})\n </span>\n }\n <ux-icon name=\"down\"></ux-icon>\n </button>\n\n <ux-menu #menu menuClass=\"ux-filter-menu\">\n @for (filter of filters; track filter; let index = $index) {\n <button\n type=\"button\"\n uxMenuItem\n [id]=\"filter.id || filterId + '-item-' + index\"\n [attr.aria-selected]=\"filter === selected\"\n (click)=\"selectFilter(filter, $event)\"\n (keydown.enter)=\"selectFilter(filter, $event)\">\n <ux-icon\n name=\"checkmark\"\n [style.visibility]=\"filter === selected ? 'visible' : 'hidden'\">\n </ux-icon>\n <span class=\"filter-dropdown-title\">{{ filter.name }}</span>\n </button>\n }\n </ux-menu>\n</div>\n" }] }], ctorParameters: () => [], propDecorators: { id: [{ type: Input }], filters: [{ type: Input }], initial: [{ type: Input }], closeOnBlur: [{ type: Input }], closed: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVyLWRyb3Bkb3duLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL2ZpbHRlcnMvZmlsdGVyLWRyb3Bkb3duL2ZpbHRlci1kcm9wZG93bi5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9maWx0ZXJzL2ZpbHRlci1kcm9wZG93bi9maWx0ZXItZHJvcGRvd24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFnQixxQkFBcUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzVFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQXFCLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM5SSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxNQUFNLElBQUksUUFBUSxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7Ozs7O0FBR2xELElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQztBQU9qQixNQUFNLE9BQU8sdUJBQXVCO0lBaUJoQyw0REFBNEQ7SUFDNUQsSUFBYSxXQUFXLENBQUMsS0FBYztRQUNuQyxJQUFJLENBQUMsWUFBWSxHQUFHLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFFRCxJQUFJLFdBQVc7UUFDWCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDN0IsQ0FBQztJQU9ELElBQUksUUFBUTtRQUNSLE9BQU8sSUFBSSxDQUFDLEVBQUUsSUFBSSxzQkFBdUIsSUFBSSxD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QUF1QjtrQkFMbkMsU0FBUzsrQkFDSSxvQkFBb0IsbUJBRWIsdUJBQXVCLENBQUMsTUFBTTt3REFXdEMsRUFBRTtzQkFBVixLQUFLO2dCQUdHLE9BQU87c0JBQWYsS0FBSztnQkFHRyxPQUFPO3NCQUFmLEtBQUs7Z0JBR08sV0FBVztzQkFBdkIsS0FBSztnQkFTYSxNQUFNO3NCQUF4QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQm9vbGVhbklucHV0LCBjb2VyY2VCb29sZWFuUHJvcGVydHkgfSBmcm9tICdAYW5ndWxhci9jZGsvY29lcmNpb24nO1xuaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgaW5qZWN0LCBJbnB1dCwgT25EZXN0cm95LCBPbkluaXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlsdGVyIGFzIHJ4RmlsdGVyLCB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBGaWx0ZXJSZW1vdmVBbGxFdmVudCB9IGZyb20gJy4uL2V2ZW50cy9maWx0ZXItcmVtb3ZlLWFsbC1ldmVudCc7XG5pbXBvcnQgeyBGaWx0ZXJTZXJ2aWNlIH0gZnJvbSAnLi4vZmlsdGVyLnNlcnZpY2UnO1xuaW1wb3J0IHsgRmlsdGVyIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9maWx0ZXIuaW50ZXJmYWNlJztcblxubGV0IHVuaXF1ZUlkID0gMDtcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICd1eC1maWx0ZXItZHJvcGRvd24nLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9maWx0ZXItZHJvcGRvd24uY29tcG9uZW50Lmh0bWwnLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIEZpbHRlckRyb3Bkb3duQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2ZpbHRlclNlcnZpY2UgPSBpbmplY3QoRmlsdGVyU2VydmljZSk7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9jaGFuZ2VEZXRlY3RvciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cbiAgICAvKiogU3RvcmUgdGhlIHVuaXF1ZSBpZCBzbyB3ZSBvbmx5IGluY3JlbWVudCB0aGUgY291bnRlciBvbmNlIHBlciBpbnN0YW5jZSAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX3VuaXF1ZUlkOiBudW1iZXIgPSB1bmlxdWVJZCsrO1xuXG4gICAgLyoqIERlZmluZSB0aGUgaW5wdXQgZm9yIHRoZSBjb21wb25lbnQgKi9cbiAgICBASW5wdXQoKSBpZDogc3RyaW5nO1xuXG4gICAgLyoqIFRoZSBsaXN0IG9mIGl0ZW1zIHRvIGRpc3BsYXkgaW4gdGhlIGRyb3Bkb3duICovXG4gICAgQElucHV0KCkgZmlsdGVyczogRmlsdGVyW10gPSBbXTtcblxuICAgIC8qKiBEZWZpbmUgYW4gaW5pdGlhbCBpdGVtIHRvIHNlbGVjdCAqL1xuICAgIEBJbnB1dCgpIGluaXRpYWw6IEZpbHRlcjtcblxuICAgIC8qKiBEZWZpbmVkIHRoZSBjbG9zZU9uQmx1ciBzdGF0ZSBmb3IgdGhlIHV4LW1lbnUgdHJpZ2dlciAqL1xuICAgIEBJbnB1dCgpIHNldCBjbG9zZU9uQmx1cih2YWx1ZTogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9jbG9zZU9uQmx1ciA9IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgZ2V0IGNsb3NlT25CbHVyKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2xvc2VPbkJsdXI7XG4gICAgfVxuXG4gICAgLyoqIEVtaXQgd2hlbiB0aGUgZmlsdGVyIG1lbnUgaXMgY2xvc2VkICovXG4gICAgQE91dHB1dCgpIHJlYWRvbmx5IGNsb3NlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAgIHNlbGVjdGVkOiBGaWx0ZXI7XG5cbiAgICBnZXQgZmlsdGVySWQoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaWQgPz8gYHV4LWZpbHRlci1kcm9wZG93bi0keyB0aGlzLl91bmlxdWVJZCB9YDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9vbkRlc3Ryb3kgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICAgIHByaXZhdGUgX2Nsb3NlT25CbHVyOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcblxuICAgICAgICB0aGlzLl9maWx0ZXJTZXJ2aWNlLmV2ZW50cyQucGlwZShyeEZpbHRlcihldmVudCA9PiBldmVudCBpbnN0YW5jZW9mIEZpbHRlclJlbW92ZUFsbEV2ZW50KSwgdGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMucmVtb3ZlRmlsdGVyKCkpO1xuXG4gICAgICAgIC8vIGVuc3VyZSB0aGF0IHRoZSBjdXJyZW50IHNlbGVjdGVkIGZpbHRlciBpcyBzdGlsbCBzZWxlY3RlZCB3aGVuIHRoZSBhY3RpdmUgZmlsdGVycyBjaGFuZ2VcbiAgICAgICAgdGhpcy5fZmlsdGVyU2VydmljZS5maWx0ZXJzJC5waXBlKHRha2VVbnRpbCh0aGlzLl9vbkRlc3Ryb3kpKS5zdWJzY3JpYmUoZmlsdGVycyA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZWxlY3RlZCAmJiBmaWx0ZXJzLmluZGV4T2YodGhpcy5zZWxlY3RlZCkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVGaWx0ZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWQgPSB0aGlzLmluaXRpYWw7XG5cbiAgICAgICAgLy8gY2hlY2sgdG8gc2VlIGlmIGFueSBvZiB0aGUgZmlsdGVycyBoYXZlIGJlZW4gcHJlc2VsZWN0ZWQgb3IgY2hhbmdlcyB0byBzZWxlY3RlZCBmaWx0ZXJzXG4gICAgICAgIHRoaXMuX2ZpbHRlclNlcnZpY2UuZmlsdGVycyQucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSkuc3Vic2NyaWJlKGZpbHRlcnMgPT4ge1xuICAgICAgICAgICAgZmlsdGVycy5mb3JFYWNoKGZpbHRlciA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZmlsdGVycy5pbmRleE9mKGZpbHRlcikgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWQgPSBmaWx0ZXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yLm1hcmtGb3JDaGVjaygpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fb25EZXN0cm95Lm5leHQoKTtcbiAgICAgICAgdGhpcy5fb25EZXN0cm95LmNvbXBsZXRlKCk7XG4gICAgfVxuXG4gICAgc2VsZWN0RmlsdGVyKGZpbHRlcjogRmlsdGVyLCBldmVudDogRXZlbnQpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVGaWx0ZXIoKTtcbiAgICAgICAgdGhpcy5zZWxlY3RlZCA9IGZpbHRlcjtcbiAgICAgICAgdGhpcy5fZmlsdGVyU2VydmljZS5hZGQodGhpcy5zZWxlY3RlZCk7XG5cbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuXG4gICAgcmVtb3ZlRmlsdGVyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9maWx0ZXJTZXJ2aWNlLnJlbW92ZSh0aGlzLnNlbGVjdGVkKTtcbiAgICAgICAgdGhpcy5zZWxlY3RlZCA9IHRoaXMuaW5pdGlhbDtcbiAgICAgICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3IubWFya0ZvckNoZWNrKCk7XG4gICAgfVxuXG4gICAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX2Nsb3NlT25CbHVyOiBCb29sZWFuSW5wdXQ7XG59IiwiPGRpdiBjbGFzcz1cImJ0bi1ncm91cFwiPlxuICA8YnV0dG9uXG4gICAgdHlwZT1cImJ1dHRvblwiXG4gICAgY2xhc3M9XCJmaWx0ZXItZHJvcGRvd24gYnRuIGRyb3Bkb3duLXRvZ2dsZVwiXG4gICAgW2lkXT1cImZpbHRlcklkICsgJy10cmlnZ2VyJ1wiXG4gICAgW2NsYXNzLmFjdGl2ZV09XCJzZWxlY3RlZCAhPT0gaW5pdGlhbFwiXG4gICAgW3V4TWVudVRyaWdnZXJGb3JdPVwibWVudVwiXG4gICAgW2Nsb3NlT25CbHVyXT1cImNsb3NlT25CbHVyXCJcbiAgICAoY2xvc2VkKT1cImNsb3NlZC5lbWl0KClcIj5cbiAgICB7eyBzZWxlY3RlZD8uZ3JvdXAgfX1cbiAgICBAaWYgKHNlbGVjdGVkICE9PSBpbml0aWFsKSB7XG4gICAgICA8c3BhbiBjbGFzcz1cImZpbHRlci1oZWFkZXJcIj5cbiAgICAgICAgKHt7IHNlbGVjdGVkPy5uYW1lIH19KVxuICAgICAgPC9zcGFuPlxuICAgIH1cbiAgICA8dXgtaWNvbiBuYW1lPVwiZG93blwiPjwvdXgtaWNvbj5cbiAgPC9idXR0b24+XG5cbiAgPHV4LW1lbnUgI21lbnUgbWVudUNsYXNzPVwidXgtZmlsdGVyLW1lbnVcIj5cbiAgICBAZm9yIChmaWx0ZXIgb2YgZmlsdGVyczsgdHJhY2sgZmlsdGVyOyBsZXQgaW5kZXggPSAkaW5kZXgpIHtcbiAgICAgIDxidXR0b25cbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIHV4TWVudUl0ZW1cbiAgICAgICAgW2lkXT1cImZpbHRlci5pZCB8fCBmaWx0ZXJJZCArICctaXRlbS0nICsgaW5kZXhcIlxuICAgICAgICBbYXR0ci5hcmlhLXNlbGVjdGVkXT1cImZpbHRlciA9PT0gc2VsZWN0ZWRcIlxuICAgICAgICAoY2xpY2spPVwic2VsZWN0RmlsdGVyKGZpbHRlciwgJGV2ZW50KVwiXG4gICAgICAgIChrZXlkb3duLmVudGVyKT1cInNlbGVjdEZpbHRlcihmaWx0ZXIsICRldmVudClcIj5cbiAgICAgICAgPHV4LWljb25cbiAgICAgICAgICBuYW1lPVwiY2hlY2ttYXJrXCJcbiAgICAgICAgICBbc3R5bGUudmlzaWJpbGl0eV09XCJmaWx0ZXIgPT09IHNlbGVjdGVkID8gJ3Zpc2libGUnIDogJ2hpZGRlbidcIj5cbiAgICAgICAgPC91eC1pY29uPlxuICAgICAgICA8c3BhbiBjbGFzcz1cImZpbHRlci1kcm9wZG93bi10aXRsZVwiPnt7IGZpbHRlci5uYW1lIH19PC9zcGFuPlxuICAgICAgPC9idXR0b24+XG4gICAgfVxuICA8L3V4LW1lbnU+XG48L2Rpdj5cbiJdfQ==