UNPKG

@catull/igniteui-angular

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

792 lines 72.8 kB
import { __decorate, __metadata } from "tslib"; import { CommonModule } from '@angular/common'; import { Component, ElementRef, EventEmitter, HostBinding, Input, NgModule, Output, Renderer2, ViewChild, ContentChild, AfterViewInit } from '@angular/core'; import { IgxProcessBarTextTemplateDirective, IgxProgressBarGradientDirective, } from './progressbar.common'; const ONE_PERCENT = 0.01; const MIN_VALUE = 0; export var IgxTextAlign; (function (IgxTextAlign) { IgxTextAlign["START"] = "start"; IgxTextAlign["CENTER"] = "center"; IgxTextAlign["END"] = "end"; })(IgxTextAlign || (IgxTextAlign = {})); export var IgxProgressType; (function (IgxProgressType) { IgxProgressType["DANGER"] = "danger"; IgxProgressType["INFO"] = "info"; IgxProgressType["WARNING"] = "warning"; IgxProgressType["SUCCESS"] = "success"; })(IgxProgressType || (IgxProgressType = {})); export class BaseProgress { constructor() { /** * @hidden */ this.requestAnimationId = undefined; /** * @hidden */ this._valueInPercent = MIN_VALUE; /** * @hidden */ this._max = 100; /** * @hidden */ this._value = MIN_VALUE; /** * @hidden */ this._animate = true; } /** *Returns the `IgxLinearProgressBarComponent`/`IgxCircularProgressBarComponent` value in percentage. *```typescript *@ViewChild("MyProgressBar") *public progressBar: IgxLinearProgressBarComponent; // IgxCircularProgressBarComponent *public valuePercent(event){ * let percentValue = this.progressBar.valueInPercent; * alert(percentValue); *} *``` */ get valueInPercent() { return this._valueInPercent; } /** *Sets the `IgxLinearProgressBarComponent`/`IgxCircularProgressBarComponent` value in percentage. *```typescript *@ViewChild("MyProgressBar") *public progressBar: IgxLinearProgressBarComponent; // IgxCircularProgressBarComponent * public setValue(event){ * this.progressBar.valueInPercent = 56; *} * //... *``` *```html *<button igxButton="fab" igxRipple="" (click)="setValue()">setValue</button> *``` */ set valueInPercent(value) { this._valueInPercent = value; } /** * @hidden */ runAnimation(val, step) { this.requestAnimationId = requestAnimationFrame(() => this.updateProgressSmoothly.call(this, val, step)); } /** * @hidden */ updateProgressSmoothly(val, step) { this._value += step; const passedValue = convertInPercentage(val, this._max); const progressValue = convertInPercentage(this._value, this._max); if (this.valueInPercent === passedValue) { this.updateProgress(val); cancelAnimationFrame(this.requestAnimationId); } else if (this.isInLimitRange(progressValue, passedValue, step)) { this.updateProgress(val); cancelAnimationFrame(this.requestAnimationId); } else { this.valueInPercent = progressValue; this.requestAnimationId = requestAnimationFrame(() => this.updateProgressSmoothly.call(this, val, step)); } } /** * @hidden */ updateProgressDirectly(val) { this._value = val; this.valueInPercent = convertInPercentage(this._value, this._max); } /** * @hidden */ directionFlow(currentValue, prevValue, step) { if (currentValue < prevValue) { return step; } return -step; } /** * @hidden */ isInLimitRange(val, comparator, step) { return this.isExceedingUpperLimit(val, comparator, step) || this.isExceedingLowerLimit(val, comparator, step); } /** * @hidden * * * @param val * @param comparator * @param step */ isExceedingUpperLimit(val, comparator, step) { return val > comparator && step > 0; } /** * @hidden * * @param val * @param comparator * @param step */ isExceedingLowerLimit(val, comparator, step) { return val < comparator && step < 0; } /** * @hidden * @param step */ updateProgress(val) { this._value = val; this.valueInPercent = convertInPercentage(this._value, this._max); } } let NEXT_LINEAR_ID = 0; let NEXT_CIRCULAR_ID = 0; let NEXT_GRADIENT_ID = 0; let IgxLinearProgressBarComponent = class IgxLinearProgressBarComponent extends BaseProgress { constructor() { super(); this.valueMin = 0; this.cssClass = 'igx-linear-bar'; /** *Set `IgxLinearProgressBarComponent` to have striped style. By default it is set to false. *```html *<igx-linear-bar [striped]="true" [max]="200" [value]="50"></igx-linear-bar> *``` */ this.striped = false; /** *Set `IgxLinearProgressBarComponent` to have indeterminate. By default it is set to false. *```html *<igx-linear-bar [indeterminate]="true"></igx-linear-bar> *``` */ this.indeterminate = false; /**An @Input property that sets the value of the `role` attribute. If not provided it will be automatically set to `progressbar`. * ```html *<igx-linear-bar role="progressbar"></igx-linear-bar> * ``` */ this.role = 'progressbar'; /**An @Input property that sets the value of `id` attribute. If not provided it will be automatically generated. * ```html *<igx-linear-bar [id]="'igx-linear-bar-55'" [striped]="true" [max]="200" [value]="50"></igx-linear-bar> * ``` */ this.id = `igx-linear-bar-${NEXT_LINEAR_ID++}`; /** *Set the position that defines where the text is aligned. Possible options - `IgxTextAlign.START` (default), `IgxTextAlign.CENTER`, `IgxTextAlign.END`. *```typescript *public positionCenter: IgxTextAlign; *public ngOnInit() { * this.positionCenter = IgxTextAlign.CENTER; *} * //... *``` * ```html *<igx-linear-bar type="warning" [text]="'Custom text'" [textAlign]="positionCenter" [striped]="true"></igx-linear-bar> *``` */ this.textAlign = IgxTextAlign.START; /** *Set the text to be visible. By default it is set to true. * ```html *<igx-linear-bar type="default" [textVisibility]="false"></igx-linear-bar> *``` */ this.textVisibility = true; /** *Set the position that defines if the text should be aligned above the progress line. By default is set to false. *```html *<igx-linear-bar type="danger" [textTop]="true"></igx-linear-bar> *``` */ this.textTop = false; /** *Set type of the `IgxLinearProgressBarComponent`. Possible options - `default`, `success`, `info`, `warning`, and `danger`. *```html *<igx-linear-bar [striped]="false" [max]="100" [value]="0" type="danger"></igx-linear-bar> *``` */ this.type = 'default'; /** *An event, which is triggered after a progress is changed. *```typescript *public progressChange(event) { * alert("Progress made!"); *} * //... *``` *```html *<igx-linear-bar (onProgressChanged)="progressChange($event)" type="success"> *``` */ this.onProgressChanged = new EventEmitter(); } /** *Animation on progress `IgxLinearProgressBarComponent`. By default it is set to true. *```html *<igx-linear-bar [animate]="false" [striped]="true" [max]="200" [value]="50"></igx-linear-bar> *``` */ set animate(animate) { this._animate = animate; } /** *Returns whether the `IgxLinearProgressBarComponent` has animation true/false. *```typescript *@ViewChild("MyProgressBar") *public progressBar: IgxLinearProgressBarComponent; *public animationStatus(event) { * let animationStatus = this.progressBar.animate; * alert(animationStatus); *} *``` */ get animate() { return this._animate; } /** *Set maximum value that can be passed. By default it is set to 100. *```html *<igx-linear-bar [striped]="false" [max]="200" [value]="0"></igx-linear-bar> *``` */ set max(maxNum) { this._max = maxNum; } /** *Returns the the maximum progress value of the `IgxLinearProgressBarComponent`. *```typescript *@ViewChild("MyProgressBar") *public progressBar: IgxLinearProgressBarComponent; *public maxValue(event) { * let max = this.progressBar.max; * alert(max); *} *``` */ get max() { return this._max; } /** *Returns the value which update the progress indicator of the `IgxLinearProgressBarComponent`. *```typescript *@ViewChild("MyProgressBar") *public progressBar: IgxLinearProgressBarComponent; *public stepValue(event) { * let step = this.progressBar.step; * alert(step); *} *``` */ get step() { if (this._step) { return this._step; } return this._max * ONE_PERCENT; } /** *Sets the value by which progress indicator is updated. By default it is 1% of the maximum value. *```html *<igx-linear-bar [striped]="false" [max]="200" [value]="0" [step]="1"></igx-linear-bar> *``` */ set step(val) { this._step = Number(val); } /** *Returns value that indicates the current `IgxLinearProgressBarComponent` position. *```typescript *@ViewChild("MyProgressBar") *public progressBar: IgxLinearProgressBarComponent; *public getValue(event) { * let value = this.progressBar.value; * alert(value); *} *``` */ get value() { return this._value; } /** *Set value that indicates the current `IgxLinearProgressBarComponent` position. *```html *<igx-linear-bar [striped]="false" [max]="200" [value]="50"></igx-linear-bar> *``` */ set value(val) { val = Number(val); if (this._value === val || this.indeterminate) { return; } const valueInRange = getValueInProperRange(val, this.max); if (isNaN(valueInRange)) { return; } const changedValues = { currentValue: valueInRange, previousValue: this._value }; const updateValue = super.directionFlow(this._value, val, this.step); if (this._animate && val >= this.step) { super.runAnimation(valueInRange, updateValue); } else { super.updateProgressDirectly(valueInRange); } this.onProgressChanged.emit(changedValues); } /** * @hidden */ get danger() { return this.type === IgxProgressType.DANGER; } /** * @hidden */ get info() { return this.type === IgxProgressType.INFO; } /** * @hidden */ get warning() { return this.type === IgxProgressType.WARNING; } /** * @hidden */ get success() { return this.type === IgxProgressType.SUCCESS; } }; __decorate([ Input(), __metadata("design:type", Boolean), __metadata("design:paramtypes", [Boolean]) ], IgxLinearProgressBarComponent.prototype, "animate", null); __decorate([ HostBinding('attr.aria-valuemax'), Input(), __metadata("design:type", Number), __metadata("design:paramtypes", [Number]) ], IgxLinearProgressBarComponent.prototype, "max", null); __decorate([ Input(), __metadata("design:type", Number), __metadata("design:paramtypes", [Number]) ], IgxLinearProgressBarComponent.prototype, "step", null); __decorate([ HostBinding('attr.aria-valuemin'), __metadata("design:type", Object) ], IgxLinearProgressBarComponent.prototype, "valueMin", void 0); __decorate([ HostBinding('class.igx-linear-bar'), __metadata("design:type", Object) ], IgxLinearProgressBarComponent.prototype, "cssClass", void 0); __decorate([ HostBinding('class.igx-linear-bar--striped'), Input(), __metadata("design:type", Object) ], IgxLinearProgressBarComponent.prototype, "striped", void 0); __decorate([ HostBinding('class.igx-linear-bar--indeterminate'), Input(), __metadata("design:type", Object) ], IgxLinearProgressBarComponent.prototype, "indeterminate", void 0); __decorate([ HostBinding('attr.role'), Input(), __metadata("design:type", Object) ], IgxLinearProgressBarComponent.prototype, "role", void 0); __decorate([ HostBinding('attr.id'), Input(), __metadata("design:type", Object) ], IgxLinearProgressBarComponent.prototype, "id", void 0); __decorate([ Input(), __metadata("design:type", String) ], IgxLinearProgressBarComponent.prototype, "textAlign", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxLinearProgressBarComponent.prototype, "textVisibility", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxLinearProgressBarComponent.prototype, "textTop", void 0); __decorate([ Input(), __metadata("design:type", String) ], IgxLinearProgressBarComponent.prototype, "text", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxLinearProgressBarComponent.prototype, "type", void 0); __decorate([ HostBinding('attr.aria-valuenow'), Input(), __metadata("design:type", Number), __metadata("design:paramtypes", [Object]) ], IgxLinearProgressBarComponent.prototype, "value", null); __decorate([ Output(), __metadata("design:type", Object) ], IgxLinearProgressBarComponent.prototype, "onProgressChanged", void 0); __decorate([ HostBinding('class.igx-linear-bar--danger'), __metadata("design:type", Object), __metadata("design:paramtypes", []) ], IgxLinearProgressBarComponent.prototype, "danger", null); __decorate([ HostBinding('class.igx-linear-bar--info'), __metadata("design:type", Object), __metadata("design:paramtypes", []) ], IgxLinearProgressBarComponent.prototype, "info", null); __decorate([ HostBinding('class.igx-linear-bar--warning'), __metadata("design:type", Object), __metadata("design:paramtypes", []) ], IgxLinearProgressBarComponent.prototype, "warning", null); __decorate([ HostBinding('class.igx-linear-bar--success'), __metadata("design:type", Object), __metadata("design:paramtypes", []) ], IgxLinearProgressBarComponent.prototype, "success", null); IgxLinearProgressBarComponent = __decorate([ Component({ selector: 'igx-linear-bar', template: "<div class=\"igx-linear-bar__base\">\n <div class=\"igx-linear-bar__indicator\"\n [style.width.%]=\"valueInPercent\"></div>\n</div>\n\n<span\n class=\"igx-linear-bar__value\"\n [ngClass]=\"{\n 'igx-linear-bar__value--start': textAlign === 'start',\n 'igx-linear-bar__value--center': textAlign === 'center',\n 'igx-linear-bar__value--end': textAlign === 'end',\n 'igx-linear-bar__value--top': textTop,\n 'igx-linear-bar__value--hidden': !textVisibility\n }\">\n {{text ? text : valueInPercent + '%'}}\n</span>\n" }), __metadata("design:paramtypes", []) ], IgxLinearProgressBarComponent); export { IgxLinearProgressBarComponent }; let IgxCircularProgressBarComponent = class IgxCircularProgressBarComponent extends BaseProgress { constructor(renderer) { super(); this.renderer = renderer; this.STROKE_OPACITY_DVIDER = 100; this.STROKE_OPACITY_ADDITION = .2; /** @hidden */ this.cssClass = 'igx-circular-bar'; /** *An event, which is triggered after a progress is changed. *```typescript *public progressChange(event) { * alert("Progress made!"); *} * //... *``` *```html *<igx-circular-bar [value]="currentValue" (onProgressChanged)="progressChange($event)"></igx-circular-bar> *``` */ this.onProgressChanged = new EventEmitter(); /** *An @Input property that sets the value of `id` attribute. If not provided it will be automatically generated. *```html *<igx-circular-bar [id]="'igx-circular-bar-55'" [value]="50"></igx-circular-bar> *``` */ this.id = `igx-circular-bar-${NEXT_CIRCULAR_ID++}`; /** * @hidden */ this.gradientId = `igx-circular-gradient-${NEXT_GRADIENT_ID++}`; /** *An @Input property that sets the value of the `indeterminate` attribute. If not provided it will be automatically set to false. *```html *<igx-circular-bar [indeterminate]="true"></igx-circular-bar> *``` */ this.indeterminate = false; /** *Sets the text visibility. By default it is set to true. *```html *<igx-circular-bar [textVisibility]="false"></igx-circular-bar> *``` */ this.textVisibility = true; this._circleRadius = 46; this._circumference = 2 * Math.PI * this._circleRadius; } /** * @hidden */ get context() { return { $implicit: { value: this.value, valueInPercent: this.valueInPercent, max: this.max } }; } /** *Animation on progress `IgxCircularProgressBarComponent`. By default it is set to true. *```html *<igx-circular-bar [animate]="false" [value]="50"></igx-circular-bar> *``` */ set animate(animate) { this._animate = animate; } /** *Returns whether the `IgxCircularProgressBarComponent` has animation true/false. *```typescript *@ViewChild("MyProgressBar") *public progressBar: IgxCircularProgressBarComponent; *public animationStatus(event) { * let animationStatus = this.progressBar.animate; * alert(animationStatus); *} *``` */ get animate() { return this._animate; } /** *Set maximum value that can be passed. By default it is set to 100. *```html *<igx-circular-bar [max]="200" [value]="0"></igx-circular-bar> *``` */ set max(maxNum) { this._max = maxNum; } /** *Returns the the maximum progress value of the `IgxCircularProgressBarComponent`. *```typescript *@ViewChild("MyProgressBar") *public progressBar: IgxCircularProgressBarComponent; *public maxValue(event) { * let max = this.progressBar.max; * alert(max); *} *``` *```html *<igx-circular-bar [max]="245" [animate]="false" [value]="currentValue"></igx-circular-bar> *``` */ get max() { return this._max; } /** *Returns the value which update the progress indicator of the `IgxCircularProgressBarComponent`. *```typescript *@ViewChild("MyProgressBar") *public progressBar: IgxCircularProgressBarComponent; *public stepValue(event) { * let step = this.progressBar.step; * alert(step); *} *``` */ get step() { if (this._step) { return this._step; } return this._max * ONE_PERCENT; } /** *Sets the value by which progress indicator is updated. By default it is 1% of the maximum value. *```html *<igx-circular-bar [striped]="false" [max]="200" [value]="0" [step]="1"></igx-circular-bar> *``` */ set step(val) { this._step = Number(val); } /** *Returns value that indicates the current `IgxCircularProgressBarComponent` position. *```typescript *@ViewChild("MyProgressBar") *public progressBar: IgxCircularProgressBarComponent; *public getValue(event) { * let value = this.progressBar.value; * alert(value); *} *``` *```html *<button igxButton="fab" igxRipple="" (click)="getValue()">Click</button> *``` */ get value() { return this._value; } /** *Set value that indicates the current `IgxCircularProgressBarComponent` position. *```html *<igx-circular-bar [value]="50"></igx-circular-bar> *``` */ set value(val) { val = Number(val); if (this._value === val || this.indeterminate) { return; } const valueInProperRange = getValueInProperRange(val, this.max); if (isNaN(valueInProperRange)) { return; } const changedValues = { currentValue: valueInProperRange, previousValue: this._value }; const updateValue = super.directionFlow(this._value, val, this.step); if (this.animate && val >= this.step) { super.runAnimation(valueInProperRange, updateValue); } else { this.updateProgressDirectly(valueInProperRange); } this.onProgressChanged.emit(changedValues); } ngAfterViewInit() { this.renderer.setStyle(this._svgCircle.nativeElement, 'stroke', `url(#${this.gradientId})`); } /** * @hidden */ updateProgressSmoothly(val, step) { // Set frames for the animation const FRAMES = [{ strokeDashoffset: this.getProgress(this._value), strokeOpacity: (this._value / this.STROKE_OPACITY_DVIDER) + this.STROKE_OPACITY_ADDITION }, { strokeDashoffset: this.getProgress(this.valueInPercent), strokeOpacity: (this.valueInPercent / this.STROKE_OPACITY_DVIDER) + this.STROKE_OPACITY_ADDITION }]; this._svgCircle.nativeElement.animate(FRAMES, { easing: 'ease-out', fill: 'forwards' }); super.updateProgressSmoothly(val, step); } /** * @hidden */ get textContent() { return this.text; } /** * @hidden */ updateProgressDirectly(val) { super.updateProgressDirectly(val); this.renderer.setStyle(this._svgCircle.nativeElement, 'stroke-dashoffset', this.getProgress(this.valueInPercent)); this.renderer.setStyle(this._svgCircle.nativeElement, 'stroke-opacity', (this.valueInPercent / this.STROKE_OPACITY_DVIDER) + this.STROKE_OPACITY_ADDITION); } getProgress(percentage) { // Reverse the sign here: '-' should become '+' in RTL mode return this._circumference - (percentage * this._circumference / 100); } }; IgxCircularProgressBarComponent.ctorParameters = () => [ { type: Renderer2 } ]; __decorate([ HostBinding('class.igx-circular-bar'), __metadata("design:type", Object) ], IgxCircularProgressBarComponent.prototype, "cssClass", void 0); __decorate([ Output(), __metadata("design:type", Object) ], IgxCircularProgressBarComponent.prototype, "onProgressChanged", void 0); __decorate([ HostBinding('attr.id'), Input(), __metadata("design:type", Object) ], IgxCircularProgressBarComponent.prototype, "id", void 0); __decorate([ HostBinding('class.igx-circular-bar--indeterminate'), Input(), __metadata("design:type", Object) ], IgxCircularProgressBarComponent.prototype, "indeterminate", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxCircularProgressBarComponent.prototype, "textVisibility", void 0); __decorate([ Input(), __metadata("design:type", String) ], IgxCircularProgressBarComponent.prototype, "text", void 0); __decorate([ ContentChild(IgxProcessBarTextTemplateDirective, { read: IgxProcessBarTextTemplateDirective }), __metadata("design:type", IgxProcessBarTextTemplateDirective) ], IgxCircularProgressBarComponent.prototype, "textTemplate", void 0); __decorate([ ContentChild(IgxProgressBarGradientDirective, { read: IgxProgressBarGradientDirective }), __metadata("design:type", IgxProgressBarGradientDirective) ], IgxCircularProgressBarComponent.prototype, "gradientTemplate", void 0); __decorate([ Input(), __metadata("design:type", Boolean), __metadata("design:paramtypes", [Boolean]) ], IgxCircularProgressBarComponent.prototype, "animate", null); __decorate([ Input(), __metadata("design:type", Number), __metadata("design:paramtypes", [Number]) ], IgxCircularProgressBarComponent.prototype, "max", null); __decorate([ Input(), __metadata("design:type", Number), __metadata("design:paramtypes", [Number]) ], IgxCircularProgressBarComponent.prototype, "step", null); __decorate([ Input(), __metadata("design:type", Number), __metadata("design:paramtypes", [Number]) ], IgxCircularProgressBarComponent.prototype, "value", null); __decorate([ ViewChild('circle', { static: true }), __metadata("design:type", ElementRef) ], IgxCircularProgressBarComponent.prototype, "_svgCircle", void 0); IgxCircularProgressBarComponent = __decorate([ Component({ selector: 'igx-circular-bar', template: "<svg #svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\"\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"xMidYMid meet\"\n role=\"progressbar\"\n aria-valuemin=\"0\"\n [attr.aria-valuemax]=\"max\"\n [attr.aria-valuenow]=\"value\">\n <svg:circle class=\"igx-circular-bar__inner\" cx=\"50\" cy=\"50\" r=\"46\" />\n <svg:circle #circle class=\"igx-circular-bar__outer\" cx=\"50\" cy=\"50\" r=\"46\" />\n <svg:text *ngIf=\"textVisibility\" text-anchor=\"middle\" x=\"50\" y=\"60\">\n <ng-container *ngTemplateOutlet=\"textTemplate ? textTemplate.template : defaultTextTemplate;\n context: context\">\n </ng-container>\n </svg:text>\n\n <svg:defs>\n <ng-container\n *ngTemplateOutlet=\"gradientTemplate ? gradientTemplate.template : defaultGradientTemplate;\n context: { $implicit: gradientId }\">\n </ng-container>\n </svg:defs>\n\n <ng-template #defaultTextTemplate>\n <svg:tspan class=\"igx-circular-bar__text\">\n {{textContent ? textContent: valueInPercent + '%'}}\n </svg:tspan>\n </ng-template>\n\n <ng-template #defaultGradientTemplate>\n <svg:linearGradient [id]=\"gradientId\" gradientTransform=\"rotate(90)\">\n <stop offset=\"0%\" class=\"igx-circular-bar__gradient-start\" />\n <stop offset=\"100%\" class=\"igx-circular-bar__gradient-end\" />\n </svg:linearGradient>\n </ng-template>\n</svg>\n\n" }), __metadata("design:paramtypes", [Renderer2]) ], IgxCircularProgressBarComponent); export { IgxCircularProgressBarComponent }; export function getValueInProperRange(value, max, min = 0) { return Math.max(Math.min(value, max), min); } export function convertInPercentage(value, max) { return Math.floor(100 * value / max); } /** * @hidden */ let IgxProgressBarModule = class IgxProgressBarModule { }; IgxProgressBarModule = __decorate([ NgModule({ declarations: [ IgxLinearProgressBarComponent, IgxCircularProgressBarComponent, IgxProcessBarTextTemplateDirective, IgxProgressBarGradientDirective, ], exports: [ IgxLinearProgressBarComponent, IgxCircularProgressBarComponent, IgxProcessBarTextTemplateDirective, IgxProgressBarGradientDirective, ], imports: [CommonModule] }) ], IgxProgressBarModule); export { IgxProgressBarModule }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZ3Jlc3NiYXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vaWduaXRldWktYW5ndWxhci8iLCJzb3VyY2VzIjpbImxpYi9wcm9ncmVzc2Jhci9wcm9ncmVzc2Jhci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQ0gsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osV0FBVyxFQUNYLEtBQUssRUFDTCxRQUFRLEVBQ1IsTUFBTSxFQUNOLFNBQVMsRUFDVCxTQUFTLEVBQ1QsWUFBWSxFQUNaLGFBQWEsRUFDaEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNILGtDQUFrQyxFQUNsQywrQkFBK0IsR0FDbEMsTUFBTSxzQkFBc0IsQ0FBQztBQUc5QixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUM7QUFDekIsTUFBTSxTQUFTLEdBQUcsQ0FBQyxDQUFDO0FBRXBCLE1BQU0sQ0FBTixJQUFZLFlBSVg7QUFKRCxXQUFZLFlBQVk7SUFDcEIsK0JBQWUsQ0FBQTtJQUNmLGlDQUFpQixDQUFBO0lBQ2pCLDJCQUFXLENBQUE7QUFDZixDQUFDLEVBSlcsWUFBWSxLQUFaLFlBQVksUUFJdkI7QUFFRCxNQUFNLENBQU4sSUFBWSxlQUtYO0FBTEQsV0FBWSxlQUFlO0lBQ3ZCLG9DQUFpQixDQUFBO0lBQ2pCLGdDQUFhLENBQUE7SUFDYixzQ0FBbUIsQ0FBQTtJQUNuQixzQ0FBbUIsQ0FBQTtBQUN2QixDQUFDLEVBTFcsZUFBZSxLQUFmLGVBQWUsUUFLMUI7QUFPRCxNQUFNLE9BQWdCLFlBQVk7SUFBbEM7UUFDSTs7V0FFRztRQUNLLHVCQUFrQixHQUFXLFNBQVMsQ0FBQztRQUUvQzs7V0FFRztRQUNPLG9CQUFlLEdBQUcsU0FBUyxDQUFDO1FBQ3RDOztXQUVHO1FBQ08sU0FBSSxHQUFHLEdBQUcsQ0FBQztRQUNyQjs7V0FFRztRQUNP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WUFDL0Isa0NBQWtDO1lBQ2xDLCtCQUErQjtTQUNsQztRQUNELE9BQU8sRUFBRSxDQUFDLFlBQVksQ0FBQztLQUMxQixDQUFDO0dBQ1csb0JBQW9CLENBQUk7U0FBeEIsb0JBQW9CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gICAgQ29tcG9uZW50LFxuICAgIEVsZW1lbnRSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIEhvc3RCaW5kaW5nLFxuICAgIElucHV0LFxuICAgIE5nTW9kdWxlLFxuICAgIE91dHB1dCxcbiAgICBSZW5kZXJlcjIsXG4gICAgVmlld0NoaWxkLFxuICAgIENvbnRlbnRDaGlsZCxcbiAgICBBZnRlclZpZXdJbml0XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgICBJZ3hQcm9jZXNzQmFyVGV4dFRlbXBsYXRlRGlyZWN0aXZlLFxuICAgIElneFByb2dyZXNzQmFyR3JhZGllbnREaXJlY3RpdmUsXG59IGZyb20gJy4vcHJvZ3Jlc3NiYXIuY29tbW9uJztcbmltcG9ydCB7IElCYXNlRXZlbnRBcmdzIH0gZnJvbSAnLi4vY29yZS91dGlscyc7XG5cbmNvbnN0IE9ORV9QRVJDRU5UID0gMC4wMTtcbmNvbnN0IE1JTl9WQUxVRSA9IDA7XG5cbmV4cG9ydCBlbnVtIElneFRleHRBbGlnbiB7XG4gICAgU1RBUlQgPSAnc3RhcnQnLFxuICAgIENFTlRFUiA9ICdjZW50ZXInLFxuICAgIEVORCA9ICdlbmQnXG59XG5cbmV4cG9ydCBlbnVtIElneFByb2dyZXNzVHlwZSB7XG4gICAgREFOR0VSID0gJ2RhbmdlcicsXG4gICAgSU5GTyA9ICdpbmZvJyxcbiAgICBXQVJOSU5HID0gJ3dhcm5pbmcnLFxuICAgIFNVQ0NFU1MgPSAnc3VjY2Vzcydcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJQ2hhbmdlUHJvZ3Jlc3NFdmVudEFyZ3MgZXh0ZW5kcyBJQmFzZUV2ZW50QXJncyB7XG4gICAgcHJldmlvdXNWYWx1ZTogbnVtYmVyO1xuICAgIGN1cnJlbnRWYWx1ZTogbnVtYmVyO1xufVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmFzZVByb2dyZXNzIHtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZXF1ZXN0QW5pbWF0aW9uSWQ6IG51bWJlciA9IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgX3ZhbHVlSW5QZXJjZW50ID0gTUlOX1ZBTFVFO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgX21heCA9IDEwMDtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIF92YWx1ZSA9IE1JTl9WQUxVRTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIF9hbmltYXRlID0gdHJ1ZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgX3N0ZXA7XG5cbiAgICAvKipcbiAgICAgKlJldHVybnMgdGhlIGBJZ3hMaW5lYXJQcm9ncmVzc0JhckNvbXBvbmVudGAvYElneENpcmN1bGFyUHJvZ3Jlc3NCYXJDb21wb25lbnRgIHZhbHVlIGluIHBlcmNlbnRhZ2UuXG4gICAgICpgYGB0eXBlc2NyaXB0XG4gICAgICpAVmlld0NoaWxkKFwiTXlQcm9ncmVzc0JhclwiKVxuICAgICAqcHVibGljIHByb2dyZXNzQmFyOiBJZ3hMaW5lYXJQcm9ncmVzc0JhckNvbXBvbmVudDsgLy8gSWd4Q2lyY3VsYXJQcm9ncmVzc0JhckNvbXBvbmVudFxuICAgICAqcHVibGljIHZhbHVlUGVyY2VudChldmVudCl7XG4gICAgICogICAgbGV0IHBlcmNlbnRWYWx1ZSA9IHRoaXMucHJvZ3Jlc3NCYXIudmFsdWVJblBlcmNlbnQ7XG4gICAgICogICAgYWxlcnQocGVyY2VudFZhbHVlKTtcbiAgICAgKn1cbiAgICAgKmBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgdmFsdWVJblBlcmNlbnQoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZhbHVlSW5QZXJjZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqU2V0cyB0aGUgYElneExpbmVhclByb2dyZXNzQmFyQ29tcG9uZW50YC9gSWd4Q2lyY3VsYXJQcm9ncmVzc0JhckNvbXBvbmVudGAgdmFsdWUgaW4gcGVyY2VudGFnZS5cbiAgICAgKmBgYHR5cGVzY3JpcHRcbiAgICAgKkBWaWV3Q2hpbGQoXCJNeVByb2dyZXNzQmFyXCIpXG4gICAgICpwdWJsaWMgcHJvZ3Jlc3NCYXI6IElneExpbmVhclByb2dyZXNzQmFyQ29tcG9uZW50OyAvLyBJZ3hDaXJjdWxhclByb2dyZXNzQmFyQ29tcG9uZW50XG4gICAgICogICAgcHVibGljIHNldFZhbHVlKGV2ZW50KXtcbiAgICAgKiAgICB0aGlzLnByb2dyZXNzQmFyLnZhbHVlSW5QZXJjZW50ID0gNTY7XG4gICAgICp9XG4gICAgICogLy8uLi5cbiAgICAgKmBgYFxuICAgICAqYGBgaHRtbFxuICAgICAqPGJ1dHRvbiBpZ3hCdXR0b249XCJmYWJcIiBpZ3hSaXBwbGU9XCJcIiAoY2xpY2spPVwic2V0VmFsdWUoKVwiPnNldFZhbHVlPC9idXR0b24+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0IHZhbHVlSW5QZXJjZW50KHZhbHVlOiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5fdmFsdWVJblBlcmNlbnQgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJ1bkFuaW1hdGlvbih2YWw6IG51bWJlciwgc3RlcDogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMucmVxdWVzdEFuaW1hdGlvbklkID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKFxuICAgICAgICAgICAgKCkgPT4gdGhpcy51cGRhdGVQcm9ncmVzc1Ntb290aGx5LmNhbGwodGhpcywgdmFsLCBzdGVwKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCB1cGRhdGVQcm9ncmVzc1Ntb290aGx5KHZhbDogbnVtYmVyLCBzdGVwOiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5fdmFsdWUgKz0gc3RlcDtcbiAgICAgICAgY29uc3QgcGFzc2VkVmFsdWUgPSBjb252ZXJ0SW5QZXJjZW50YWdlKHZhbCwgdGhpcy5fbWF4KTtcbiAgICAgICAgY29uc3QgcHJvZ3Jlc3NWYWx1ZSA9IGNvbnZlcnRJblBlcmNlbnRhZ2UodGhpcy5fdmFsdWUsIHRoaXMuX21heCk7XG4gICAgICAgIGlmICh0aGlzLnZhbHVlSW5QZXJjZW50ID09PSBwYXNzZWRWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVQcm9ncmVzcyh2YWwpO1xuICAgICAgICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5yZXF1ZXN0QW5pbWF0aW9uSWQpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaXNJbkxpbWl0UmFuZ2UocHJvZ3Jlc3NWYWx1ZSwgcGFzc2VkVmFsdWUsIHN0ZXApKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVByb2dyZXNzKHZhbCk7XG4gICAgICAgICAgICBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnJlcXVlc3RBbmltYXRpb25JZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlSW5QZXJjZW50ID0gcHJvZ3Jlc3NWYWx1ZTtcbiAgICAgICAgICAgIHRoaXMucmVxdWVzdEFuaW1hdGlvbklkID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHRoaXMudXBkYXRlUHJvZ3Jlc3NTbW9vdGhseS5jYWxsKHRoaXMsIHZhbCwgc3RlcCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCB1cGRhdGVQcm9ncmVzc0RpcmVjdGx5KHZhbDogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlID0gdmFsO1xuICAgICAgICB0aGlzLnZhbHVlSW5QZXJjZW50ID0gY29udmVydEluUGVyY2VudGFnZSh0aGlzLl92YWx1ZSwgdGhpcy5fbWF4KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGRpcmVjdGlvbkZsb3coY3VycmVudFZhbHVlOiBudW1iZXIsIHByZXZWYWx1ZTogbnVtYmVyLCBzdGVwOiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBpZiAoY3VycmVudFZhbHVlIDwgcHJldlZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RlcDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAtc3RlcDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJpdmF0ZSBpc0luTGltaXRSYW5nZSh2YWw6IG51bWJlciwgY29tcGFyYXRvcjogbnVtYmVyLCBzdGVwOiBudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNFeGNlZWRpbmdVcHBlckxpbWl0KHZhbCwgY29tcGFyYXRvciwgc3RlcCkgfHwgdGhpcy5pc0V4Y2VlZGluZ0xvd2VyTGltaXQodmFsLCBjb21wYXJhdG9yLCBzdGVwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICpcbiAgICAgKlxuICAgICAqIEBwYXJhbSB2YWxcbiAgICAgKiBAcGFyYW0gY29tcGFyYXRvclxuICAgICAqIEBwYXJhbSBzdGVwXG4gICAgICovXG4gICAgcHJpdmF0ZSBpc0V4Y2VlZGluZ1VwcGVyTGltaXQodmFsOiBudW1iZXIsIGNvbXBhcmF0b3I6IG51bWJlciwgc3RlcDogbnVtYmVyKSB7XG4gICAgICAgIHJldHVybiB2YWwgPiBjb21wYXJhdG9yICYmIHN0ZXAgPiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB2YWxcbiAgICAgKiBAcGFyYW0gY29tcGFyYXRvclxuICAgICAqIEBwYXJhbSBzdGVwXG4gICAgICovXG4gICAgcHJpdmF0ZSBpc0V4Y2VlZGluZ0xvd2VyTGltaXQodmFsOiBudW1iZXIsIGNvbXBhcmF0b3I6IG51bWJlciwgc3RlcDogbnVtYmVyKSB7XG4gICAgICAgIHJldHVybiB2YWwgPCBjb21wYXJhdG9yICYmIHN0ZXAgPCAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBAcGFyYW0gc3RlcFxuICAgICAqL1xuICAgIHByaXZhdGUgdXBkYXRlUHJvZ3Jlc3ModmFsOiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5fdmFsdWUgPSB2YWw7XG4gICAgICAgIHRoaXMudmFsdWVJblBlcmNlbnQgPSBjb252ZXJ0SW5QZXJjZW50YWdlKHRoaXMuX3ZhbHVlLCB0aGlzLl9tYXgpO1xuICAgIH1cbn1cbmxldCBORVhUX0xJTkVBUl9JRCA9IDA7XG5sZXQgTkVYVF9DSVJDVUxBUl9JRCA9IDA7XG5sZXQgTkVYVF9HUkFESUVOVF9JRCA9IDA7XG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2lneC1saW5lYXItYmFyJyxcbiAgICB0ZW1wbGF0ZVVybDogJ3RlbXBsYXRlcy9saW5lYXItYmFyLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBJZ3hMaW5lYXJQcm9ncmVzc0JhckNvbXBvbmVudCBleHRlbmRzIEJhc2VQcm9ncmVzcyB7XG5cbiAgICAvKipcbiAgICAgKkFuaW1hdGlvbiBvbiBwcm9ncmVzcyBgSWd4TGluZWFyUHJvZ3Jlc3NCYXJDb21wb25lbnRgLiBCeSBkZWZhdWx0IGl0IGlzIHNldCB0byB0cnVlLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1saW5lYXItYmFyIFthbmltYXRlXT1cImZhbHNlXCIgW3N0cmlwZWRdPVwidHJ1ZVwiIFttYXhdPVwiMjAwXCIgW3ZhbHVlXT1cIjUwXCI+PC9pZ3gtbGluZWFyLWJhcj5cbiAgICAgKmBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgc2V0IGFuaW1hdGUoYW5pbWF0ZTogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9hbmltYXRlID0gYW5pbWF0ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKlJldHVybnMgd2hldGhlciB0aGUgYElneExpbmVhclByb2dyZXNzQmFyQ29tcG9uZW50YCBoYXMgYW5pbWF0aW9uIHRydWUvZmFsc2UuXG4gICAgICpgYGB0eXBlc2NyaXB0XG4gICAgICpAVmlld0NoaWxkKFwiTXlQ