carbon-components-angular
Version:
Next generation components
457 lines • 36.2 kB
JavaScript
import { Component, Input, HostBinding, EventEmitter, Output, TemplateRef, HostListener } from "@angular/core";
import { NG_VALUE_ACCESSOR } from "@angular/forms";
import * as i0 from "@angular/core";
import * as i1 from "carbon-components-angular/i18n";
import * as i2 from "@angular/common";
import * as i3 from "carbon-components-angular/icon";
/**
* Used to emit changes performed on number input components.
*/
export class NumberChange {
}
/**
* Get started with importing the module:
*
* ```typescript
* import { NumberModule } from 'carbon-components-angular';
* ```
*
* [See demo](../../?path=/story/components-number--basic)
*/
export class NumberComponent {
/**
* Creates an instance of `Number`.
*/
constructor(i18n) {
this.i18n = i18n;
this.containerClass = true;
/**
* @deprecated since v5 - Use `cdsLayer` directive instead
* `light` or `dark` number input theme.
*/
this.theme = "dark";
/**
* Set to `true` for a disabled number input.
*/
this.disabled = false;
/**
* Set to `true` for a loading number component.
*/
this.skeleton = false;
/**
* Set to `true` for an invalid number component.
*/
this.invalid = false;
/**
* The unique id for the number component.
*/
this.id = `number-${NumberComponent.numberCount}`;
/**
* Sets the placeholder attribute on the `input` element.
*/
this.placeholder = "";
/**
* Number input field render size
*/
this.size = "md";
/**
* Sets the min attribute on the `input` element.
*/
this.min = null;
/**
* Sets the max attribute on the `input` element.
*/
this.max = null;
/**
* Sets the amount the number controls increment and decrement by.
*/
this.step = 1;
/**
* Set to `true` to show a warning (contents set by warningText)
*/
this.warn = false;
/**
* Emits event notifying other classes when a change in state occurs in the input.
*/
this.change = new EventEmitter();
this._value = 0;
this._decrementLabel = this.i18n.getOverridable("NUMBER.DECREMENT");
this._incrementLabel = this.i18n.getOverridable("NUMBER.INCREMENT");
/**
* Called when number input is blurred. Needed to properly implement `ControlValueAccessor`.
*/
this.onTouched = () => { };
/**
* Method set in `registerOnChange` to propagate changes back to the form.
*/
this.propagateChange = (_) => { };
NumberComponent.numberCount++;
}
/**
* Sets the value attribute on the `input` element.
*/
set value(v) {
if (v === "" || v === null) {
this._value = null;
return;
}
this._value = Number(v);
}
get value() {
return this._value;
}
set decrementLabel(value) {
this._decrementLabel.override(value);
}
get decrementLabel() {
return this._decrementLabel.value;
}
set incrementLabel(value) {
this._incrementLabel.override(value);
}
get incrementLabel() {
return this._incrementLabel.value;
}
/**
* This is the initial value set to the component
* @param value The input value.
*/
writeValue(value) {
this.value = value;
}
/**
* Sets a method in order to propagate changes back to the form.
*/
registerOnChange(fn) {
this.propagateChange = fn;
}
/**
* Registers a callback to be triggered when the control has been touched.
* @param fn Callback to be triggered when the number input is touched.
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
focusOut() {
this.onTouched();
}
/**
* Sets the disabled state through the model
*/
setDisabledState(isDisabled) {
this.disabled = isDisabled;
}
/**
* Adds `step` to the current `value`.
*/
onIncrement() {
if (this.max === null || this.value + this.step <= this.max) {
this.value += this.step;
this.value = parseFloat(this.value.toPrecision(this.precision));
this.emitChangeEvent();
}
}
/**
* Subtracts `step` to the current `value`.
*/
onDecrement() {
if (this.min === null || this.value - this.step >= this.min) {
this.value -= this.step;
this.value = parseFloat(this.value.toPrecision(this.precision));
this.emitChangeEvent();
}
}
getDecrementLabel() {
return this._decrementLabel.subject;
}
getIncrementLabel() {
return this._incrementLabel.subject;
}
/**
* Creates a class of `NumberChange` to emit the change in the `Number`.
*/
emitChangeEvent() {
let event = new NumberChange();
event.source = this;
event.value = this.value;
this.change.emit(event);
this.propagateChange(this.value);
}
onNumberInputChange(event) {
this.value = event.target.value;
this.emitChangeEvent();
}
isTemplate(value) {
return value instanceof TemplateRef;
}
}
/**
* Variable used for creating unique ids for number input components.
*/
NumberComponent.numberCount = 0;
NumberComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NumberComponent, deps: [{ token: i1.I18n }], target: i0.ɵɵFactoryTarget.Component });
NumberComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: NumberComponent, selector: "cds-number, ibm-number", inputs: { theme: "theme", disabled: "disabled", skeleton: "skeleton", invalid: "invalid", id: "id", placeholder: "placeholder", size: "size", required: "required", value: "value", min: "min", max: "max", label: "label", helperText: "helperText", invalidText: "invalidText", step: "step", precision: "precision", warn: "warn", warnText: "warnText", ariaLabel: "ariaLabel", decrementLabel: "decrementLabel", incrementLabel: "incrementLabel" }, outputs: { change: "change" }, host: { listeners: { "focusout": "focusOut()" }, properties: { "class.cds--form-item": "this.containerClass" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: NumberComponent,
multi: true
}
], ngImport: i0, template: `
<div
data-numberinput
[attr.data-invalid]="(invalid ? true : null)"
class="cds--number"
[ngClass]="{
'cds--number--light': theme === 'light',
'cds--number--nolabel': !label,
'cds--number--helpertext': helperText,
'cds--skeleton' : skeleton,
'cds--number--sm': size === 'sm',
'cds--number--md': size === 'md',
'cds--number--lg': size === 'lg'
}">
<label *ngIf="skeleton && label" class="cds--label cds--skeleton"></label>
<label
*ngIf="!skeleton && label"
[for]="id"
class="cds--label"
[ngClass]="{'cds--label--disabled': disabled}">
<ng-container *ngIf="!isTemplate(label)">{{label}}</ng-container>
<ng-template *ngIf="isTemplate(label)" [ngTemplateOutlet]="label"></ng-template>
</label>
<div
class="cds--number__input-wrapper"
[ngClass]="{
'cds--number__input-wrapper--warning': warn
}">
<input
type="number"
[id]="id"
[value]="value"
[attr.min]="min"
[attr.max]="max"
[attr.step]="step"
[disabled]="disabled"
[required]="required"
[attr.aria-label]="ariaLabel"
[attr.data-invalid]="invalid ? invalid : null"
[placeholder]="placeholder"
(change)="onNumberInputChange($event)"/>
<svg
*ngIf="!skeleton && invalid"
cdsIcon="warning--filled"
size="16"
class="cds--number__invalid">
</svg>
<svg
*ngIf="!skeleton && !invalid && warn"
cdsIcon="warning--alt--filled"
size="16"
class="cds--number__invalid cds--number__invalid--warning">
</svg>
<div *ngIf="!skeleton" class="cds--number__controls">
<button
class="cds--number__control-btn down-icon"
type="button"
[attr.disabled]="disabled ? true : null"
aria-live="polite"
aria-atomic="true"
[attr.aria-label]="getDecrementLabel() | async"
(click)="onDecrement()">
<svg cdsIcon="subtract" size="16"></svg>
</button>
<div class="cds--number__rule-divider"></div>
<button
class="cds--number__control-btn up-icon"
type="button"
[attr.disabled]="disabled ? true : null"
aria-live="polite"
aria-atomic="true"
[attr.aria-label]="getIncrementLabel() | async"
(click)="onIncrement()">
<svg cdsIcon="add" size="16"></svg>
</button>
<div class="cds--number__rule-divider"></div>
</div>
</div>
<div
*ngIf="helperText && !invalid && !warn"
class="cds--form__helper-text"
[ngClass]="{
'cds--form__helper-text--disabled': disabled
}">
<ng-container *ngIf="!isTemplate(helperText)">{{helperText}}</ng-container>
<ng-template *ngIf="isTemplate(helperText)" [ngTemplateOutlet]="helperText"></ng-template>
</div>
<div *ngIf="invalid" class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(invalidText)">{{invalidText}}</ng-container>
<ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template>
</div>
<div *ngIf="!invalid && warn" class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container>
<ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template>
</div>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NumberComponent, decorators: [{
type: Component,
args: [{
selector: "cds-number, ibm-number",
template: `
<div
data-numberinput
[attr.data-invalid]="(invalid ? true : null)"
class="cds--number"
[ngClass]="{
'cds--number--light': theme === 'light',
'cds--number--nolabel': !label,
'cds--number--helpertext': helperText,
'cds--skeleton' : skeleton,
'cds--number--sm': size === 'sm',
'cds--number--md': size === 'md',
'cds--number--lg': size === 'lg'
}">
<label *ngIf="skeleton && label" class="cds--label cds--skeleton"></label>
<label
*ngIf="!skeleton && label"
[for]="id"
class="cds--label"
[ngClass]="{'cds--label--disabled': disabled}">
<ng-container *ngIf="!isTemplate(label)">{{label}}</ng-container>
<ng-template *ngIf="isTemplate(label)" [ngTemplateOutlet]="label"></ng-template>
</label>
<div
class="cds--number__input-wrapper"
[ngClass]="{
'cds--number__input-wrapper--warning': warn
}">
<input
type="number"
[id]="id"
[value]="value"
[attr.min]="min"
[attr.max]="max"
[attr.step]="step"
[disabled]="disabled"
[required]="required"
[attr.aria-label]="ariaLabel"
[attr.data-invalid]="invalid ? invalid : null"
[placeholder]="placeholder"
(change)="onNumberInputChange($event)"/>
<svg
*ngIf="!skeleton && invalid"
cdsIcon="warning--filled"
size="16"
class="cds--number__invalid">
</svg>
<svg
*ngIf="!skeleton && !invalid && warn"
cdsIcon="warning--alt--filled"
size="16"
class="cds--number__invalid cds--number__invalid--warning">
</svg>
<div *ngIf="!skeleton" class="cds--number__controls">
<button
class="cds--number__control-btn down-icon"
type="button"
[attr.disabled]="disabled ? true : null"
aria-live="polite"
aria-atomic="true"
[attr.aria-label]="getDecrementLabel() | async"
(click)="onDecrement()">
<svg cdsIcon="subtract" size="16"></svg>
</button>
<div class="cds--number__rule-divider"></div>
<button
class="cds--number__control-btn up-icon"
type="button"
[attr.disabled]="disabled ? true : null"
aria-live="polite"
aria-atomic="true"
[attr.aria-label]="getIncrementLabel() | async"
(click)="onIncrement()">
<svg cdsIcon="add" size="16"></svg>
</button>
<div class="cds--number__rule-divider"></div>
</div>
</div>
<div
*ngIf="helperText && !invalid && !warn"
class="cds--form__helper-text"
[ngClass]="{
'cds--form__helper-text--disabled': disabled
}">
<ng-container *ngIf="!isTemplate(helperText)">{{helperText}}</ng-container>
<ng-template *ngIf="isTemplate(helperText)" [ngTemplateOutlet]="helperText"></ng-template>
</div>
<div *ngIf="invalid" class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(invalidText)">{{invalidText}}</ng-container>
<ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template>
</div>
<div *ngIf="!invalid && warn" class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container>
<ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template>
</div>
</div>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: NumberComponent,
multi: true
}
]
}]
}], ctorParameters: function () { return [{ type: i1.I18n }]; }, propDecorators: { containerClass: [{
type: HostBinding,
args: ["class.cds--form-item"]
}], theme: [{
type: Input
}], disabled: [{
type: Input
}], skeleton: [{
type: Input
}], invalid: [{
type: Input
}], id: [{
type: Input
}], placeholder: [{
type: Input
}], size: [{
type: Input
}], required: [{
type: Input
}], value: [{
type: Input
}], min: [{
type: Input
}], max: [{
type: Input
}], label: [{
type: Input
}], helperText: [{
type: Input
}], invalidText: [{
type: Input
}], step: [{
type: Input
}], precision: [{
type: Input
}], warn: [{
type: Input
}], warnText: [{
type: Input
}], ariaLabel: [{
type: Input
}], change: [{
type: Output
}], decrementLabel: [{
type: Input
}], incrementLabel: [{
type: Input
}], focusOut: [{
type: HostListener,
args: ["focusout"]
}] } });
export { NumberComponent as Number };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnVtYmVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9udW1iZXItaW5wdXQvbnVtYmVyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ04sU0FBUyxFQUNULEtBQUssRUFDTCxXQUFXLEVBQ1gsWUFBWSxFQUNaLE1BQU0sRUFDTixXQUFXLEVBQ1gsWUFBWSxFQUNaLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxpQkFBaUIsRUFBd0IsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7QUFLekU7O0dBRUc7QUFDSCxNQUFNLE9BQU8sWUFBWTtDQVN4QjtBQUVEOzs7Ozs7OztHQVFHO0FBNEdILE1BQU0sT0FBTyxlQUFlO0lBMkgzQjs7T0FFRztJQUNILFlBQXNCLElBQVU7UUFBVixTQUFJLEdBQUosSUFBSSxDQUFNO1FBeEhLLG1CQUFjLEdBQUcsSUFBSSxDQUFDO1FBRTNEOzs7V0FHRztRQUNNLFVBQUssR0FBcUIsTUFBTSxDQUFDO1FBQzFDOztXQUVHO1FBQ00sYUFBUSxHQUFHLEtBQUssQ0FBQztRQUMxQjs7V0FFRztRQUNNLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFDMUI7O1dBRUc7UUFDTSxZQUFPLEdBQUcsS0FBSyxDQUFDO1FBQ3pCOztXQUVHO1FBQ00sT0FBRSxHQUFHLFVBQVUsZUFBZSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3REOztXQUVHO1FBQ00sZ0JBQVcsR0FBRyxFQUFFLENBQUM7UUFDMUI7O1dBRUc7UUFDTSxTQUFJLEdBQXVCLElBQUksQ0FBQztRQW1CekM7O1dBRUc7UUFDTSxRQUFHLEdBQUcsSUFBSSxDQUFDO1FBQ3BCOztXQUVHO1FBQ00sUUFBRyxHQUFHLElBQUksQ0FBQztRQWFwQjs7V0FFRztRQUNNLFNBQUksR0FBRyxDQUFDLENBQUM7UUFLbEI7O1dBRUc7UUFDTSxTQUFJLEdBQUcsS0FBSyxDQUFDO1FBU3RCOztXQUVHO1FBQ08sV0FB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LEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdENvbXBvbmVudCxcblx0SW5wdXQsXG5cdEhvc3RCaW5kaW5nLFxuXHRFdmVudEVtaXR0ZXIsXG5cdE91dHB1dCxcblx0VGVtcGxhdGVSZWYsXG5cdEhvc3RMaXN0ZW5lclxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgTkdfVkFMVUVfQUNDRVNTT1IsIENvbnRyb2xWYWx1ZUFjY2Vzc29yIH0gZnJvbSBcIkBhbmd1bGFyL2Zvcm1zXCI7XG5cbmltcG9ydCB7IEkxOG4sIE92ZXJyaWRhYmxlIH0gZnJvbSBcImNhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXIvaTE4blwiO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gXCJyeGpzXCI7XG5cbi8qKlxuICogVXNlZCB0byBlbWl0IGNoYW5nZXMgcGVyZm9ybWVkIG9uIG51bWJlciBpbnB1dCBjb21wb25lbnRzLlxuICovXG5leHBvcnQgY2xhc3MgTnVtYmVyQ2hhbmdlIHtcblx0LyoqXG5cdCAqIENvbnRhaW5zIHRoZSBgTnVtYmVyYCB0aGF0IGhhcyBiZWVuIGNoYW5nZWQuXG5cdCAqL1xuXHRzb3VyY2U6IE51bWJlckNvbXBvbmVudDtcblx0LyoqXG5cdCAqIFRoZSB2YWx1ZSBvZiB0aGUgYE51bWJlcmAgZmllbGQgZW5jb21wYXNzZWQgaW4gdGhlIGBOdW1iZXJDaGFuZ2VgIGNsYXNzLlxuXHQgKi9cblx0dmFsdWU6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBHZXQgc3RhcnRlZCB3aXRoIGltcG9ydGluZyB0aGUgbW9kdWxlOlxuICpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IE51bWJlck1vZHVsZSB9IGZyb20gJ2NhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXInO1xuICogYGBgXG4gKlxuICogW1NlZSBkZW1vXSguLi8uLi8/cGF0aD0vc3RvcnkvY29tcG9uZW50cy1udW1iZXItLWJhc2ljKVxuICovXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6IFwiY2RzLW51bWJlciwgaWJtLW51bWJlclwiLFxuXHR0ZW1wbGF0ZTogYFxuXHRcdDxkaXZcblx0XHRcdGRhdGEtbnVtYmVyaW5wdXRcblx0XHRcdFthdHRyLmRhdGEtaW52YWxpZF09XCIoaW52YWxpZCA/IHRydWUgOiBudWxsKVwiXG5cdFx0XHRjbGFzcz1cImNkcy0tbnVtYmVyXCJcblx0XHRcdFtuZ0NsYXNzXT1cIntcblx0XHRcdFx0J2Nkcy0tbnVtYmVyLS1saWdodCc6IHRoZW1lID09PSAnbGlnaHQnLFxuXHRcdFx0XHQnY2RzLS1udW1iZXItLW5vbGFiZWwnOiAhbGFiZWwsXG5cdFx0XHRcdCdjZHMtLW51bWJlci0taGVscGVydGV4dCc6IGhlbHBlclRleHQsXG5cdFx0XHRcdCdjZHMtLXNrZWxldG9uJyA6IHNrZWxldG9uLFxuXHRcdFx0XHQnY2RzLS1udW1iZXItLXNtJzogc2l6ZSA9PT0gJ3NtJyxcblx0XHRcdFx0J2Nkcy0tbnVtYmVyLS1tZCc6IHNpemUgPT09ICdtZCcsXG5cdFx0XHRcdCdjZHMtLW51bWJlci0tbGcnOiBzaXplID09PSAnbGcnXG5cdFx0XHR9XCI+XG5cdFx0XHQ8bGFiZWwgKm5nSWY9XCJza2VsZXRvbiAmJiBsYWJlbFwiIGNsYXNzPVwiY2RzLS1sYWJlbCBjZHMtLXNrZWxldG9uXCI+PC9sYWJlbD5cblx0XHRcdDxsYWJlbFxuXHRcdFx0XHQqbmdJZj1cIiFza2VsZXRvbiAmJiBsYWJlbFwiXG5cdFx0XHRcdFtmb3JdPVwiaWRcIlxuXHRcdFx0XHRjbGFzcz1cImNkcy0tbGFiZWxcIlxuXHRcdFx0XHRbbmdDbGFzc109XCJ7J2Nkcy0tbGFiZWwtLWRpc2FibGVkJzogZGlzYWJsZWR9XCI+XG5cdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNUZW1wbGF0ZShsYWJlbClcIj57e2xhYmVsfX08L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0PG5nLXRlbXBsYXRlICpuZ0lmPVwiaXNUZW1wbGF0ZShsYWJlbClcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJsYWJlbFwiPjwvbmctdGVtcGxhdGU+XG5cdFx0XHQ8L2xhYmVsPlxuXHRcdFx0PGRpdlxuXHRcdFx0XHRjbGFzcz1cImNkcy0tbnVtYmVyX19pbnB1dC13cmFwcGVyXCJcblx0XHRcdFx0W25nQ2xhc3NdPVwie1xuXHRcdFx0XHRcdCdjZHMtLW51bWJlcl9faW5wdXQtd3JhcHBlci0td2FybmluZyc6IHdhcm5cblx0XHRcdFx0fVwiPlxuXHRcdFx0XHQ8aW5wdXRcblx0XHRcdFx0XHR0eXBlPVwibnVtYmVyXCJcblx0XHRcdFx0XHRbaWRdPVwiaWRcIlxuXHRcdFx0XHRcdFt2YWx1ZV09XCJ2YWx1ZVwiXG5cdFx0XHRcdFx0W2F0dHIubWluXT1cIm1pblwiXG5cdFx0XHRcdFx0W2F0dHIubWF4XT1cIm1heFwiXG5cdFx0XHRcdFx0W2F0dHIuc3RlcF09XCJzdGVwXCJcblx0XHRcdFx0XHRbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuXHRcdFx0XHRcdFtyZXF1aXJlZF09XCJyZXF1aXJlZFwiXG5cdFx0XHRcdFx0W2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWxcIlxuXHRcdFx0XHRcdFthdHRyLmRhdGEtaW52YWxpZF09XCJpbnZhbGlkID8gaW52YWxpZCA6IG51bGxcIlxuXHRcdFx0XHRcdFtwbGFjZWhvbGRlcl09XCJwbGFjZWhvbGRlclwiXG5cdFx0XHRcdFx0KGNoYW5nZSk9XCJvbk51bWJlcklucHV0Q2hhbmdlKCRldmVudClcIi8+XG5cdFx0XHRcdDxzdmdcblx0XHRcdFx0XHQqbmdJZj1cIiFza2VsZXRvbiAmJiBpbnZhbGlkXCJcblx0XHRcdFx0XHRjZHNJY29uPVwid2FybmluZy0tZmlsbGVkXCJcblx0XHRcdFx0XHRzaXplPVwiMTZcIlxuXHRcdFx0XHRcdGNsYXNzPVwiY2RzLS1udW1iZXJfX2ludmFsaWRcIj5cblx0XHRcdFx0PC9zdmc+XG5cdFx0XHRcdDxzdmdcblx0XHRcdFx0XHQqbmdJZj1cIiFza2VsZXRvbiAmJiAhaW52YWxpZCAmJiB3YXJuXCJcblx0XHRcdFx0XHRjZHNJY29uPVwid2FybmluZy0tYWx0LS1maWxsZWRcIlxuXHRcdFx0XHRcdHNpemU9XCIxNlwiXG5cdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLW51bWJlcl9faW52YWxpZCBjZHMtLW51bWJlcl9faW52YWxpZC0td2FybmluZ1wiPlxuXHRcdFx0XHQ8L3N2Zz5cblx0XHRcdFx0PGRpdiAqbmdJZj1cIiFza2VsZXRvblwiIGNsYXNzPVwiY2RzLS1udW1iZXJfX2NvbnRyb2xzXCI+XG5cdFx0XHRcdFx0PGJ1dHRvblxuXHRcdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLW51bWJlcl9fY29udHJvbC1idG4gZG93bi1pY29uXCJcblx0XHRcdFx0XHRcdHR5cGU9XCJidXR0b25cIlxuXHRcdFx0XHRcdFx0W2F0dHIuZGlzYWJsZWRdPVwiZGlzYWJsZWQgPyB0cnVlIDogbnVsbFwiXG5cdFx0XHRcdFx0XHRhcmlhLWxpdmU9XCJwb2xpdGVcIlxuXHRcdFx0XHRcdFx0YXJpYS1hdG9taWM9XCJ0cnVlXCJcblx0XHRcdFx0XHRcdFthdHRyLmFyaWEtbGFiZWxdPVwiZ2V0RGVjcmVtZW50TGFiZWwoKSB8IGFzeW5jXCJcblx0XHRcdFx0XHRcdChjbGljayk9XCJvbkRlY3JlbWVudCgpXCI+XG5cdFx0XHRcdFx0XHQ8c3ZnIGNkc0ljb249XCJzdWJ0cmFjdFwiIHNpemU9XCIxNlwiPjwvc3ZnPlxuXHRcdFx0XHRcdDwvYnV0dG9uPlxuXHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJjZHMtLW51bWJlcl9fcnVsZS1kaXZpZGVyXCI+PC9kaXY+XG5cdFx0XHRcdFx0PGJ1dHRvblxuXHRcdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLW51bWJlcl9fY29udHJvbC1idG4gdXAtaWNvblwiXG5cdFx0XHRcdFx0XHR0eXBlPVwiYnV0dG9uXCJcblx0XHRcdFx0XHRcdFthdHRyLmRpc2FibGVkXT1cImRpc2FibGVkID8gdHJ1ZSA6IG51bGxcIlxuXHRcdFx0XHRcdFx0YXJpYS1saXZlPVwicG9saXRlXCJcblx0XHRcdFx0XHRcdGFyaWEtYXRvbWljPVwidHJ1ZVwiXG5cdFx0XHRcdFx0XHRbYXR0ci5hcmlhLWxhYmVsXT1cImdldEluY3JlbWVudExhYmVsKCkgfCBhc3luY1wiXG5cdFx0XHRcdFx0XHQoY2xpY2spPVwib25JbmNyZW1lbnQoKVwiPlxuXHRcdFx0XHRcdFx0PHN2ZyBjZHNJY29uPVwiYWRkXCIgc2l6ZT1cIjE2XCI+PC9zdmc+XG5cdFx0XHRcdFx0PC9idXR0b24+XG5cdFx0XHRcdFx0PGRpdiBjbGFzcz1cImNkcy0tbnVtYmVyX19ydWxlLWRpdmlkZXJcIj48L2Rpdj5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHQ8L2Rpdj5cblx0XHRcdDxkaXZcblx0XHRcdFx0Km5nSWY9XCJoZWxwZXJUZXh0ICYmICFpbnZhbGlkICYmICF3YXJuXCJcblx0XHRcdFx0Y2xhc3M9XCJjZHMtLWZvcm1fX2hlbHBlci10ZXh0XCJcblx0XHRcdFx0W25nQ2xhc3NdPVwie1xuXHRcdFx0XHRcdCdjZHMtLWZvcm1fX2hlbHBlci10ZXh0LS1kaXNhYmxlZCc6IGRpc2FibGVkXG5cdFx0XHRcdH1cIj5cblx0XHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpc1RlbXBsYXRlKGhlbHBlclRleHQpXCI+e3toZWxwZXJUZXh0fX08L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0PG5nLXRlbXBsYXRlICpuZ0lmPVwiaXNUZW1wbGF0ZShoZWxwZXJUZXh0KVwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImhlbHBlclRleHRcIj48L25nLXRlbXBsYXRlPlxuXHRcdFx0PC9kaXY+XG5cdFx0XHQ8ZGl2ICpuZ0lmPVwiaW52YWxpZFwiIGNsYXNzPVwiY2RzLS1mb3JtLXJlcXVpcmVtZW50XCI+XG5cdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNUZW1wbGF0ZShpbnZhbGlkVGV4dClcIj57e2ludmFsaWRUZXh0fX08L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0PG5nLXRlbXBsYXRlICpuZ0lmPVwiaXNUZW1wbGF0ZShpbnZhbGlkVGV4dClcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJpbnZhbGlkVGV4dFwiPjwvbmctdGVtcGxhdGU+XG5cdFx0XHQ8L2Rpdj5cblx0XHRcdDxkaXYgKm5nSWY9XCIhaW52YWxpZCAmJiB3YXJuXCIgY2xhc3M9XCJjZHMtLWZvcm0tcmVxdWlyZW1lbnRcIj5cblx0XHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpc1RlbXBsYXRlKHdhcm5UZXh0KVwiPnt7d2FyblRleHR9fTwvbmctY29udGFpbmVyPlxuXHRcdFx0XHQ8bmctdGVtcGxhdGUgKm5nSWY9XCJpc1RlbXBsYXRlKHdhcm5UZXh0KVwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIndhcm5UZXh0XCI+PC9uZy10ZW1wbGF0ZT5cblx0XHRcdDwvZGl2PlxuXHRcdDwvZGl2PlxuXHRgLFxuXHRwcm92aWRlcnM6IFtcblx0XHR7XG5cdFx0XHRwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcblx0XHRcdHVzZUV4aXN0aW5nOiBOdW1iZXJDb21wb25lbnQsXG5cdFx0XHRtdWx0aTogdHJ1ZVxuXHRcdH1cblx0XVxufSlcbmV4cG9ydCBjbGFzcyBOdW1iZXJDb21wb25lbnQgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciB7XG5cdC8qKlxuXHQgKiBWYXJpYWJsZSB1c2VkIGZvciBjcmVhdGluZyB1bmlxdWUgaWRzIGZvciBudW1iZXIgaW5wdXQgY29tcG9uZW50cy5cblx0ICovXG5cdHN0YXRpYyBudW1iZXJDb3VudCA9IDA7XG5cblx0QEhvc3RCaW5kaW5nKFwiY2xhc3MuY2RzLS1mb3JtLWl0ZW1cIikgY29udGFpbmVyQ2xhc3MgPSB0cnVlO1xuXG5cdC8qKlxuXHQgKiBAZGVwcmVjYXRlZCBzaW5jZSB2NSAtIFVzZSBgY2RzTGF5ZXJgIGRpcmVjdGl2ZSBpbnN0ZWFkXG5cdCAqIGBsaWdodGAgb3IgYGRhcmtgIG51bWJlciBpbnB1dCB0aGVtZS5cblx0ICovXG5cdEBJbnB1dCgpIHRoZW1lOiBcImxpZ2h0XCIgfCBcImRhcmtcIiA9IFwiZGFya1wiO1xuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCBmb3IgYSBkaXNhYmxlZCBudW1iZXIgaW5wdXQuXG5cdCAqL1xuXHRASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCBmb3IgYSBsb2FkaW5nIG51bWJlciBjb21wb25lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSBza2VsZXRvbiA9IGZhbHNlO1xuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCBmb3IgYW4gaW52YWxpZCBudW1iZXIgY29tcG9uZW50LlxuXHQgKi9cblx0QElucHV0KCkgaW52YWxpZCA9IGZhbHNlO1xuXHQvKipcblx0ICogVGhlIHVuaXF1ZSBpZCBmb3IgdGhlIG51bWJlciBjb21wb25lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSBpZCA9IGBudW1iZXItJHtOdW1iZXJDb21wb25lbnQubnVtYmVyQ291bnR9YDtcblx0LyoqXG5cdCAqIFNldHMgdGhlIHBsYWNlaG9sZGVyIGF0dHJpYnV0ZSBvbiB0aGUgYGlucHV0YCBlbGVtZW50LlxuXHQgKi9cblx0QElucHV0KCkgcGxhY2Vob2xkZXIgPSBcIlwiO1xuXHQvKipcblx0ICogTnVtYmVyIGlucHV0IGZpZWxkIHJlbmRlciBzaXplXG5cdCAqL1xuXHRASW5wdXQoKSBzaXplOiBcInNtXCIgfCBcIm1kXCIgfCBcImxnXCIgPSBcIm1kXCI7XG5cdC8qKlxuXHQgKiBSZWZsZWN0cyB0aGUgcmVxdWlyZWQgYXR0cmlidXRlIG9mIHRoZSBgaW5wdXRgIGVsZW1lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSByZXF1aXJlZDogYm9vbGVhbjtcblx0LyoqXG5cdCAqIFNldHMgdGhlIHZhbHVlIGF0dHJpYnV0ZSBvbiB0aGUgYGlucHV0YCBlbGVtZW50LlxuXHQgKi9cblx0QElucHV0KCkgc2V0IHZhbHVlKHY6IGFueSkge1xuXHRcdGlmICh2ID09PSBcIlwiIHx8IHYgPT09IG51bGwpIHtcblx0XHRcdHRoaXMuX3ZhbHVlID0gbnVsbDtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy5fdmFsdWUgPSBOdW1iZXIodik7XG5cdH1cblxuXHRnZXQgdmFsdWUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3ZhbHVlO1xuXHR9XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBtaW4gYXR0cmlidXRlIG9uIHRoZSBgaW5wdXRgIGVsZW1lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSBtaW4gPSBudWxsO1xuXHQvKipcblx0ICogU2V0cyB0aGUgbWF4IGF0dHJpYnV0ZSBvbiB0aGUgYGlucHV0YCBlbGVtZW50LlxuXHQgKi9cblx0QElucHV0KCkgbWF4ID0gbnVsbDtcblx0LyoqXG5cdCAqIFNldHMgdGhlIHRleHQgaW5zaWRlIHRoZSBgbGFiZWxgIHRhZy5cblx0ICovXG5cdEBJbnB1dCgpIGxhYmVsOiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXHQvKipcblx0ICogU2V0cyB0aGUgb3B0aW9uYWwgaGVscGVyIHRleHQuXG5cdCAqL1xuXHRASW5wdXQoKSBoZWxwZXJUZXh0OiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXHQvKipcblx0ICogU2V0cyB0aGUgaW52YWxpZCB0ZXh0LlxuXHQgKi9cblx0QElucHV0KCkgaW52YWxpZFRleHQ6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT47XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBhbW91bnQgdGhlIG51bWJlciBjb250cm9scyBpbmNyZW1lbnQgYW5kIGRlY3JlbWVudCBieS5cblx0ICovXG5cdEBJbnB1dCgpIHN0ZXAgPSAxO1xuXHQvKipcblx0ICogSWYgYHN0ZXBgIGlzIGEgZGVjaW1hbCwgd2UgbWF5IHdhbnQgcHJlY2lzaW9uIHRvIGJlIHNldCB0byBnbyBhcm91bmQgZmxvYXRpbmcgcG9pbnQgcHJlY2lzaW9uLlxuXHQgKi9cblx0QElucHV0KCkgcHJlY2lzaW9uOiBudW1iZXI7XG5cdC8qKlxuXHQgKiBTZXQgdG8gYHRydWVgIHRvIHNob3cgYSB3YXJuaW5nIChjb250ZW50cyBzZXQgYnkgd2FybmluZ1RleHQpXG5cdCAqL1xuXHRASW5wdXQoKSB3YXJuID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB3YXJuaW5nIHRleHRcblx0ICovXG5cdEBJbnB1dCgpIHdhcm5UZXh0OiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXHQvKipcblx0ICogU2V0cyB0aGUgYXJpYWxhYmVsIGZvciBpbnB1dFxuXHQgKi9cblx0QElucHV0KCkgYXJpYUxhYmVsOiBzdHJpbmc7XG5cdC8qKlxuXHQgKiBFbWl0cyBldmVudCBub3RpZnlpbmcgb3RoZXIgY2xhc3NlcyB3aGVuIGEgY2hhbmdlIGluIHN0YXRlIG9jY3VycyBpbiB0aGUgaW5wdXQuXG5cdCAqL1xuXHRAT3V0cHV0KCkgY2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxOdW1iZXJDaGFuZ2U+KCk7XG5cblx0QElucHV0KClcblx0c2V0IGRlY3JlbWVudExhYmVsKHZhbHVlOiBzdHJpbmcgfCBPYnNlcnZhYmxlPHN0cmluZz4pIHtcblx0XHR0aGlzLl9kZWNyZW1lbnRMYWJlbC5vdmVycmlkZSh2YWx1ZSk7XG5cdH1cblxuXHRnZXQgZGVjcmVtZW50TGFiZWwoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2RlY3JlbWVudExhYmVsLnZhbHVlO1xuXHR9XG5cblx0QElucHV0KClcblx0c2V0IGluY3JlbWVudExhYmVsKHZhbHVlOiBzdHJpbmcgfCBPYnNlcnZhYmxlPHN0cmluZz4pIHtcblx0XHR0aGlzLl9pbmNyZW1lbnRMYWJlbC5vdmVycmlkZSh2YWx1ZSk7XG5cdH1cblxuXHRnZXQgaW5jcmVtZW50TGFiZWwoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2luY3JlbWVudExhYmVsLnZhbHVlO1xuXHR9XG5cblx0cHJvdGVjdGVkIF92YWx1ZSA9IDA7XG5cblx0cHJvdGVjdGVkIF9kZWNyZW1lbnRMYWJlbDogT3ZlcnJpZGFibGUgPSB0aGlzLmkxOG4uZ2V0T3ZlcnJpZGFibGUoXCJOVU1CRVIuREVDUkVNRU5UXCIpO1xuXHRwcm90ZWN0ZWQgX2luY3JlbWVudExhYmVsOiBPdmVycmlkYWJsZSA9IHRoaXMuaTE4bi5nZXRPdmVycmlkYWJsZShcIk5VTUJFUi5JTkNSRU1FTlRcIik7XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgYE51bWJlcmAuXG5cdCAqL1xuXHRjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgaTE4bjogSTE4bikge1xuXHRcdE51bWJlckNvbXBvbmVudC5udW1iZXJDb3VudCsrO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoaXMgaXMgdGhlIGluaXRpYWwgdmFsdWUgc2V0IHRvIHRoZSBjb21wb25lbnRcblx0ICogQHBhcmFtIHZhbHVlIFRoZSBpbnB1dCB2YWx1ZS5cblx0ICovXG5cdHB1YmxpYyB3cml0ZVZhbHVlKHZhbHVlOiBhbnkpIHtcblx0XHR0aGlzLnZhbHVlID0gdmFsdWU7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyBhIG1ldGhvZCBpbiBvcmRlciB0byBwcm9wYWdhdGUgY2hhbmdlcyBiYWNrIHRvIHRoZSBmb3JtLlxuXHQgKi9cblx0cHVibGljIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSkge1xuXHRcdHRoaXMucHJvcGFnYXRlQ2hhbmdlID0gZm47XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIGEgY2FsbGJhY2sgdG8gYmUgdHJpZ2dlcmVkIHdoZW4gdGhlIGNvbnRyb2wgaGFzIGJlZW4gdG91Y2hlZC5cblx0ICogQHBhcmFtIGZuIENhbGxiYWNrIHRvIGJlIHRyaWdnZXJlZCB3aGVuIHRoZSBudW1iZXIgaW5wdXQgaXMgdG91Y2hlZC5cblx0ICovXG5cdHB1YmxpYyByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KSB7XG5cdFx0dGhpcy5vblRvdWNoZWQgPSBmbjtcblx0fVxuXG5cdEBIb3N0TGlzdGVuZXIoXCJmb2N1c291dFwiKVxuXHRmb2N1c091dCgpIHtcblx0XHR0aGlzLm9uVG91Y2hlZCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGRpc2FibGVkIHN0YXRlIHRocm91Z2ggdGhlIG1vZGVsXG5cdCAqL1xuXHRzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pIHtcblx0XHR0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDYWxsZWQgd2hlbiBudW1iZXIgaW5wdXQgaXMgYmx1cnJlZC4gTmVlZGVkIHRvIHByb3Blcmx5IGltcGxlbWVudCBgQ29udHJvbFZhbHVlQWNjZXNzb3JgLlxuXHQgKi9cblx0b25Ub3VjaGVkOiAoKSA9PiBhbnkgPSAoKSA9PiB7IH07XG5cblx0LyoqXG5cdCAqIE1ldGhvZCBzZXQgaW4gYHJlZ2lzdGVyT25DaGFuZ2VgIHRvIHByb3BhZ2F0ZSBjaGFuZ2VzIGJhY2sgdG8gdGhlIGZvcm0uXG5cdCAqL1xuXHRwcm9wYWdhdGVDaGFuZ2UgPSAoXzogYW55KSA9PiB7IH07XG5cblx0LyoqXG5cdCAqIEFkZHMgYHN0ZXBgIHRvIHRoZSBjdXJyZW50IGB2YWx1ZWAuXG5cdCAqL1xuXHRvbkluY3JlbWVudCgpOiB2b2lkIHtcblx0XHRpZiAodGhpcy5tYXggPT09IG51bGwgfHwgdGhpcy52YWx1ZSArIHRoaXMuc3RlcCA8PSB0aGlzLm1heCkge1xuXHRcdFx0dGhpcy52YWx1ZSArPSB0aGlzLnN0ZXA7XG5cdFx0XHR0aGlzLnZhbHVlID0gcGFyc2VGbG9hdCh0aGlzLnZhbHVlLnRvUHJlY2lzaW9uKHRoaXMucHJlY2lzaW9uKSk7XG5cdFx0XHR0aGlzLmVtaXRDaGFuZ2VFdmVudCgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTdWJ0cmFjdHMgYHN0ZXBgIHRvIHRoZSBjdXJyZW50IGB2YWx1ZWAuXG5cdCAqL1xuXHRvbkRlY3JlbWVudCgpOiB2b2lkIHtcblx0XHRpZiAodGhpcy5taW4gPT09IG51bGwgfHwgdGhpcy52YWx1ZSAtIHRoaXMuc3RlcCA+PSB0aGlzLm1pbikge1xuXHRcdFx0dGhpcy52YWx1ZSAtPSB0aGlzLnN0ZXA7XG5cdFx0XHR0aGlzLnZhbHVlID0gcGFyc2VGbG9hdCh0aGlzLnZhbHVlLnRvUHJlY2lzaW9uKHRoaXMucHJlY2lzaW9uKSk7XG5cdFx0XHR0aGlzLmVtaXRDaGFuZ2VFdmVudCgpO1xuXHRcdH1cblx0fVxuXG5cdGdldERlY3JlbWVudExhYmVsKCk6IE9ic2VydmFibGU8c3RyaW5nPiB7XG5cdFx0cmV0dXJuIHRoaXMuX2RlY3JlbWVudExhYmVsLnN1YmplY3Q7XG5cdH1cblxuXHRnZXRJbmNyZW1lbnRMYWJlbCgpOiBPYnNlcnZhYmxlPHN0cmluZz4ge1xuXHRcdHJldHVybiB0aGlzLl9pbmNyZW1lbnRMYWJlbC5zdWJqZWN0O1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBjbGFzcyBvZiBgTnVtYmVyQ2hhbmdlYCB0byBlbWl0IHRoZSBjaGFuZ2UgaW4gdGhlIGBOdW1iZXJgLlxuXHQgKi9cblx0ZW1pdENoYW5nZUV2ZW50KCk6IHZvaWQge1xuXHRcdGxldCBldmVudCA9IG5ldyBOdW1iZXJDaGFuZ2UoKTtcblx0XHRldmVudC5zb3VyY2UgPSB0aGlzO1xuXHRcdGV2ZW50LnZhbHVlID0gdGhpcy52YWx1ZTtcblx0XHR0aGlzLmNoYW5nZS5lbWl0KGV2ZW50KTtcblx0XHR0aGlzLnByb3BhZ2F0ZUNoYW5nZSh0aGlzLnZhbHVlKTtcblx0fVxuXG5cdG9uTnVtYmVySW5wdXRDaGFuZ2UoZXZlbnQpIHtcblx0XHR0aGlzLnZhbHVlID0gZXZlbnQudGFyZ2V0LnZhbHVlO1xuXHRcdHRoaXMuZW1pdENoYW5nZUV2ZW50KCk7XG5cdH1cblxuXHRwdWJsaWMgaXNUZW1wbGF0ZSh2YWx1ZSkge1xuXHRcdHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFRlbXBsYXRlUmVmO1xuXHR9XG59XG5leHBvcnQgeyBOdW1iZXJDb21wb25lbnQgYXMgTnVtYmVyIH07XG4iXX0=