UNPKG

@q149/angular-scrollspy

Version:

A simple lightweight library for Angular which automatically updates links to indicate the currently active section in the viewport

400 lines (391 loc) 30 kB
import { Directive, Input, HostBinding, ChangeDetectorRef, Injectable, ContentChildren, Component, NgModule } from '@angular/core'; import { __spread } from 'tslib'; import { InViewportModule } from '@q149/angular-inviewport'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * A directive used to add an `active` class to a nav item * when the section is in the viewport * * \@example * ```html * <a snScrollSpyItem for="foo" href="#section1">Section 1</a> * ``` * */ var ScrollSpyItemDirective = /** @class */ (function () { /** * Creates an instance of ScrollSpyItemDirective. * @memberof ScrollSpyItemDirective */ function ScrollSpyItemDirective(cdRef) { this.cdRef = cdRef; /** * True if the nav item is the active item in the `items` list * for `ScrollSpyDirective` instance * * \@memberof ScrollSpyItemDirective */ this.active = false; /** * If true means the section is in the viewport * * \@memberof ScrollSpyItemDirective */ this.inViewport = false; } Object.defineProperty(ScrollSpyItemDirective.prototype, "section", { get: /** * Id of section that links navigates to * * \@readonly * \@memberof ScrollSpyItemDirective * @return {?} */ function () { return this.href.replace('#', ''); }, enumerable: true, configurable: true }); /** * Manually trigger change detection * * \@memberof ScrollSpyItemDirective * @return {?} */ ScrollSpyItemDirective.prototype.detectChanges = /** * Manually trigger change detection * * \@memberof ScrollSpyItemDirective * @return {?} */ function () { this.cdRef.detectChanges(); }; ScrollSpyItemDirective.decorators = [ { type: Directive, args: [{ selector: '[snScrollSpyItem]' },] }, ]; /** @nocollapse */ ScrollSpyItemDirective.ctorParameters = function () { return [ { type: ChangeDetectorRef, }, ]; }; ScrollSpyItemDirective.propDecorators = { "active": [{ type: HostBinding, args: ['class.active',] },], "for": [{ type: Input },], "href": [{ type: Input },], }; return ScrollSpyItemDirective; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * Service that stores a list of `Spy`'s and the state * of their nav items `inViewport` and `active` state * */ var ScrollSpyService = /** @class */ (function () { function ScrollSpyService() { /** * List of `Spy`'s * * \@memberof ScrollSpyService */ this.spys = []; /** * Stores requests to add items to spy when spy hasn't been created * yet. Once spy has been added then request will be made again. * * \@memberof ScrollSpyService */ this.buffer = []; } /** * Add spy to list of `spys` * * \@memberof ScrollSpyService * @param {?} id * @param {?} items * @return {?} */ ScrollSpyService.prototype.addSpy = /** * Add spy to list of `spys` * * \@memberof ScrollSpyService * @param {?} id * @param {?} items * @return {?} */ function (id, items) { var _this = this; this.spys.push({ id: id, items: items }); var /** @type {?} */ buffer = this.buffer.filter(function (i) { return i.spyId === id; }); this.buffer = this.buffer.filter(function (i) { return i.spyId !== id; }); buffer.forEach(function (i) { return _this.setSpySectionStatus(i.sectionId, i.spyId, i.inViewport); }); }; /** * Remove spy from list of `spys` * * \@memberof ScrollSpyService * @param {?} id * @return {?} */ ScrollSpyService.prototype.removeSpy = /** * Remove spy from list of `spys` * * \@memberof ScrollSpyService * @param {?} id * @return {?} */ function (id) { var /** @type {?} */ i = this.spys.findIndex(function (s) { return s.id === id; }); this.spys.splice(i, 1); }; /** * Set the `inViewport` status for a spy item then sets the active * to true for the first item in the list that has `inViewport` * set to true * * \@memberof ScrollSpyService * @param {?} sectionId * @param {?} spyId * @param {?} inViewport * @return {?} */ ScrollSpyService.prototype.setSpySectionStatus = /** * Set the `inViewport` status for a spy item then sets the active * to true for the first item in the list that has `inViewport` * set to true * * \@memberof ScrollSpyService * @param {?} sectionId * @param {?} spyId * @param {?} inViewport * @return {?} */ function (sectionId, spyId, inViewport) { var /** @type {?} */ spy = this.spys.find(function (s) { return s.id === spyId; }); if (!spy) { this.buffer.push({ sectionId: sectionId, spyId: spyId, inViewport: inViewport }); return; } var /** @type {?} */ item = spy.items.find(function (i) { return i.section === sectionId; }); if (!item) { return; } item.inViewport = inViewport; var /** @type {?} */ firstInViewport = spy.items.filter(function (i) { return i.inViewport; })[0]; spy.items.forEach(function (i) { return (i.active = false); }); if (firstInViewport) { firstInViewport.active = true; firstInViewport.detectChanges(); } }; ScrollSpyService.decorators = [ { type: Injectable }, ]; return ScrollSpyService; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * Adds `active` class to navigation links when section is in the viewport. * Used in conjuction with `snScrollItem` directive which should be added * to anchor links in the nav * * \@example * ``` * <ul role="navigation" snScrollSpy id="foo"> * <li><a snScrollSpyItem for="foo" href="#section1">Section 1</a></li> * <li><a snScrollSpyItem for="foo" href="#section2">Section 2</a></li> * <li><a snScrollSpyItem for="foo" href="#section3">Section 3</a></li> * <li><a snScrollSpyItem for="foo" href="#section4">Section 4</a></li> * </ul> * ``` * */ var ScrollSpyDirective = /** @class */ (function () { /** * Creates an instance of ScrollSpyDirective. * @memberof ScrollSpyDirective */ function ScrollSpyDirective(scrollSpySvc) { this.scrollSpySvc = scrollSpySvc; } /** * Adds spy to list of spys in `ScrollSpyService` * * \@memberof ScrollSpyDirective * @return {?} */ ScrollSpyDirective.prototype.ngAfterViewInit = /** * Adds spy to list of spys in `ScrollSpyService` * * \@memberof ScrollSpyDirective * @return {?} */ function () { this.scrollSpySvc.addSpy(this.id, this.items); }; /** * Remove spy from list of spys when directive is destroyed * * \@memberof ScrollSpyDirective * @return {?} */ ScrollSpyDirective.prototype.ngOnDestroy = /** * Remove spy from list of spys when directive is destroyed * * \@memberof ScrollSpyDirective * @return {?} */ function () { this.scrollSpySvc.removeSpy(this.id); }; ScrollSpyDirective.decorators = [ { type: Directive, args: [{ selector: '[snScrollSpy]' },] }, ]; /** @nocollapse */ ScrollSpyDirective.ctorParameters = function () { return [ { type: ScrollSpyService, }, ]; }; ScrollSpyDirective.propDecorators = { "items": [{ type: ContentChildren, args: [ScrollSpyItemDirective,] },], "id": [{ type: Input },], }; return ScrollSpyDirective; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * A component to wrap section content within that will update the * `ScrollSpyService` when it's in view * * \@example * ```html * <sn-scroll-spy-section id="section1" for="foo"> * ... * </sn-scroll-spy-section> * ``` */ var ScrollSpySectionComponent = /** @class */ (function () { /** * Creates an instance of ScrollSpySectionComponent. * @memberof ScrollSpySectionComponent */ function ScrollSpySectionComponent(scrollSpySvc) { this.scrollSpySvc = scrollSpySvc; /** * Amount of time in ms to wait for other scroll events * before running event handler * * \@default 0 * \@memberof ScrollSpySectionComponent */ this.debounce = 0; } /** * Updates `ScrollSpy` section when element enters/leaves viewport * * \@memberof ScrollSpySectionComponent * @param {?} inViewport * @return {?} */ ScrollSpySectionComponent.prototype.onInViewportChange = /** * Updates `ScrollSpy` section when element enters/leaves viewport * * \@memberof ScrollSpySectionComponent * @param {?} inViewport * @return {?} */ function (inViewport) { this.scrollSpySvc.setSpySectionStatus(this.id, this.for, inViewport); }; ScrollSpySectionComponent.decorators = [ { type: Component, args: [{ selector: 'sn-scroll-spy-section', template: "<div\n class=\"sn-hidden\"\n snInViewport\n [offsetTop]=\"500\"\n (inViewportChange)=\"onInViewportChange($event)\"\n [debounce]=\"debounce\">\n</div>\n<ng-content></ng-content>\n", styles: [":host{display:block;position:relative}.sn-hidden{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0;z-index:-1}"] },] }, ]; /** @nocollapse */ ScrollSpySectionComponent.ctorParameters = function () { return [ { type: ScrollSpyService, }, ]; }; ScrollSpySectionComponent.propDecorators = { "id": [{ type: Input },], "for": [{ type: Input },], "debounce": [{ type: Input },], }; return ScrollSpySectionComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var /** @type {?} */ directives = [ScrollSpyDirective, ScrollSpyItemDirective]; var /** @type {?} */ components = [ScrollSpySectionComponent]; var /** @type {?} */ providers = [ScrollSpyService]; /** * A simple lightweight library for Angular which automatically * updates links to indicate the currently active section in the viewport * */ var ScrollSpyModule = /** @class */ (function () { function ScrollSpyModule() { } /** * Specify a static method for root module to ensure providers are * only provided once but allows the module to still be imported * into other modules without reproviding services. * * \@memberof ScrollSpyModule * @return {?} */ ScrollSpyModule.forRoot = /** * Specify a static method for root module to ensure providers are * only provided once but allows the module to still be imported * into other modules without reproviding services. * * \@memberof ScrollSpyModule * @return {?} */ function () { return { ngModule: ScrollSpyModule, providers: __spread(providers) }; }; ScrollSpyModule.decorators = [ { type: NgModule, args: [{ imports: [InViewportModule], declarations: __spread(directives, components), exports: __spread(directives, components) },] }, ]; return ScrollSpyModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ export { ScrollSpyDirective, ScrollSpyItemDirective, ScrollSpySectionComponent, ScrollSpyService, ScrollSpyModule }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicTE0OS1hbmd1bGFyLXNjcm9sbHNweS5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQHExNDkvYW5ndWxhci1zY3JvbGxzcHkvYXBwL3Njcm9sbC1zcHkvc2Nyb2xsLXNweS1pdGVtL3Njcm9sbC1zcHktaXRlbS5kaXJlY3RpdmUudHMiLCJuZzovL0BxMTQ5L2FuZ3VsYXItc2Nyb2xsc3B5L2FwcC9zY3JvbGwtc3B5L3Njcm9sbC1zcHktc2VydmljZS9zY3JvbGwtc3B5LnNlcnZpY2UudHMiLCJuZzovL0BxMTQ5L2FuZ3VsYXItc2Nyb2xsc3B5L2FwcC9zY3JvbGwtc3B5L3Njcm9sbC1zcHkvc2Nyb2xsLXNweS5kaXJlY3RpdmUudHMiLCJuZzovL0BxMTQ5L2FuZ3VsYXItc2Nyb2xsc3B5L2FwcC9zY3JvbGwtc3B5L3Njcm9sbC1zcHktc2VjdGlvbi9zY3JvbGwtc3B5LXNlY3Rpb24uY29tcG9uZW50LnRzIiwibmc6Ly9AcTE0OS9hbmd1bGFyLXNjcm9sbHNweS9hcHAvc2Nyb2xsLXNweS9zY3JvbGwtc3B5Lm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIERpcmVjdGl2ZSxcclxuICBJbnB1dCxcclxuICBIb3N0QmluZGluZyxcclxuICBDaGFuZ2VEZXRlY3RvclJlZlxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuLyoqXHJcbiAqIEEgZGlyZWN0aXZlIHVzZWQgdG8gYWRkIGFuIGBhY3RpdmVgIGNsYXNzIHRvIGEgbmF2IGl0ZW1cclxuICogd2hlbiB0aGUgc2VjdGlvbiBpcyBpbiB0aGUgdmlld3BvcnRcclxuICpcclxuICogQGV4YW1wbGVcclxuICogYGBgaHRtbFxyXG4gKiA8YSBzblNjcm9sbFNweUl0ZW0gZm9yPVwiZm9vXCIgaHJlZj1cIiNzZWN0aW9uMVwiPlNlY3Rpb24gMTwvYT5cclxuICogYGBgXHJcbiAqXHJcbiAqL1xyXG5ARGlyZWN0aXZlKHtcclxuICBzZWxlY3RvcjogJ1tzblNjcm9sbFNweUl0ZW1dJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZSB7XHJcbiAgLyoqXHJcbiAgICogVHJ1ZSBpZiB0aGUgbmF2IGl0ZW0gaXMgdGhlIGFjdGl2ZSBpdGVtIGluIHRoZSBgaXRlbXNgIGxpc3RcclxuICAgKiBmb3IgYFNjcm9sbFNweURpcmVjdGl2ZWAgaW5zdGFuY2VcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlXHJcbiAgICovXHJcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5hY3RpdmUnKSBwdWJsaWMgYWN0aXZlID0gZmFsc2U7XHJcbiAgLyoqXHJcbiAgICogSUQgb2YgYFNjcm9sbFNweURpcmVjdGl2ZWAgaW5zdGFuY2VcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlXHJcbiAgICovXHJcbiAgQElucHV0KCkgcHVibGljIGZvcjogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIEhhc2ggZm9yIHNlY3Rpb24gdG8gbGluayB0b1xyXG4gICAqXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweUl0ZW1EaXJlY3RpdmVcclxuICAgKi9cclxuICBASW5wdXQoKSBwdWJsaWMgaHJlZjogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIElmIHRydWUgbWVhbnMgdGhlIHNlY3Rpb24gaXMgaW4gdGhlIHZpZXdwb3J0XHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBpblZpZXdwb3J0ID0gZmFsc2U7XHJcbiAgLyoqXHJcbiAgICogSWQgb2Ygc2VjdGlvbiB0aGF0IGxpbmtzIG5hdmlnYXRlcyB0b1xyXG4gICAqXHJcbiAgICogQHJlYWRvbmx5XHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweUl0ZW1EaXJlY3RpdmVcclxuICAgKi9cclxuICBwdWJsaWMgZ2V0IHNlY3Rpb24oKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLmhyZWYucmVwbGFjZSgnIycsICcnKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlLlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjZFJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYpIHt9XHJcbiAgLyoqXHJcbiAgICogTWFudWFsbHkgdHJpZ2dlciBjaGFuZ2UgZGV0ZWN0aW9uXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBkZXRlY3RDaGFuZ2VzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5jZFJlZi5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IEluamVjdGFibGUsIFF1ZXJ5TGlzdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuaW1wb3J0IHsgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktaXRlbS9zY3JvbGwtc3B5LWl0ZW0uZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgU3B5IH0gZnJvbSAnLi4vc2hhcmVkL3NweS5tb2RlbCc7XHJcblxyXG4vKipcclxuICogU2VydmljZSB0aGF0IHN0b3JlcyBhIGxpc3Qgb2YgYFNweWAncyBhbmQgdGhlIHN0YXRlXHJcbiAqIG9mIHRoZWlyIG5hdiBpdGVtcyBgaW5WaWV3cG9ydGAgYW5kIGBhY3RpdmVgIHN0YXRlXHJcbiAqXHJcbiAqL1xyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBTY3JvbGxTcHlTZXJ2aWNlIHtcclxuICAvKipcclxuICAgKiBMaXN0IG9mIGBTcHlgJ3NcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHVibGljIHNweXM6IFNweVtdID0gW107XHJcbiAgLyoqXHJcbiAgICogU3RvcmVzIHJlcXVlc3RzIHRvIGFkZCBpdGVtcyB0byBzcHkgd2hlbiBzcHkgaGFzbid0IGJlZW4gY3JlYXRlZFxyXG4gICAqIHlldC4gT25jZSBzcHkgaGFzIGJlZW4gYWRkZWQgdGhlbiByZXF1ZXN0IHdpbGwgYmUgbWFkZSBhZ2Fpbi5cclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHVibGljIGJ1ZmZlcjogYW55W10gPSBbXTtcclxuICAvKipcclxuICAgKiBBZGQgc3B5IHRvIGxpc3Qgb2YgYHNweXNgXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5U2VydmljZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBhZGRTcHkoaWQ6IHN0cmluZywgaXRlbXM6IFF1ZXJ5TGlzdDxTY3JvbGxTcHlJdGVtRGlyZWN0aXZlPik6IHZvaWQge1xyXG4gICAgdGhpcy5zcHlzLnB1c2goeyBpZCwgaXRlbXMgfSk7XHJcbiAgICBjb25zdCBidWZmZXIgPSB0aGlzLmJ1ZmZlci5maWx0ZXIoaSA9PiBpLnNweUlkID09PSBpZCk7XHJcbiAgICB0aGlzLmJ1ZmZlciA9IHRoaXMuYnVmZmVyLmZpbHRlcihpID0+IGkuc3B5SWQgIT09IGlkKTtcclxuICAgIGJ1ZmZlci5mb3JFYWNoKGkgPT5cclxuICAgICAgdGhpcy5zZXRTcHlTZWN0aW9uU3RhdHVzKGkuc2VjdGlvbklkLCBpLnNweUlkLCBpLmluVmlld3BvcnQpXHJcbiAgICApO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBSZW1vdmUgc3B5IGZyb20gbGlzdCBvZiBgc3B5c2BcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHVibGljIHJlbW92ZVNweShpZDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBpID0gdGhpcy5zcHlzLmZpbmRJbmRleChzID0+IHMuaWQgPT09IGlkKTtcclxuICAgIHRoaXMuc3B5cy5zcGxpY2UoaSwgMSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFNldCB0aGUgYGluVmlld3BvcnRgIHN0YXR1cyBmb3IgYSBzcHkgaXRlbSB0aGVuIHNldHMgdGhlIGFjdGl2ZVxyXG4gICAqIHRvIHRydWUgZm9yIHRoZSBmaXJzdCBpdGVtIGluIHRoZSBsaXN0IHRoYXQgaGFzIGBpblZpZXdwb3J0YFxyXG4gICAqIHNldCB0byB0cnVlXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5U2VydmljZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBzZXRTcHlTZWN0aW9uU3RhdHVzKFxyXG4gICAgc2VjdGlvbklkOiBzdHJpbmcsXHJcbiAgICBzcHlJZDogc3RyaW5nLFxyXG4gICAgaW5WaWV3cG9ydDogYm9vbGVhblxyXG4gICk6IHZvaWQge1xyXG4gICAgY29uc3Qgc3B5ID0gdGhpcy5zcHlzLmZpbmQocyA9PiBzLmlkID09PSBzcHlJZCk7XHJcbiAgICBpZiAoIXNweSkge1xyXG4gICAgICB0aGlzLmJ1ZmZlci5wdXNoKHsgc2VjdGlvbklkLCBzcHlJZCwgaW5WaWV3cG9ydCB9KTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgY29uc3QgaXRlbSA9IHNweS5pdGVtcy5maW5kKGkgPT4gaS5zZWN0aW9uID09PSBzZWN0aW9uSWQpO1xyXG4gICAgaWYgKCFpdGVtKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBpdGVtLmluVmlld3BvcnQgPSBpblZpZXdwb3J0O1xyXG4gICAgY29uc3QgZmlyc3RJblZpZXdwb3J0ID0gc3B5Lml0ZW1zLmZpbHRlcihpID0+IGkuaW5WaWV3cG9ydClbMF07XHJcbiAgICBzcHkuaXRlbXMuZm9yRWFjaChpID0+IChpLmFjdGl2ZSA9IGZhbHNlKSk7XHJcblxyXG4gICAgaWYgKGZpcnN0SW5WaWV3cG9ydCkge1xyXG4gICAgICBmaXJzdEluVmlld3BvcnQuYWN0aXZlID0gdHJ1ZTtcclxuICAgICAgZmlyc3RJblZpZXdwb3J0LmRldGVjdENoYW5nZXMoKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHtcclxuICBEaXJlY3RpdmUsXHJcbiAgQ29udGVudENoaWxkcmVuLFxyXG4gIFF1ZXJ5TGlzdCxcclxuICBBZnRlclZpZXdJbml0LFxyXG4gIElucHV0LFxyXG4gIE9uRGVzdHJveVxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuaW1wb3J0IHsgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktaXRlbS9zY3JvbGwtc3B5LWl0ZW0uZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgU2Nyb2xsU3B5U2VydmljZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktc2VydmljZS9zY3JvbGwtc3B5LnNlcnZpY2UnO1xyXG5cclxuLyoqXHJcbiAqIEFkZHMgYGFjdGl2ZWAgY2xhc3MgdG8gbmF2aWdhdGlvbiBsaW5rcyB3aGVuIHNlY3Rpb24gaXMgaW4gdGhlIHZpZXdwb3J0LlxyXG4gKiBVc2VkIGluIGNvbmp1Y3Rpb24gd2l0aCBgc25TY3JvbGxJdGVtYCBkaXJlY3RpdmUgd2hpY2ggc2hvdWxkIGJlIGFkZGVkXHJcbiAqIHRvIGFuY2hvciBsaW5rcyBpbiB0aGUgbmF2XHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIGBgYFxyXG4gKiA8dWwgcm9sZT1cIm5hdmlnYXRpb25cIiBzblNjcm9sbFNweSBpZD1cImZvb1wiPlxyXG4gKiAgPGxpPjxhIHNuU2Nyb2xsU3B5SXRlbSBmb3I9XCJmb29cIiBocmVmPVwiI3NlY3Rpb24xXCI+U2VjdGlvbiAxPC9hPjwvbGk+XHJcbiAqICA8bGk+PGEgc25TY3JvbGxTcHlJdGVtIGZvcj1cImZvb1wiIGhyZWY9XCIjc2VjdGlvbjJcIj5TZWN0aW9uIDI8L2E+PC9saT5cclxuICogIDxsaT48YSBzblNjcm9sbFNweUl0ZW0gZm9yPVwiZm9vXCIgaHJlZj1cIiNzZWN0aW9uM1wiPlNlY3Rpb24gMzwvYT48L2xpPlxyXG4gKiAgPGxpPjxhIHNuU2Nyb2xsU3B5SXRlbSBmb3I9XCJmb29cIiBocmVmPVwiI3NlY3Rpb240XCI+U2VjdGlvbiA0PC9hPjwvbGk+XHJcbiAqIDwvdWw+XHJcbiAqIGBgYFxyXG4gKlxyXG4gKi9cclxuQERpcmVjdGl2ZSh7XHJcbiAgc2VsZWN0b3I6ICdbc25TY3JvbGxTcHldJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgU2Nyb2xsU3B5RGlyZWN0aXZlIGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcclxuICAvKipcclxuICAgKiBDb2xsZWN0aW9uIG9mIGBTY3JvbGxTcHlJdGVtYC4gVGhleSBhcmUgdGhlIGxpc3Qgb2ZcclxuICAgKiBuYXYgaXRlbXMuXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5RGlyZWN0aXZlXHJcbiAgICovXHJcbiAgQENvbnRlbnRDaGlsZHJlbihTY3JvbGxTcHlJdGVtRGlyZWN0aXZlKVxyXG4gIHB1YmxpYyBpdGVtczogUXVlcnlMaXN0PFNjcm9sbFNweUl0ZW1EaXJlY3RpdmU+O1xyXG4gIC8qKlxyXG4gICAqIElEIG9mIHNjcm9sbFNweSBpbnN0YW5jZVxyXG4gICAqXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweURpcmVjdGl2ZVxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyBpZDogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgU2Nyb2xsU3B5RGlyZWN0aXZlLlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlEaXJlY3RpdmVcclxuICAgKi9cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNjcm9sbFNweVN2YzogU2Nyb2xsU3B5U2VydmljZSkge31cclxuICAvKipcclxuICAgKiBBZGRzIHNweSB0byBsaXN0IG9mIHNweXMgaW4gYFNjcm9sbFNweVNlcnZpY2VgXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5RGlyZWN0aXZlXHJcbiAgICovXHJcbiAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuc2Nyb2xsU3B5U3ZjLmFkZFNweSh0aGlzLmlkLCB0aGlzLml0ZW1zKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogUmVtb3ZlIHNweSBmcm9tIGxpc3Qgb2Ygc3B5cyB3aGVuIGRpcmVjdGl2ZSBpcyBkZXN0cm95ZWRcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlEaXJlY3RpdmVcclxuICAgKi9cclxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLnNjcm9sbFNweVN2Yy5yZW1vdmVTcHkodGhpcy5pZCk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgU2Nyb2xsU3B5U2VydmljZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktc2VydmljZS9zY3JvbGwtc3B5LnNlcnZpY2UnO1xyXG5cclxuLyoqXHJcbiAqIEEgY29tcG9uZW50IHRvIHdyYXAgc2VjdGlvbiBjb250ZW50IHdpdGhpbiB0aGF0IHdpbGwgdXBkYXRlIHRoZVxyXG4gKiBgU2Nyb2xsU3B5U2VydmljZWAgd2hlbiBpdCdzIGluIHZpZXdcclxuICpcclxuICogQGV4YW1wbGVcclxuICogYGBgaHRtbFxyXG4gKiAgPHNuLXNjcm9sbC1zcHktc2VjdGlvbiBpZD1cInNlY3Rpb24xXCIgZm9yPVwiZm9vXCI+XHJcbiAqICAgIC4uLlxyXG4gKiAgPC9zbi1zY3JvbGwtc3B5LXNlY3Rpb24+XHJcbiAqIGBgYFxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdzbi1zY3JvbGwtc3B5LXNlY3Rpb24nLFxyXG4gIHRlbXBsYXRlOiBgPGRpdlxuICBjbGFzcz1cInNuLWhpZGRlblwiXG4gIHNuSW5WaWV3cG9ydFxuICBbb2Zmc2V0VG9wXT1cIjUwMFwiXG4gIChpblZpZXdwb3J0Q2hhbmdlKT1cIm9uSW5WaWV3cG9ydENoYW5nZSgkZXZlbnQpXCJcbiAgW2RlYm91bmNlXT1cImRlYm91bmNlXCI+XG48L2Rpdj5cbjxuZy1jb250ZW50PjwvbmctY29udGVudD5cbmAsXHJcbiAgc3R5bGVzOiBbYDpob3N0e2Rpc3BsYXk6YmxvY2s7cG9zaXRpb246cmVsYXRpdmV9LnNuLWhpZGRlbntib3R0b206MDtsZWZ0OjA7b3BhY2l0eTowO3Bvc2l0aW9uOmFic29sdXRlO3JpZ2h0OjA7dG9wOjA7ei1pbmRleDotMX1gXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgU2Nyb2xsU3B5U2VjdGlvbkNvbXBvbmVudCB7XHJcbiAgLyoqXHJcbiAgICogSWRlbnRpZmllcyB0aGUgc2VjdGlvblxyXG4gICAqXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweVNlY3Rpb25Db21wb25lbnRcclxuICAgKi9cclxuICBASW5wdXQoKSBwdWJsaWMgaWQ6IHN0cmluZztcclxuICAvKipcclxuICAgKiBTcGVjaWZpZXMgd2hpY2ggYFNjcm9sbFNweWAgaW5zdGFuY2UgdG8gdXBkYXRlXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5U2VjdGlvbkNvbXBvbmVudFxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyBmb3I6IHN0cmluZztcclxuICAvKipcclxuICAgKiBBbW91bnQgb2YgdGltZSBpbiBtcyB0byB3YWl0IGZvciBvdGhlciBzY3JvbGwgZXZlbnRzXHJcbiAgICogYmVmb3JlIHJ1bm5pbmcgZXZlbnQgaGFuZGxlclxyXG4gICAqXHJcbiAgICogQGRlZmF1bHQgMFxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZWN0aW9uQ29tcG9uZW50XHJcbiAgICovXHJcbiAgQElucHV0KCkgcHVibGljIGRlYm91bmNlID0gMDtcclxuICAvKipcclxuICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIFNjcm9sbFNweVNlY3Rpb25Db21wb25lbnQuXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweVNlY3Rpb25Db21wb25lbnRcclxuICAgKi9cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNjcm9sbFNweVN2YzogU2Nyb2xsU3B5U2VydmljZSkge31cclxuICAvKipcclxuICAgKiBVcGRhdGVzIGBTY3JvbGxTcHlgIHNlY3Rpb24gd2hlbiBlbGVtZW50IGVudGVycy9sZWF2ZXMgdmlld3BvcnRcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZWN0aW9uQ29tcG9uZW50XHJcbiAgICovXHJcbiAgcHVibGljIG9uSW5WaWV3cG9ydENoYW5nZShpblZpZXdwb3J0OiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLnNjcm9sbFNweVN2Yy5zZXRTcHlTZWN0aW9uU3RhdHVzKHRoaXMuaWQsIHRoaXMuZm9yLCBpblZpZXdwb3J0KTtcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgTmdNb2R1bGUsIE1vZHVsZVdpdGhQcm92aWRlcnMsIFByb3ZpZGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBJblZpZXdwb3J0TW9kdWxlIH0gZnJvbSAnQHExNDkvYW5ndWxhci1pbnZpZXdwb3J0JztcblxuaW1wb3J0IHsgU2Nyb2xsU3B5RGlyZWN0aXZlIH0gZnJvbSAnLi9zY3JvbGwtc3B5L3Njcm9sbC1zcHkuZGlyZWN0aXZlJztcbmltcG9ydCB7IFNjcm9sbFNweVNlY3Rpb25Db21wb25lbnQgfSBmcm9tICcuL3Njcm9sbC1zcHktc2VjdGlvbi9zY3JvbGwtc3B5LXNlY3Rpb24uY29tcG9uZW50JztcbmltcG9ydCB7IFNjcm9sbFNweUl0ZW1EaXJlY3RpdmUgfSBmcm9tICcuL3Njcm9sbC1zcHktaXRlbS9zY3JvbGwtc3B5LWl0ZW0uZGlyZWN0aXZlJztcbmltcG9ydCB7IFNjcm9sbFNweVNlcnZpY2UgfSBmcm9tICcuL3Njcm9sbC1zcHktc2VydmljZS9zY3JvbGwtc3B5LnNlcnZpY2UnO1xuXG5jb25zdCBkaXJlY3RpdmVzOiBhbnlbXSA9IFtTY3JvbGxTcHlEaXJlY3RpdmUsIFNjcm9sbFNweUl0ZW1EaXJlY3RpdmVdO1xuXG5jb25zdCBjb21wb25lbnRzOiBhbnlbXSA9IFtTY3JvbGxTcHlTZWN0aW9uQ29tcG9uZW50XTtcblxuY29uc3QgcHJvdmlkZXJzOiBQcm92aWRlcltdID0gW1Njcm9sbFNweVNlcnZpY2VdO1xuXG4vKipcbiAqIEEgc2ltcGxlIGxpZ2h0d2VpZ2h0IGxpYnJhcnkgZm9yIEFuZ3VsYXIgd2hpY2ggYXV0b21hdGljYWxseVxuICogdXBkYXRlcyBsaW5rcyB0byBpbmRpY2F0ZSB0aGUgY3VycmVudGx5IGFjdGl2ZSBzZWN0aW9uIGluIHRoZSB2aWV3cG9ydFxuICpcbiAqL1xuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW0luVmlld3BvcnRNb2R1bGVdLFxuICBkZWNsYXJhdGlvbnM6IFsuLi5kaXJlY3RpdmVzLCAuLi5jb21wb25lbnRzXSxcbiAgZXhwb3J0czogWy4uLmRpcmVjdGl2ZXMsIC4uLmNvbXBvbmVudHNdXG59KVxuZXhwb3J0IGNsYXNzIFNjcm9sbFNweU1vZHVsZSB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IGEgc3RhdGljIG1ldGhvZCBmb3Igcm9vdCBtb2R1bGUgdG8gZW5zdXJlIHByb3ZpZGVycyBhcmVcbiAgICogb25seSBwcm92aWRlZCBvbmNlIGJ1dCBhbGxvd3MgdGhlIG1vZHVsZSB0byBzdGlsbCBiZSBpbXBvcnRlZFxuICAgKiBpbnRvIG90aGVyIG1vZHVsZXMgd2l0aG91dCByZXByb3ZpZGluZyBzZXJ2aWNlcy5cbiAgICpcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweU1vZHVsZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmb3JSb290KCk6IE1vZHVsZVdpdGhQcm92aWRlcnMge1xuICAgIHJldHVybiB7XG4gICAgICBuZ01vZHVsZTogU2Nyb2xsU3B5TW9kdWxlLFxuICAgICAgcHJvdmlkZXJzOiBbLi4ucHJvdmlkZXJzXVxuICAgIH07XG4gIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUFBOzs7Ozs7Ozs7Ozs7Ozs7SUEyREUsZ0NBQW9C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