@spartacus/storefront
Version:
Spartacus Storefront is a package that you can include in your application, which allows you to add default storefront features.
167 lines • 20.1 kB
JavaScript
import { isPlatformBrowser } from '@angular/common';
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { of } from 'rxjs';
import { distinctUntilChanged, map } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "@spartacus/core";
import * as i2 from "../config/layout-config";
/**
* The `BreakpointService` resolves the various screen sizes that are used in
* the storefront. The screen sizes are globally configurable based on your
* layout requirements. You can adjust the screen sizes by setting the minimum
* and/or maximum size for a breakpoint, as well as extending the configuration
* with new screens.
*
* By default, the `BreakpointService` is based on the breakpoints from the
* Bootstrap ui library:
* - `xs`: < 576px
* - `sm`: 576px - 767px
* - `md`: 768px - 991px
* - `lg`: 992px - 1199px
* - `xl`: >= 1200px
*/
export class BreakpointService {
constructor(winRef, layoutConfig, platform) {
this.winRef = winRef;
this.layoutConfig = layoutConfig;
this.platform = platform;
this.breakpoint$ = isPlatformBrowser(this.platform)
? this.winRef.resize$.pipe(map((event) => this.getBreakpoint(event.target.innerWidth)), distinctUntilChanged())
: of(this.fallbackBreakpoint);
}
/**
* Returns the breakpoints for the storefront layout.
*
* The breakpoints are driven by the `LayoutConfig.breakpoints` and sorted based on
* the given screen size.
*/
get breakpoints() {
if (!this._breakpoints) {
this._breakpoints = this.resolveBreakpointsFromConfig();
}
return this._breakpoints;
}
/**
* Returns the _maximum_ size for the breakpoint, given by the `LayoutConfig.breakpoints`
* configuration.
*/
getSize(breakpoint) {
var _a, _b;
return ((_a = this.getMaxSize(breakpoint)) !== null && _a !== void 0 ? _a :
// if there's no direct max value or explicit max value
// we must derive the max value from the previous min
this.getMinSize((_b = this.breakpoints) === null || _b === void 0 ? void 0 : _b[this.breakpoints.indexOf(breakpoint) + 1]));
}
/**
* Indicates whether the current screen size is smaller than the maximum size of the
* given breakpoint.
*
* If the given breakpoint is `BREAKPOINT.md`, the method returns `true` when the
* window innerWidth is smaller than the configured size of `BREAKPOINT.md`.
*/
isDown(breakpoint) {
return this.breakpoint$.pipe(map((br) => this.breakpoints
.slice(0, this.breakpoints.indexOf(breakpoint) + 1)
.includes(br)));
}
/**
* Indicates whether the current screen size is larger than the minimum size of the
* given breakpoint.
*
* If the given breakpoint is `BREAKPOINT.md`, the method returns `true` when the
* window innerWidth is larger than the configured size of `BREAKPOINT.sm`.
*/
isUp(breakpoint) {
return this.breakpoint$.pipe(map((br) => this.breakpoints
.slice(this.breakpoints.indexOf(breakpoint))
.includes(br)));
}
/**
* Indicates whether the given breakpoint fits in the current screen size.
*/
isEqual(breakpoint) {
return this.breakpoint$.pipe(map((br) => br === breakpoint));
}
/**
* Returns the fallback breakpoint in case no breakpoint can be resolved. This is
* typically the case when we're on SSR without an actual window.
*
* Returns the smallest screen size (mobile first).
*/
get fallbackBreakpoint() {
var _a;
return (_a = this.breakpoints) === null || _a === void 0 ? void 0 : _a[0];
}
/**
* Resolves the breakpoints and sorts them according to the configured size.
*
* The sort order is by small to large screens.
*/
resolveBreakpointsFromConfig() {
const sortByScreenSize = (next, prev) => {
const maxNext = Math.max(this.getMinSize(next) + 1 || 0, this.getMaxSize(next) || 0);
const maxPrev = Math.max(this.getMinSize(prev) + 1 || 0, this.getMaxSize(prev) || 0);
return maxNext < maxPrev ? -1 : 0;
};
return Object.keys(this.config).sort(sortByScreenSize);
}
/**
* Returns the _maximum_ size for the breakpoint, given by the
* `LayoutConfig.breakpoints` configuration. We will try to resolve the
* max size form the current breakpoint, but if this is not available, we
* resolve it form the next breakpoint
*/
getMaxSize(breakpoint) {
const breakpointConfig = this.config[breakpoint];
if (!breakpointConfig) {
return null;
}
// we treat numbers as the max number by default
if (typeof breakpointConfig === 'number') {
return breakpointConfig;
}
else if (breakpointConfig.max) {
return breakpointConfig.max;
}
else {
return null;
}
}
getMinSize(breakpoint) {
var _a;
return (_a = this.config[breakpoint]) === null || _a === void 0 ? void 0 : _a.min;
}
/**
* Returns a `BREAKPOINT` for the given window size.
*
* This method tries to match the closest breakpoint for the given
* window size. We'll fallback to the `largest` size in case the window
* is greater than the largest configurable breakpoint.
*
* The windowWidth should be smaller than the maximum size of any of the
* screen sizes defined in the `LayoutConfig.breakpoints`.
*/
getBreakpoint(windowWidth) {
var _a, _b;
return ((_a = this.breakpoints.find((br) => windowWidth < this.getSize(br))) !== null && _a !== void 0 ? _a : (_b = this.breakpoints) === null || _b === void 0 ? void 0 : _b[this.breakpoints.length - 1]);
}
/**
* Helper method to return the breakpoint configuration.
*/
get config() {
var _a;
return ((_a = this.layoutConfig) === null || _a === void 0 ? void 0 : _a.breakpoints) || {};
}
}
BreakpointService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: BreakpointService, deps: [{ token: i1.WindowRef }, { token: i2.LayoutConfig }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable });
BreakpointService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: BreakpointService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: BreakpointService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: function () { return [{ type: i1.WindowRef }, { type: i2.LayoutConfig }, { type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJlYWtwb2ludC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc3RvcmVmcm9udGxpYi9sYXlvdXQvYnJlYWtwb2ludC9icmVha3BvaW50LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDcEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRWhFLE9BQU8sRUFBYyxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7O0FBUTNEOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBSUgsTUFBTSxPQUFPLGlCQUFpQjtJQVU1QixZQUNZLE1BQWlCLEVBQ2pCLFlBQTBCLEVBQ0wsUUFBYTtRQUZsQyxXQUFNLEdBQU4sTUFBTSxDQUFXO1FBQ2pCLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQ0wsYUFBUSxHQUFSLFFBQVEsQ0FBSztRQVY5QyxnQkFBVyxHQUEyQixpQkFBaUIsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1lBQ3BFLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQ3RCLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBVSxLQUFLLENBQUMsTUFBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQ3JFLG9CQUFvQixFQUFFLENBQ3ZCO1lBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQU03QixDQUFDO0lBRUo7Ozs7O09BS0c7SUFDSCxJQUFJLFdBQVc7UUFDYixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUN0QixJQUFJ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QUNoRCxJQUFJLE9BQU8sZ0JBQWdCLEtBQUssUUFBUSxFQUFFO1lBQ3hDLE9BQU8sZ0JBQTBCLENBQUM7U0FDbkM7YUFBTSxJQUFJLGdCQUFnQixDQUFDLEdBQUcsRUFBRTtZQUMvQixPQUFPLGdCQUFnQixDQUFDLEdBQUcsQ0FBQztTQUM3QjthQUFNO1lBQ0wsT0FBTyxJQUFJLENBQUM7U0FDYjtJQUNILENBQUM7SUFFUyxVQUFVLENBQUMsVUFBc0I7O1FBQ3pDLE9BQU8sTUFBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBZ0IsMENBQUUsR0FBRyxDQUFDO0lBQ3RELENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDTyxhQUFhLENBQUMsV0FBbUI7O1FBQ3pDLE9BQU8sQ0FDTCxNQUFBLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxtQ0FDN0QsTUFBQSxJQUFJLENBQUMsV0FBVywwQ0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FDaEQsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILElBQWMsTUFBTTs7UUFDbEIsT0FBTyxDQUFBLE1BQUEsSUFBSSxDQUFDLFlBQVksMENBQUUsV0FBVyxLQUFJLEVBQUUsQ0FBQztJQUM5QyxDQUFDOzs4R0FwS1UsaUJBQWlCLHVFQWFsQixXQUFXO2tIQWJWLGlCQUFpQixjQUZoQixNQUFNOzJGQUVQLGlCQUFpQjtrQkFIN0IsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkI7OzBCQWNJLE1BQU07MkJBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlzUGxhdGZvcm1Ccm93c2VyIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSwgUExBVEZPUk1fSUQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFdpbmRvd1JlZiB9IGZyb20gJ0BzcGFydGFjdXMvY29yZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGlzdGluY3RVbnRpbENoYW5nZWQsIG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7XG4gIEJyZWFrUG9pbnQsXG4gIEJSRUFLUE9JTlQsXG4gIExheW91dEJyZWFrUG9pbnRzLFxuICBMYXlvdXRDb25maWcsXG59IGZyb20gJy4uL2NvbmZpZy9sYXlvdXQtY29uZmlnJztcblxuLyoqXG4gKiBUaGUgYEJyZWFrcG9pbnRTZXJ2aWNlYCByZXNvbHZlcyB0aGUgdmFyaW91cyBzY3JlZW4gc2l6ZXMgdGhhdCBhcmUgdXNlZCBpblxuICogdGhlIHN0b3JlZnJvbnQuIFRoZSBzY3JlZW4gc2l6ZXMgYXJlIGdsb2JhbGx5IGNvbmZpZ3VyYWJsZSBiYXNlZCBvbiB5b3VyXG4gKiBsYXlvdXQgcmVxdWlyZW1lbnRzLiBZb3UgY2FuIGFkanVzdCB0aGUgc2NyZWVuIHNpemVzIGJ5IHNldHRpbmcgdGhlIG1pbmltdW1cbiAqIGFuZC9vciBtYXhpbXVtIHNpemUgZm9yIGEgYnJlYWtwb2ludCwgYXMgd2VsbCBhcyBleHRlbmRpbmcgdGhlIGNvbmZpZ3VyYXRpb25cbiAqIHdpdGggbmV3IHNjcmVlbnMuXG4gKlxuICogQnkgZGVmYXVsdCwgdGhlIGBCcmVha3BvaW50U2VydmljZWAgaXMgYmFzZWQgb24gdGhlIGJyZWFrcG9pbnRzIGZyb20gdGhlXG4gKiBCb290c3RyYXAgdWkgbGlicmFyeTpcbiAqIC0gYHhzYDogPCA1NzZweFxuICogLSBgc21gOiA1NzZweCAtIDc2N3B4XG4gKiAtIGBtZGA6IDc2OHB4IC0gOTkxcHhcbiAqIC0gYGxnYDogOTkycHggLSAxMTk5cHhcbiAqIC0gYHhsYDogPj0gMTIwMHB4XG4gKi9cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxufSlcbmV4cG9ydCBjbGFzcyBCcmVha3BvaW50U2VydmljZSB7XG4gIHByaXZhdGUgX2JyZWFrcG9pbnRzOiBCUkVBS1BPSU5UW107XG5cbiAgYnJlYWtwb2ludCQ6IE9ic2VydmFibGU8QlJFQUtQT0lOVD4gPSBpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtKVxuICAgID8gdGhpcy53aW5SZWYucmVzaXplJC5waXBlKFxuICAgICAgICBtYXAoKGV2ZW50KSA9PiB0aGlzLmdldEJyZWFrcG9pbnQoKDxXaW5kb3c+ZXZlbnQudGFyZ2V0KS5pbm5lcldpZHRoKSksXG4gICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKClcbiAgICAgIClcbiAgICA6IG9mKHRoaXMuZmFsbGJhY2tCcmVha3BvaW50KTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgd2luUmVmOiBXaW5kb3dSZWYsXG4gICAgcHJvdGVjdGVkIGxheW91dENvbmZpZzogTGF5b3V0Q29uZmlnLFxuICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHByb3RlY3RlZCBwbGF0Zm9ybTogYW55XG4gICkge31cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYnJlYWtwb2ludHMgZm9yIHRoZSBzdG9yZWZyb250IGxheW91dC5cbiAgICpcbiAgICogVGhlIGJyZWFrcG9pbnRzIGFyZSBkcml2ZW4gYnkgdGhlIGBMYXlvdXRDb25maWcuYnJlYWtwb2ludHNgIGFuZCBzb3J0ZWQgYmFzZWQgb25cbiAgICogdGhlIGdpdmVuIHNjcmVlbiBzaXplLlxuICAgKi9cbiAgZ2V0IGJyZWFrcG9pbnRzKCk6IEJSRUFLUE9JTlRbXSB7XG4gICAgaWYgKCF0aGlzLl9icmVha3BvaW50cykge1xuICAgICAgdGhpcy5fYnJlYWtwb2ludHMgPSB0aGlzLnJlc29sdmVCcmVha3BvaW50c0Zyb21Db25maWcoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2JyZWFrcG9pbnRzO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIF9tYXhpbXVtXyBzaXplIGZvciB0aGUgYnJlYWtwb2ludCwgZ2l2ZW4gYnkgdGhlIGBMYXlvdXRDb25maWcuYnJlYWtwb2ludHNgXG4gICAqIGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICBnZXRTaXplKGJyZWFrcG9pbnQ6IEJSRUFLUE9JTlQpOiBudW1iZXIge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmdldE1heFNpemUoYnJlYWtwb2ludCkgPz9cbiAgICAgIC8vIGlmIHRoZXJlJ3Mgbm8gZGlyZWN0IG1heCB2YWx1ZSBvciBleHBsaWNpdCBtYXggdmFsdWVcbiAgICAgIC8vIHdlIG11c3QgZGVyaXZlIHRoZSBtYXggdmFsdWUgZnJvbSB0aGUgcHJldmlvdXMgbWluXG4gICAgICB0aGlzLmdldE1pblNpemUoXG4gICAgICAgIHRoaXMuYnJlYWtwb2ludHM/Llt0aGlzLmJyZWFrcG9pbnRzLmluZGV4T2YoYnJlYWtwb2ludCkgKyAxXVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgdGhlIGN1cnJlbnQgc2NyZWVuIHNpemUgaXMgc21hbGxlciB0aGFuIHRoZSBtYXhpbXVtIHNpemUgb2YgdGhlXG4gICAqIGdpdmVuIGJyZWFrcG9pbnQuXG4gICAqXG4gICAqIElmIHRoZSBnaXZlbiBicmVha3BvaW50IGlzIGBCUkVBS1BPSU5ULm1kYCwgdGhlIG1ldGhvZCByZXR1cm5zIGB0cnVlYCB3aGVuIHRoZVxuICAgKiB3aW5kb3cgaW5uZXJXaWR0aCBpcyBzbWFsbGVyIHRoYW4gdGhlIGNvbmZpZ3VyZWQgc2l6ZSBvZiBgQlJFQUtQT0lOVC5tZGAuXG4gICAqL1xuICBpc0Rvd24oYnJlYWtwb2ludDogQlJFQUtQT0lOVCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLmJyZWFrcG9pbnQkLnBpcGUoXG4gICAgICBtYXAoKGJyKSA9PlxuICAgICAgICB0aGlzLmJyZWFrcG9pbnRzXG4gICAgICAgICAgLnNsaWNlKDAsIHRoaXMuYnJlYWtwb2ludHMuaW5kZXhPZihicmVha3BvaW50KSArIDEpXG4gICAgICAgICAgLmluY2x1ZGVzKGJyKVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgdGhlIGN1cnJlbnQgc2NyZWVuIHNpemUgaXMgbGFyZ2VyIHRoYW4gdGhlIG1pbmltdW0gc2l6ZSBvZiB0aGVcbiAgICogZ2l2ZW4gYnJlYWtwb2ludC5cbiAgICpcbiAgICogSWYgdGhlIGdpdmVuIGJyZWFrcG9pbnQgaXMgYEJSRUFLUE9JTlQubWRgLCB0aGUgbWV0aG9kIHJldHVybnMgYHRydWVgIHdoZW4gdGhlXG4gICAqIHdpbmRvdyBpbm5lcldpZHRoIGlzIGxhcmdlciB0aGFuIHRoZSBjb25maWd1cmVkIHNpemUgb2YgYEJSRUFLUE9JTlQuc21gLlxuICAgKi9cbiAgaXNVcChicmVha3BvaW50OiBCUkVBS1BPSU5UKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuYnJlYWtwb2ludCQucGlwZShcbiAgICAgIG1hcCgoYnIpID0+XG4gICAgICAgIHRoaXMuYnJlYWtwb2ludHNcbiAgICAgICAgICAuc2xpY2UodGhpcy5icmVha3BvaW50cy5pbmRleE9mKGJyZWFrcG9pbnQpKVxuICAgICAgICAgIC5pbmNsdWRlcyhicilcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSBnaXZlbiBicmVha3BvaW50IGZpdHMgaW4gdGhlIGN1cnJlbnQgc2NyZWVuIHNpemUuXG4gICAqL1xuICBpc0VxdWFsKGJyZWFrcG9pbnQ6IEJSRUFLUE9JTlQpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdGhpcy5icmVha3BvaW50JC5waXBlKG1hcCgoYnIpID0+IGJyID09PSBicmVha3BvaW50KSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgZmFsbGJhY2sgYnJlYWtwb2ludCBpbiBjYXNlIG5vIGJyZWFrcG9pbnQgY2FuIGJlIHJlc29sdmVkLiBUaGlzIGlzXG4gICAqIHR5cGljYWxseSB0aGUgY2FzZSB3aGVuIHdlJ3JlIG9uIFNTUiB3aXRob3V0IGFuIGFjdHVhbCB3aW5kb3cuXG4gICAqXG4gICAqIFJldHVybnMgdGhlIHNtYWxsZXN0IHNjcmVlbiBzaXplIChtb2JpbGUgZmlyc3QpLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldCBmYWxsYmFja0JyZWFrcG9pbnQoKTogQlJFQUtQT0lOVCB7XG4gICAgcmV0dXJuIHRoaXMuYnJlYWtwb2ludHM/LlswXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyB0aGUgYnJlYWtwb2ludHMgYW5kIHNvcnRzIHRoZW0gYWNjb3JkaW5nIHRvIHRoZSBjb25maWd1cmVkIHNpemUuXG4gICAqXG4gICAqIFRoZSBzb3J0IG9yZGVyIGlzIGJ5IHNtYWxsIHRvIGxhcmdlIHNjcmVlbnMuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVzb2x2ZUJyZWFrcG9pbnRzRnJvbUNvbmZpZygpOiBCUkVBS1BPSU5UW10ge1xuICAgIGNvbnN0IHNvcnRCeVNjcmVlblNpemUgPSAobmV4dDogQlJFQUtQT0lOVCwgcHJldjogQlJFQUtQT0lOVCk6IG51bWJlciA9PiB7XG4gICAgICBjb25zdCBtYXhOZXh0ID0gTWF0aC5tYXgoXG4gICAgICAgIHRoaXMuZ2V0TWluU2l6ZShuZXh0KSArIDEgfHwgMCxcbiAgICAgICAgdGhpcy5nZXRNYXhTaXplKG5leHQpIHx8IDBcbiAgICAgICk7XG4gICAgICBjb25zdCBtYXhQcmV2ID0gTWF0aC5tYXgoXG4gICAgICAgIHRoaXMuZ2V0TWluU2l6ZShwcmV2KSArIDEgfHwgMCxcbiAgICAgICAgdGhpcy5nZXRNYXhTaXplKHByZXYpIHx8IDBcbiAgICAgICk7XG4gICAgICByZXR1cm4gbWF4TmV4dCA8IG1heFByZXYgPyAtMSA6IDA7XG4gICAgfTtcbiAgICByZXR1cm4gKE9iamVjdC5rZXlzKHRoaXMuY29uZmlnKSBhcyBCUkVBS1BPSU5UW10pLnNvcnQoc29ydEJ5U2NyZWVuU2l6ZSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgX21heGltdW1fIHNpemUgZm9yIHRoZSBicmVha3BvaW50LCBnaXZlbiBieSB0aGVcbiAgICogYExheW91dENvbmZpZy5icmVha3BvaW50c2AgY29uZmlndXJhdGlvbi4gV2Ugd2lsbCB0cnkgdG8gcmVzb2x2ZSB0aGVcbiAgICogbWF4IHNpemUgZm9ybSB0aGUgY3VycmVudCBicmVha3BvaW50LCBidXQgaWYgdGhpcyBpcyBub3QgYXZhaWxhYmxlLCB3ZVxuICAgKiByZXNvbHZlIGl0IGZvcm0gdGhlIG5leHQgYnJlYWtwb2ludFxuICAgKi9cbiAgcHJvdGVjdGVkIGdldE1heFNpemUoYnJlYWtwb2ludDogQlJFQUtQT0lOVCk6IG51bWJlciB7XG4gICAgY29uc3QgYnJlYWtwb2ludENvbmZpZyA9IHRoaXMuY29uZmlnW2JyZWFrcG9pbnRdO1xuXG4gICAgaWYgKCFicmVha3BvaW50Q29uZmlnKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyB3ZSB0cmVhdCBudW1iZXJzIGFzIHRoZSBtYXggbnVtYmVyIGJ5IGRlZmF1bHRcbiAgICBpZiAodHlwZW9mIGJyZWFrcG9pbnRDb25maWcgPT09ICdudW1iZXInKSB7XG4gICAgICByZXR1cm4gYnJlYWtwb2ludENvbmZpZyBhcyBudW1iZXI7XG4gICAgfSBlbHNlIGlmIChicmVha3BvaW50Q29uZmlnLm1heCkge1xuICAgICAgcmV0dXJuIGJyZWFrcG9pbnRDb25maWcubWF4O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0TWluU2l6ZShicmVha3BvaW50OiBCUkVBS1BPSU5UKTogbnVtYmVyIHtcbiAgICByZXR1cm4gKHRoaXMuY29uZmlnW2JyZWFrcG9pbnRdIGFzIEJyZWFrUG9pbnQpPy5taW47XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGBCUkVBS1BPSU5UYCBmb3IgdGhlIGdpdmVuIHdpbmRvdyBzaXplLlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCB0cmllcyB0byBtYXRjaCB0aGUgY2xvc2VzdCBicmVha3BvaW50IGZvciB0aGUgZ2l2ZW5cbiAgICogd2luZG93IHNpemUuIFdlJ2xsIGZhbGxiYWNrIHRvIHRoZSBgbGFyZ2VzdGAgc2l6ZSBpbiBjYXNlIHRoZSB3aW5kb3dcbiAgICogaXMgZ3JlYXRlciB0aGFuIHRoZSBsYXJnZXN0IGNvbmZpZ3VyYWJsZSBicmVha3BvaW50LlxuICAgKlxuICAgKiBUaGUgd2luZG93V2lkdGggc2hvdWxkIGJlIHNtYWxsZXIgdGhhbiB0aGUgbWF4aW11bSBzaXplIG9mIGFueSBvZiB0aGVcbiAgICogc2NyZWVuIHNpemVzIGRlZmluZWQgaW4gdGhlIGBMYXlvdXRDb25maWcuYnJlYWtwb2ludHNgLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldEJyZWFrcG9pbnQod2luZG93V2lkdGg6IG51bWJlcik6IEJSRUFLUE9JTlQge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmJyZWFrcG9pbnRzLmZpbmQoKGJyKSA9PiB3aW5kb3dXaWR0aCA8IHRoaXMuZ2V0U2l6ZShicikpID8/XG4gICAgICB0aGlzLmJyZWFrcG9pbnRzPy5bdGhpcy5icmVha3BvaW50cy5sZW5ndGggLSAxXVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIG1ldGhvZCB0byByZXR1cm4gdGhlIGJyZWFrcG9pbnQgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHByb3RlY3RlZCBnZXQgY29uZmlnKCk6IExheW91dEJyZWFrUG9pbnRzIHtcbiAgICByZXR1cm4gdGhpcy5sYXlvdXRDb25maWc/LmJyZWFrcG9pbnRzIHx8IHt9O1xuICB9XG59XG4iXX0=