UNPKG

@spartacus/storefront

Version:

Spartacus Storefront is a package that you can include in your application, which allows you to add default storefront features.

90 lines 16.6 kB
import { ChangeDetectionStrategy, Component, Input, isDevMode, } from '@angular/core'; import { tap } from 'rxjs/operators'; import { ICON_TYPE } from '../../../cms-components/misc/icon/icon.model'; import * as i0 from "@angular/core"; import * as i1 from "./carousel.service"; import * as i2 from "../../../cms-components/misc/icon/icon.component"; import * as i3 from "@angular/common"; import * as i4 from "@spartacus/core"; /** * Generic carousel component that can be used to render any carousel items, * such as products, images, banners, or any component. Carousel items are * rendered in so-called carousel slides, and the previous/next buttons as well as * the indicator-buttons can used to navigate the slides. * * The component uses an array of Observables (`items$`) as an input, to allow * for lazy loading of items. * * The number of items per slide is calculated with the `itemWidth`, which can given * in pixels or percentage. * * To allow for flexible rendering of items, the rendering is delegated to the * given `template`. This allows for maximum flexibility. */ export class CarouselComponent { constructor(el, service) { this.el = el; this.service = service; /** * Specifies the minimum size of the carousel item, either in px or %. * This value is used for the calculation of numbers per carousel, so that * the number of carousel items is dynamic. The calculation uses the `itemWidth` * and the host element `clientWidth`, so that the carousel is reusable in * different layouts (for example in a 50% grid). */ this.itemWidth = '300px'; /** * Indicates whether the visual indicators are used. */ this.hideIndicators = false; this.indicatorIcon = ICON_TYPE.CIRCLE; this.previousIcon = ICON_TYPE.CARET_LEFT; this.nextIcon = ICON_TYPE.CARET_RIGHT; } set setItems(inputItems) { this.items = inputItems; //Reset slider when changing products this.activeSlide = 0; } ngOnInit() { if (!this.template && isDevMode()) { console.error('No template reference provided to render the carousel items for the `cx-carousel`'); return; } this.size$ = this.service .getItemsPerSlide(this.el.nativeElement, this.itemWidth) .pipe(tap(() => (this.activeSlide = 0))); } getSlideNumber(size, currentIndex) { let normalizedCurrentIndex = currentIndex + 1; return Math.ceil(normalizedCurrentIndex / size); } } CarouselComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: CarouselComponent, deps: [{ token: i0.ElementRef }, { token: i1.CarouselService }], target: i0.ɵɵFactoryTarget.Component }); CarouselComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.0.5", type: CarouselComponent, selector: "cx-carousel", inputs: { title: "title", setItems: ["items", "setItems"], template: "template", itemWidth: "itemWidth", hideIndicators: "hideIndicators", indicatorIcon: "indicatorIcon", previousIcon: "previousIcon", nextIcon: "nextIcon" }, ngImport: i0, template: "<ng-container *ngIf=\"items?.length > 0 && (size$ | async) as size\">\n <h2 *ngIf=\"title\">{{ title }}</h2>\n\n <div class=\"carousel-panel\" [ngClass]=\"'size-' + size\">\n <button\n *ngIf=\"size < items.length\"\n class=\"previous\"\n (click)=\"activeSlide = activeSlide - size\"\n [disabled]=\"activeSlide === 0\"\n [attr.aria-label]=\"'carousel.previousSlide' | cxTranslate\"\n >\n <cx-icon [type]=\"previousIcon\"></cx-icon>\n </button>\n\n <div class=\"slides\">\n <ng-container *ngFor=\"let _ of items; let i = index\">\n <div\n class=\"slide\"\n *ngIf=\"i % size === 0\"\n [class.active]=\"i === activeSlide\"\n >\n <ng-container\n *ngFor=\"let item of items | slice: i:i + size; let j = index\"\n >\n <div\n *ngIf=\"item | async as data\"\n class=\"item\"\n [class.active]=\"i === activeSlide\"\n >\n <ng-container\n *ngTemplateOutlet=\"template; context: { item: data }\"\n ></ng-container>\n </div>\n </ng-container>\n </div>\n </ng-container>\n </div>\n\n <button\n *ngIf=\"size < items.length\"\n class=\"next\"\n (click)=\"activeSlide = activeSlide + size\"\n tabindex=\"-1\"\n [disabled]=\"activeSlide > items.length - size - 1\"\n [attr.aria-label]=\"'carousel.nextSlide' | cxTranslate\"\n >\n <cx-icon [type]=\"nextIcon\"></cx-icon>\n </button>\n </div>\n\n <div *ngIf=\"!hideIndicators && size < items.length\" class=\"indicators\">\n <ng-container *ngFor=\"let _ of items; let i = index\">\n <button\n *ngIf=\"i % size === 0\"\n (focus)=\"activeSlide = i\"\n [disabled]=\"i === activeSlide\"\n [attr.aria-label]=\"\n 'carousel.slideNumber'\n | cxTranslate: { currentSlideNumber: getSlideNumber(size, i) }\n \"\n tabindex=\"-1\"\n >\n <cx-icon [type]=\"indicatorIcon\" aria-hidden=\"true\"></cx-icon>\n </button>\n </ng-container>\n </div>\n</ng-container>\n", components: [{ type: i2.IconComponent, selector: "cx-icon,[cxIcon]", inputs: ["cxIcon", "type"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i3.AsyncPipe, "cxTranslate": i4.TranslatePipe, "slice": i3.SlicePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: CarouselComponent, decorators: [{ type: Component, args: [{ selector: 'cx-carousel', templateUrl: './carousel.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.CarouselService }]; }, propDecorators: { title: [{ type: Input }], setItems: [{ type: Input, args: ['items'] }], template: [{ type: Input }], itemWidth: [{ type: Input }], hideIndicators: [{ type: Input }], indicatorIcon: [{ type: Input }], previousIcon: [{ type: Input }], nextIcon: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2Fyb3VzZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc3RvcmVmcm9udGxpYi9zaGFyZWQvY29tcG9uZW50cy9jYXJvdXNlbC9jYXJvdXNlbC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zdG9yZWZyb250bGliL3NoYXJlZC9jb21wb25lbnRzL2Nhcm91c2VsL2Nhcm91c2VsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUVULEtBQUssRUFDTCxTQUFTLEdBR1YsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3JDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQzs7Ozs7O0FBR3pFOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBTUgsTUFBTSxPQUFPLGlCQUFpQjtJQTZDNUIsWUFBc0IsRUFBYyxFQUFZLE9BQXdCO1FBQWxELE9BQUUsR0FBRixFQUFFLENBQVk7UUFBWSxZQUFPLEdBQVAsT0FBTyxDQUFpQjtRQXJCeEU7Ozs7OztXQU1HO1FBQ00sY0FBUyxHQUFHLE9BQU8sQ0FBQztRQUU3Qjs7V0FFRztRQUNNLG1CQUFjLEdBQUcsS0FBSyxDQUFDO1FBRXZCLGtCQUFhLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNqQyxpQkFBWSxHQUFHLFNBQVMsQ0FBQyxVQUFVLENBQUM7UUFDcEMsYUFBUSxHQUFHLFNBQVMsQ0FBQyxXQUFXLENBQUM7SUFLaUMsQ0FBQztJQWxDNUUsSUFDSSxRQUFRLENBQUMsVUFBNkI7UUFDeEMsSUFBSSxDQUFDLEtBQUssR0FBRyxVQUFVLENBQUM7UUFDeEIscUNBQXFDO1FBQ3JDLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZCLENBQUM7SUErQkQsUUFBUTtRQUNOLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxJQUFJLFNBQVMsRUFBRSxFQUFFO1lBQ2pDLE9BQU8sQ0FBQyxLQUFLLENBQ1gsbUZBQW1GLENBQ3BGLENBQUM7WUFDRixPQUFPO1NBQ1I7UUFDRCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPO2FBQ3RCLGdCQUFnQixDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUM7YUFDdkQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRCxjQUFjLENBQUMsSUFBWSxFQUFFLFlBQW9CO1FBQy9DLElBQUksc0JBQXNCLEdBQUcsWUFBWSxHQUFHLENBQUMsQ0FBQztRQUM5QyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEQsQ0FBQzs7OEdBOURVLGlCQUFpQjtrR0FBakIsaUJBQWlCLG9SQ2xDOUIsNG5FQW1FQTsyRkRqQ2EsaUJBQWlCO2tCQUw3QixTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxhQUFhO29CQUN2QixXQUFXLEVBQUUsMkJBQTJCO29CQUN4QyxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtpQkFDaEQ7K0hBS1UsS0FBSztzQkFBYixLQUFLO2dCQVFGLFFBQVE7c0JBRFgsS0FBSzt1QkFBQyxPQUFPO2dCQVdMLFFBQVE7c0JBQWhCLEtBQUs7Z0JBU0csU0FBUztzQkFBakIsS0FBSztnQkFLRyxjQUFjO3NCQUF0QixLQUFLO2dCQUVHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgSW5wdXQsXG4gIGlzRGV2TW9kZSxcbiAgT25Jbml0LFxuICBUZW1wbGF0ZVJlZixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBJQ09OX1RZUEUgfSBmcm9tICcuLi8uLi8uLi9jbXMtY29tcG9uZW50cy9taXNjL2ljb24vaWNvbi5tb2RlbCc7XG5pbXBvcnQgeyBDYXJvdXNlbFNlcnZpY2UgfSBmcm9tICcuL2Nhcm91c2VsLnNlcnZpY2UnO1xuXG4vKipcbiAqIEdlbmVyaWMgY2Fyb3VzZWwgY29tcG9uZW50IHRoYXQgY2FuIGJlIHVzZWQgdG8gcmVuZGVyIGFueSBjYXJvdXNlbCBpdGVtcyxcbiAqIHN1Y2ggYXMgcHJvZHVjdHMsIGltYWdlcywgYmFubmVycywgb3IgYW55IGNvbXBvbmVudC4gQ2Fyb3VzZWwgaXRlbXMgYXJlXG4gKiByZW5kZXJlZCBpbiBzby1jYWxsZWQgY2Fyb3VzZWwgc2xpZGVzLCBhbmQgdGhlIHByZXZpb3VzL25leHQgYnV0dG9ucyBhcyB3ZWxsIGFzXG4gKiB0aGUgaW5kaWNhdG9yLWJ1dHRvbnMgY2FuIHVzZWQgdG8gbmF2aWdhdGUgdGhlIHNsaWRlcy5cbiAqXG4gKiBUaGUgY29tcG9uZW50IHVzZXMgYW4gYXJyYXkgb2YgT2JzZXJ2YWJsZXMgKGBpdGVtcyRgKSBhcyBhbiBpbnB1dCwgdG8gYWxsb3dcbiAqIGZvciBsYXp5IGxvYWRpbmcgb2YgaXRlbXMuXG4gKlxuICogVGhlIG51bWJlciBvZiBpdGVtcyBwZXIgc2xpZGUgaXMgY2FsY3VsYXRlZCB3aXRoIHRoZSBgaXRlbVdpZHRoYCwgd2hpY2ggY2FuIGdpdmVuXG4gKiBpbiBwaXhlbHMgb3IgcGVyY2VudGFnZS5cbiAqXG4gKiBUbyBhbGxvdyBmb3IgZmxleGlibGUgcmVuZGVyaW5nIG9mIGl0ZW1zLCB0aGUgcmVuZGVyaW5nIGlzIGRlbGVnYXRlZCB0byB0aGVcbiAqIGdpdmVuIGB0ZW1wbGF0ZWAuIFRoaXMgYWxsb3dzIGZvciBtYXhpbXVtIGZsZXhpYmlsaXR5LlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjeC1jYXJvdXNlbCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9jYXJvdXNlbC5jb21wb25lbnQuaHRtbCcsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBDYXJvdXNlbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIC8qKlxuICAgKiBUaGUgdGl0bGUgaXMgcmVuZGVyZWQgYXMgdGhlIGNhcm91c2VsIGhlYWRpbmcuXG4gICAqL1xuICBASW5wdXQoKSB0aXRsZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgaXRlbXMkIHJlcHJlc2VudCB0aGUgY2Fyb3VzZWwgaXRlbXMuIFRoZSBpdGVtcyQgYXJlXG4gICAqIG9ic2VydmFibGVzIHNvIHRoYXQgdGhlIGl0ZW1zIGNhbiBiZSBsb2FkZWQgb24gZGVtYW5kLlxuICAgKi9cbiAgaXRlbXM6IE9ic2VydmFibGU8YW55PltdO1xuICBASW5wdXQoJ2l0ZW1zJylcbiAgc2V0IHNldEl0ZW1zKGlucHV0SXRlbXM6IE9ic2VydmFibGU8YW55PltdKSB7XG4gICAgdGhpcy5pdGVtcyA9IGlucHV0SXRlbXM7XG4gICAgLy9SZXNldCBzbGlkZXIgd2hlbiBjaGFuZ2luZyBwcm9kdWN0c1xuICAgIHRoaXMuYWN0aXZlU2xpZGUgPSAwO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSB0ZW1wbGF0ZSBpcyByZW5kZXJlZCBmb3IgZWFjaCBpdGVtLCBzbyB0aGF0IHRoZSBhY3R1YWxcbiAgICogdmlldyBjYW4gYmUgZ2l2ZW4gYnkgdGhlIGNvbXBvZW50IHRoYXQgdXNlcyB0aGUgYENhcm91c2VsQ29tcG9uZW50YC5cbiAgICovXG4gIEBJbnB1dCgpIHRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgdGhlIG1pbmltdW0gc2l6ZSBvZiB0aGUgY2Fyb3VzZWwgaXRlbSwgZWl0aGVyIGluIHB4IG9yICUuXG4gICAqIFRoaXMgdmFsdWUgaXMgdXNlZCBmb3IgdGhlIGNhbGN1bGF0aW9uIG9mIG51bWJlcnMgcGVyIGNhcm91c2VsLCBzbyB0aGF0XG4gICAqIHRoZSBudW1iZXIgb2YgY2Fyb3VzZWwgaXRlbXMgaXMgZHluYW1pYy4gVGhlIGNhbGN1bGF0aW9uIHVzZXMgdGhlIGBpdGVtV2lkdGhgXG4gICAqIGFuZCB0aGUgaG9zdCBlbGVtZW50IGBjbGllbnRXaWR0aGAsIHNvIHRoYXQgdGhlIGNhcm91c2VsIGlzIHJldXNhYmxlIGluXG4gICAqIGRpZmZlcmVudCBsYXlvdXRzIChmb3IgZXhhbXBsZSBpbiBhIDUwJSBncmlkKS5cbiAgICovXG4gIEBJbnB1dCgpIGl0ZW1XaWR0aCA9ICczMDBweCc7XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSB2aXN1YWwgaW5kaWNhdG9ycyBhcmUgdXNlZC5cbiAgICovXG4gIEBJbnB1dCgpIGhpZGVJbmRpY2F0b3JzID0gZmFsc2U7XG5cbiAgQElucHV0KCkgaW5kaWNhdG9ySWNvbiA9IElDT05fVFlQRS5DSVJDTEU7XG4gIEBJbnB1dCgpIHByZXZpb3VzSWNvbiA9IElDT05fVFlQRS5DQVJFVF9MRUZUO1xuICBASW5wdXQoKSBuZXh0SWNvbiA9IElDT05fVFlQRS5DQVJFVF9SSUdIVDtcblxuICBhY3RpdmVTbGlkZTogbnVtYmVyO1xuICBzaXplJDogT2JzZXJ2YWJsZTxudW1iZXI+O1xuXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBlbDogRWxlbWVudFJlZiwgcHJvdGVjdGVkIHNlcnZpY2U6IENhcm91c2VsU2VydmljZSkge31cblxuICBuZ09uSW5pdCgpIHtcbiAgICBpZiAoIXRoaXMudGVtcGxhdGUgJiYgaXNEZXZNb2RlKCkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICdObyB0ZW1wbGF0ZSByZWZlcmVuY2UgcHJvdmlkZWQgdG8gcmVuZGVyIHRoZSBjYXJvdXNlbCBpdGVtcyBmb3IgdGhlIGBjeC1jYXJvdXNlbGAnXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnNpemUkID0gdGhpcy5zZXJ2aWNlXG4gICAgICAuZ2V0SXRlbXNQZXJTbGlkZSh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQsIHRoaXMuaXRlbVdpZHRoKVxuICAgICAgLnBpcGUodGFwKCgpID0+ICh0aGlzLmFjdGl2ZVNsaWRlID0gMCkpKTtcbiAgfVxuXG4gIGdldFNsaWRlTnVtYmVyKHNpemU6IG51bWJlciwgY3VycmVudEluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGxldCBub3JtYWxpemVkQ3VycmVudEluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICByZXR1cm4gTWF0aC5jZWlsKG5vcm1hbGl6ZWRDdXJyZW50SW5kZXggLyBzaXplKTtcbiAgfVxufVxuIiwiPG5nLWNvbnRhaW5lciAqbmdJZj1cIml0ZW1zPy5sZW5ndGggPiAwICYmIChzaXplJCB8IGFzeW5jKSBhcyBzaXplXCI+XG4gIDxoMiAqbmdJZj1cInRpdGxlXCI+e3sgdGl0bGUgfX08L2gyPlxuXG4gIDxkaXYgY2xhc3M9XCJjYXJvdXNlbC1wYW5lbFwiIFtuZ0NsYXNzXT1cIidzaXplLScgKyBzaXplXCI+XG4gICAgPGJ1dHRvblxuICAgICAgKm5nSWY9XCJzaXplIDwgaXRlbXMubGVuZ3RoXCJcbiAgICAgIGNsYXNzPVwicHJldmlvdXNcIlxuICAgICAgKGNsaWNrKT1cImFjdGl2ZVNsaWRlID0gYWN0aXZlU2xpZGUgLSBzaXplXCJcbiAgICAgIFtkaXNhYmxlZF09XCJhY3RpdmVTbGlkZSA9PT0gMFwiXG4gICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidjYXJvdXNlbC5wcmV2aW91c1NsaWRlJyB8IGN4VHJhbnNsYXRlXCJcbiAgICA+XG4gICAgICA8Y3gtaWNvbiBbdHlwZV09XCJwcmV2aW91c0ljb25cIj48L2N4LWljb24+XG4gICAgPC9idXR0b24+XG5cbiAgICA8ZGl2IGNsYXNzPVwic2xpZGVzXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBfIG9mIGl0ZW1zOyBsZXQgaSA9IGluZGV4XCI+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICBjbGFzcz1cInNsaWRlXCJcbiAgICAgICAgICAqbmdJZj1cImkgJSBzaXplID09PSAwXCJcbiAgICAgICAgICBbY2xhc3MuYWN0aXZlXT1cImkgPT09IGFjdGl2ZVNsaWRlXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGl0ZW1zIHwgc2xpY2U6IGk6aSArIHNpemU7IGxldCBqID0gaW5kZXhcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgKm5nSWY9XCJpdGVtIHwgYXN5bmMgYXMgZGF0YVwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiaXRlbVwiXG4gICAgICAgICAgICAgIFtjbGFzcy5hY3RpdmVdPVwiaSA9PT0gYWN0aXZlU2xpZGVcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0ZW1wbGF0ZTsgY29udGV4dDogeyBpdGVtOiBkYXRhIH1cIlxuICAgICAgICAgICAgICA+PC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L2Rpdj5cblxuICAgIDxidXR0b25cbiAgICAgICpuZ0lmPVwic2l6ZSA8IGl0ZW1zLmxlbmd0aFwiXG4gICAgICBjbGFzcz1cIm5leHRcIlxuICAgICAgKGNsaWNrKT1cImFjdGl2ZVNsaWRlID0gYWN0aXZlU2xpZGUgKyBzaXplXCJcbiAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgW2Rpc2FibGVkXT1cImFjdGl2ZVNsaWRlID4gaXRlbXMubGVuZ3RoIC0gc2l6ZSAtIDFcIlxuICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInY2Fyb3VzZWwubmV4dFNsaWRlJyB8IGN4VHJhbnNsYXRlXCJcbiAgICA+XG4gICAgICA8Y3gtaWNvbiBbdHlwZV09XCJuZXh0SWNvblwiPjwvY3gtaWNvbj5cbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG5cbiAgPGRpdiAqbmdJZj1cIiFoaWRlSW5kaWNhdG9ycyAmJiBzaXplIDwgaXRlbXMubGVuZ3RoXCIgY2xhc3M9XCJpbmRpY2F0b3JzXCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgXyBvZiBpdGVtczsgbGV0IGkgPSBpbmRleFwiPlxuICAgICAgPGJ1dHRvblxuICAgICAgICAqbmdJZj1cImkgJSBzaXplID09PSAwXCJcbiAgICAgICAgKGZvY3VzKT1cImFjdGl2ZVNsaWRlID0gaVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpID09PSBhY3RpdmVTbGlkZVwiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiXG4gICAgICAgICAgJ2Nhcm91c2VsLnNsaWRlTnVtYmVyJ1xuICAgICAgICAgICAgfCBjeFRyYW5zbGF0ZTogeyBjdXJyZW50U2xpZGVOdW1iZXI6IGdldFNsaWRlTnVtYmVyKHNpemUsIGkpIH1cbiAgICAgICAgXCJcbiAgICAgICAgdGFiaW5kZXg9XCItMVwiXG4gICAgICA+XG4gICAgICAgIDxjeC1pY29uIFt0eXBlXT1cImluZGljYXRvckljb25cIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2N4LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgPC9kaXY+XG48L25nLWNvbnRhaW5lcj5cbiJdfQ==