UNPKG

carbon-components-angular

Version:
454 lines 40 kB
import { ContentChildren, Component, EventEmitter, forwardRef, Input, Output, HostBinding, HostListener, TemplateRef } from "@angular/core"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; import { Radio } from "./radio.component"; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "carbon-components-angular/icon"; /** * Get started with importing the module: * * ```typescript * import { RadioModule } from 'carbon-components-angular'; * ``` * * Ex: * * ```html * <cds-radio-group [(ngModel)]="radio"> * <cds-radio *ngFor="let one of manyRadios" [value]="one"> * Radio {{one}} * </cds-radio> * </cds-radio-group> * * Radio selected: {{radio}} * ``` * * ```ts * const manyRadios = ["one", "two", "three", "four", "five", "six"]; * ``` * * [See demo](../../?path=/story/components-radio--basic) */ export class RadioGroup { constructor() { this.orientation = "horizontal"; this.labelPlacement = "right"; /** * Set to `true` to show the invalid state. */ this.invalid = false; /** * Set to `true` to show a warning (contents set by warnText) */ this.warn = false; /** * Emits event notifying other classes of a change using a `RadioChange` class. */ this.change = new EventEmitter(); /** * Binds 'cds--form-item' value to the class for `RadioGroup`. */ this.radioButtonGroupClass = true; /** * To track whether the `RadioGroup` has been initialized. */ this.isInitialized = false; /** * Reflects whether or not the input is disabled and cannot be selected. */ this._disabled = false; /** * Reflects whether or not the dropdown is loading. */ this._skeleton = false; /** * The value of the selected option within the `RadioGroup`. */ this._value = null; /** * The `Radio` within the `RadioGroup` that is selected. */ this._selected = null; /** * The name attribute associated with the `RadioGroup`. */ this._name = `radio-group-${RadioGroup.radioGroupCount++}`; /** * Needed to properly implement ControlValueAccessor. */ this.onTouched = () => { }; /** * Method set in registerOnChange to propagate changes back to the form. */ this.propagateChange = (_) => { }; } /** * Sets the passed in `Radio` item as the selected input within the `RadioGroup`. */ set selected(selected) { const alreadySelected = (this._selected && this._selected.value) === (selected && selected.value); if (alreadySelected) { // no need to redo return; } if (this._selected) { this._selected.checked = false; } this._selected = selected; this.value = selected ? selected.value : null; this.checkSelectedRadio(); } /** * Returns the `Radio` that is selected within the `RadioGroup`. */ get selected() { return this._selected; } /** * Sets the value/state of the selected `Radio` within the `RadioGroup` to the passed in value. */ set value(newValue) { if (this._value !== newValue) { this._value = newValue; this.updateSelectedRadioFromValue(); this.checkSelectedRadio(); } } /** * Returns the value/state of the selected `Radio` within the `RadioGroup`. */ get value() { return this._value; } /** * Replaces the name associated with the `RadioGroup` with the provided parameter. */ set name(name) { this._name = name; this.updateRadios(); } /** * Returns the associated name of the `RadioGroup`. */ get name() { return this._name; } /** * Set to true to disable the whole radio group */ set disabled(disabled) { this._disabled = disabled; this.updateRadios(); } /** * Returns the disabled value for the `RadioGroup`. */ get disabled() { return this._disabled; } /** * Returns the skeleton value in the `RadioGroup` if there is one. */ get skeleton() { return this._skeleton; } /** * Sets the skeleton value for all `Radio` to the skeleton value of `RadioGroup`. */ set skeleton(value) { this._skeleton = value; this.updateChildren(); } /** * Updates the selected `Radio` to be checked (selected). */ checkSelectedRadio() { if (this.selected && !this._selected.checked) { this.selected.checked = true; } } /** * Use the value of the `RadioGroup` to update the selected radio to the right state (selected state). */ updateSelectedRadioFromValue() { let alreadySelected = this._selected != null && this._selected.value === this._value; if (this.radios && !alreadySelected) { if (this.selected && this.value) { this.selected.checked = false; } this._selected = null; this.radios.forEach(radio => { if (radio.checked || radio.value === this._value) { this._selected = radio; } }); if (this.selected && !this.value) { this._value = this.selected.value; } } } /** * `ControlValueAccessor` method to programmatically disable the `RadioGroup`. * * ex: `this.formGroup.get("myRadioGroup").disable();` * * @param isDisabled `true` to disable the inputs */ setDisabledState(isDisabled) { this.disabled = isDisabled; } /** * Creates a class of `RadioChange` to emit the change in the `RadioGroup`. */ emitChangeEvent(event) { this.change.emit(event); this.propagateChange(event.value); this.onTouched(); } /** * Synchronizes radio properties. */ updateRadios() { if (this.radios) { setTimeout(() => { this.radios.forEach(radio => { radio.name = this.name; radio.setDisabledFromGroup(this.disabled); if (this.labelPlacement === "left") { radio.labelPlacement = "left"; } }); }); } } /** * Updates the value of the `RadioGroup` using the provided parameter. */ writeValue(value) { this.value = value; setTimeout(() => { this.updateSelectedRadioFromValue(); this.checkSelectedRadio(); }); } ngAfterContentInit() { this.radios.changes.subscribe(() => { this.updateRadios(); this.updateRadioChangeHandler(); }); this.updateChildren(); this.updateRadioChangeHandler(); } ngAfterViewInit() { this.updateRadios(); } /** * Used to set method 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 checkbox is touched. */ registerOnTouched(fn) { this.onTouched = fn; } focusOut() { this.onTouched(); } isTemplate(value) { return value instanceof TemplateRef; } updateChildren() { if (this.radios) { this.radios.forEach(child => child.skeleton = this.skeleton); } } updateRadioChangeHandler() { this.radios.forEach(radio => { radio.registerRadioChangeHandler((event) => { if ((this.selected && this.selected.value) === event.value) { // no need to redo return; } // deselect previous radio if (this.selected) { this.selected.checked = false; } // update selected and value from the event this._selected = event.source; this._value = event.value; // bubble the event this.emitChangeEvent(event); }); }); } } /** * Used for creating the `RadioGroup` 'name' property dynamically. */ RadioGroup.radioGroupCount = 0; RadioGroup.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: RadioGroup, deps: [], target: i0.ɵɵFactoryTarget.Component }); RadioGroup.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: RadioGroup, selector: "cds-radio-group, ibm-radio-group", inputs: { selected: "selected", value: "value", name: "name", disabled: "disabled", skeleton: "skeleton", orientation: "orientation", labelPlacement: "labelPlacement", legend: "legend", ariaLabel: "ariaLabel", ariaLabelledby: "ariaLabelledby", helperText: "helperText", invalid: "invalid", invalidText: "invalidText", warn: "warn", warnText: "warnText" }, outputs: { change: "change" }, host: { listeners: { "focusout": "focusOut()" }, properties: { "class.cds--form-item": "this.radioButtonGroupClass" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: RadioGroup, multi: true } ], queries: [{ propertyName: "radios", predicate: i0.forwardRef(function () { return Radio; }) }], ngImport: i0, template: ` <fieldset class="cds--radio-button-group" [attr.aria-label]="ariaLabel" [attr.aria-labelledby]="ariaLabelledby" [ngClass]="{ 'cds--radio-button-group--vertical': orientation === 'vertical', 'cds--radio-button-group--label-left': labelPlacement === 'left', 'cds--radio-button-group--invalid': invalid, 'cds--radio-button-group--warning': !invalid && warn }" [attr.data-invalid]="invalid ? true : null"> <legend *ngIf="legend" class="cds--label"> <ng-template *ngIf="isTemplate(legend); else legendLabel;" [ngTemplateOutlet]="legend"></ng-template> <ng-template #legendLabel>{{legend}}</ng-template> </legend> <ng-content></ng-content> </fieldset> <div class="cds--radio-button__validation-msg"> <ng-container *ngIf="invalid"> <svg cdsIcon="warning--filled" size="16" class="cds--radio-button__invalid-icon"> </svg> <div class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(invalidText)">{{ invalidText }}</ng-container> <ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template> </div> </ng-container> <ng-container *ngIf="!invalid && warn"> <svg cdsIcon="warning--alt--filled" class="cds--radio-button__invalid-icon cds--radio-button__invalid-icon--warning" size="16"> </svg> <div class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container> <ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template> </div> </ng-container> </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> `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: RadioGroup, decorators: [{ type: Component, args: [{ selector: "cds-radio-group, ibm-radio-group", template: ` <fieldset class="cds--radio-button-group" [attr.aria-label]="ariaLabel" [attr.aria-labelledby]="ariaLabelledby" [ngClass]="{ 'cds--radio-button-group--vertical': orientation === 'vertical', 'cds--radio-button-group--label-left': labelPlacement === 'left', 'cds--radio-button-group--invalid': invalid, 'cds--radio-button-group--warning': !invalid && warn }" [attr.data-invalid]="invalid ? true : null"> <legend *ngIf="legend" class="cds--label"> <ng-template *ngIf="isTemplate(legend); else legendLabel;" [ngTemplateOutlet]="legend"></ng-template> <ng-template #legendLabel>{{legend}}</ng-template> </legend> <ng-content></ng-content> </fieldset> <div class="cds--radio-button__validation-msg"> <ng-container *ngIf="invalid"> <svg cdsIcon="warning--filled" size="16" class="cds--radio-button__invalid-icon"> </svg> <div class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(invalidText)">{{ invalidText }}</ng-container> <ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template> </div> </ng-container> <ng-container *ngIf="!invalid && warn"> <svg cdsIcon="warning--alt--filled" class="cds--radio-button__invalid-icon cds--radio-button__invalid-icon--warning" size="16"> </svg> <div class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container> <ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template> </div> </ng-container> </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> `, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: RadioGroup, multi: true } ] }] }], propDecorators: { selected: [{ type: Input }], value: [{ type: Input }], name: [{ type: Input }], disabled: [{ type: Input }], skeleton: [{ type: Input }], orientation: [{ type: Input }], labelPlacement: [{ type: Input }], legend: [{ type: Input }], ariaLabel: [{ type: Input }], ariaLabelledby: [{ type: Input }], helperText: [{ type: Input }], invalid: [{ type: Input }], invalidText: [{ type: Input }], warn: [{ type: Input }], warnText: [{ type: Input }], change: [{ type: Output }], radios: [{ type: ContentChildren, args: [forwardRef(() => Radio)] }], radioButtonGroupClass: [{ type: HostBinding, args: ["class.cds--form-item"] }], focusOut: [{ type: HostListener, args: ["focusout"] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFkaW8tZ3JvdXAuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3JhZGlvL3JhZGlvLWdyb3VwLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRU4sZUFBZSxFQUNmLFNBQVMsRUFDVCxZQUFZLEVBQ1osVUFBVSxFQUNWLEtBQUssRUFDTCxNQUFNLEVBRU4sV0FBVyxFQUVYLFlBQVksRUFDWixXQUFXLEVBQ1gsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGlCQUFpQixFQUF3QixNQUFNLGdCQUFnQixDQUFDO0FBQ3pFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7OztBQUcxQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBNkRILE1BQU0sT0FBTyxVQUFVO0lBNUR2QjtRQThKVSxnQkFBVyxHQUE4QixZQUFZLENBQUM7UUFFdEQsbUJBQWMsR0FBc0IsT0FBTyxDQUFDO1FBbUJyRDs7V0FFRztRQUNNLFlBQU8sR0FBRyxLQUFLLENBQUM7UUFPekI7O1VBRUU7UUFDTyxTQUFJLEdBQUcsS0FBSyxDQUFDO1FBT3RCOztXQUVHO1FBQ08sV0FBTSxHQUE4QixJQUFJLFlBQVksRUFBZSxDQUFDO1FBUTlFOztXQUVHO1FBQ2tDLDBCQUFxQixHQUFHLElBQUksQ0FBQztRQUVsRTs7V0FFRztRQUNPLGtCQUFhLEdBQUcsS0FBSyxDQUFDO1FBQ2hDOztXQUVHO1FBQ08sY0FBUyxHQUFHLEtBQUssQ0FBQztRQUM1Qjs7V0FFRztRQUNPLGNBQVMsR0FBRyxLQUFLLENBQUM7UUFDNUI7O1dBRUc7UUFDTyxXQUFNLEdBQVEsSUFBSSxDQUFDO1FBQzdCOztXQUVHO1FBQ08sY0FBUyxHQUFVLElBQUksQ0FBQztRQUNsQzs7V0FFRztRQUNPLFVBQUssR0FBRyxlQUFlLFVBQVUsQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDO1FBa0hoRTs7V0FFRztR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Ozs7Ozs7Ozs7Ozs7Ozs7O0VBaURUOzJGQVNXLFVBQVU7a0JBNUR0QixTQUFTO21CQUFDO29CQUNWLFFBQVEsRUFBRSxrQ0FBa0M7b0JBQzVDLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQWlEVDtvQkFDRCxTQUFTLEVBQUU7d0JBQ1Y7NEJBQ0MsT0FBTyxFQUFFLGlCQUFpQjs0QkFDMUIsV0FBVyxZQUFZOzRCQUN2QixLQUFLLEVBQUUsSUFBSTt5QkFDWDtxQkFDRDtpQkFDRDs4QkFPSSxRQUFRO3NCQURYLEtBQUs7Z0JBMkJGLEtBQUs7c0JBRFIsS0FBSztnQkFxQkYsSUFBSTtzQkFEUCxLQUFLO2dCQWdCRixRQUFRO3NCQURYLEtBQUs7Z0JBZ0JGLFFBQVE7c0JBRFgsS0FBSztnQkFpQkcsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxjQUFjO3NCQUF0QixLQUFLO2dCQUVHLE1BQU07c0JBQWQsS0FBSztnQkFLRyxTQUFTO3NCQUFqQixLQUFLO2dCQUtHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBS0csVUFBVTtzQkFBbEIsS0FBSztnQkFLRyxPQUFPO3NCQUFmLEtBQUs7Z0JBS0csV0FBVztzQkFBbkIsS0FBSztnQkFLRyxJQUFJO3NCQUFaLEtBQUs7Z0JBS0csUUFBUTtzQkFBaEIsS0FBSztnQkFLSSxNQUFNO3NCQUFmLE1BQU07Z0JBTW1DLE1BQU07c0JBQS9DLGVBQWU7dUJBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQztnQkFLSCxxQkFBcUI7c0JBQXpELFdBQVc7dUJBQUMsc0JBQXNCO2dCQXVJbkMsUUFBUTtzQkFEUCxZQUFZO3VCQUFDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuXHRBZnRlckNvbnRlbnRJbml0LFxuXHRDb250ZW50Q2hpbGRyZW4sXG5cdENvbXBvbmVudCxcblx0RXZlbnRFbWl0dGVyLFxuXHRmb3J3YXJkUmVmLFxuXHRJbnB1dCxcblx0T3V0cHV0LFxuXHRRdWVyeUxpc3QsXG5cdEhvc3RCaW5kaW5nLFxuXHRBZnRlclZpZXdJbml0LFxuXHRIb3N0TGlzdGVuZXIsXG5cdFRlbXBsYXRlUmVmXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBOR19WQUxVRV9BQ0NFU1NPUiwgQ29udHJvbFZhbHVlQWNjZXNzb3IgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCB7IFJhZGlvIH0gZnJvbSBcIi4vcmFkaW8uY29tcG9uZW50XCI7XG5pbXBvcnQgeyBSYWRpb0NoYW5nZSB9IGZyb20gXCIuL3JhZGlvLWNoYW5nZS5jbGFzc1wiO1xuXG4vKipcbiAqIEdldCBzdGFydGVkIHdpdGggaW1wb3J0aW5nIHRoZSBtb2R1bGU6XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgUmFkaW9Nb2R1bGUgfSBmcm9tICdjYXJib24tY29tcG9uZW50cy1hbmd1bGFyJztcbiAqIGBgYFxuICpcbiAqIEV4OlxuICpcbiAqIGBgYGh0bWxcbiAqIDxjZHMtcmFkaW8tZ3JvdXAgWyhuZ01vZGVsKV09XCJyYWRpb1wiPlxuICogXHQ8Y2RzLXJhZGlvICpuZ0Zvcj1cImxldCBvbmUgb2YgbWFueVJhZGlvc1wiIFt2YWx1ZV09XCJvbmVcIj5cbiAqXHRcdFJhZGlvIHt7b25lfX1cbiAqIFx0PC9jZHMtcmFkaW8+XG4gKiA8L2Nkcy1yYWRpby1ncm91cD5cbiAqXG4gKiBSYWRpbyBzZWxlY3RlZDoge3tyYWRpb319XG4gKiBgYGBcbiAqXG4gKiBgYGB0c1xuICpcdGNvbnN0IG1hbnlSYWRpb3MgPSBbXCJvbmVcIiwgXCJ0d29cIiwgXCJ0aHJlZVwiLCBcImZvdXJcIiwgXCJmaXZlXCIsIFwic2l4XCJdO1xuICogYGBgXG4gKlxuICogW1NlZSBkZW1vXSguLi8uLi8/cGF0aD0vc3RvcnkvY29tcG9uZW50cy1yYWRpby0tYmFzaWMpXG4gKi9cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogXCJjZHMtcmFkaW8tZ3JvdXAsIGlibS1yYWRpby1ncm91cFwiLFxuXHR0ZW1wbGF0ZTogYFxuXHRcdDxmaWVsZHNldFxuXHRcdFx0Y2xhc3M9XCJjZHMtLXJhZGlvLWJ1dHRvbi1ncm91cFwiXG5cdFx0XHRbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbFwiXG5cdFx0XHRbYXR0ci5hcmlhLWxhYmVsbGVkYnldPVwiYXJpYUxhYmVsbGVkYnlcIlxuXHRcdFx0W25nQ2xhc3NdPVwie1xuXHRcdFx0XHQnY2RzLS1yYWRpby1idXR0b24tZ3JvdXAtLXZlcnRpY2FsJzogb3JpZW50YXRpb24gPT09ICd2ZXJ0aWNhbCcsXG5cdFx0XHRcdCdjZHMtLXJhZGlvLWJ1dHRvbi1ncm91cC0tbGFiZWwtbGVmdCc6IGxhYmVsUGxhY2VtZW50ID09PSAnbGVmdCcsXG5cdFx0XHRcdCdjZHMtLXJhZGlvLWJ1dHRvbi1ncm91cC0taW52YWxpZCc6IGludmFsaWQsXG5cdFx0XHRcdCdjZHMtLXJhZGlvLWJ1dHRvbi1ncm91cC0td2FybmluZyc6ICFpbnZhbGlkICYmIHdhcm5cblx0XHRcdH1cIlxuXHRcdFx0W2F0dHIuZGF0YS1pbnZhbGlkXT1cImludmFsaWQgPyB0cnVlIDogbnVsbFwiPlxuXHRcdFx0PGxlZ2VuZCAqbmdJZj1cImxlZ2VuZFwiIGNsYXNzPVwiY2RzLS1sYWJlbFwiPlxuXHRcdFx0XHQ8bmctdGVtcGxhdGUgKm5nSWY9XCJpc1RlbXBsYXRlKGxlZ2VuZCk7IGVsc2UgbGVnZW5kTGFiZWw7XCIgW25nVGVtcGxhdGVPdXRsZXRdPVwibGVnZW5kXCI+PC9uZy10ZW1wbGF0ZT5cblx0XHRcdFx0PG5nLXRlbXBsYXRlICNsZWdlbmRMYWJlbD57e2xlZ2VuZH19PC9uZy10ZW1wbGF0ZT5cblx0XHRcdDwvbGVnZW5kPlxuXHRcdFx0PG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuXHRcdDwvZmllbGRzZXQ+XG5cdFx0PGRpdiBjbGFzcz1cImNkcy0tcmFkaW8tYnV0dG9uX192YWxpZGF0aW9uLW1zZ1wiPlxuXHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cImludmFsaWRcIj5cblx0XHRcdFx0PHN2Z1xuXHRcdFx0XHRcdGNkc0ljb249XCJ3YXJuaW5nLS1maWxsZWRcIlxuXHRcdFx0XHRcdHNpemU9XCIxNlwiXG5cdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLXJhZGlvLWJ1dHRvbl9faW52YWxpZC1pY29uXCI+XG5cdFx0XHRcdDwvc3ZnPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzPVwiY2RzLS1mb3JtLXJlcXVpcmVtZW50XCI+XG5cdFx0XHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpc1RlbXBsYXRlKGludmFsaWRUZXh0KVwiPnt7IGludmFsaWRUZXh0IH19PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdFx0PG5nLXRlbXBsYXRlICpuZ0lmPVwiaXNUZW1wbGF0ZShpbnZhbGlkVGV4dClcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJpbnZhbGlkVGV4dFwiPjwvbmctdGVtcGxhdGU+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0PC9uZy1jb250YWluZXI+XG5cdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIWludmFsaWQgJiYgd2FyblwiPlxuXHRcdFx0XHQ8c3ZnXG5cdFx0XHRcdFx0Y2RzSWNvbj1cIndhcm5pbmctLWFsdC0tZmlsbGVkXCJcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tcmFkaW8tYnV0dG9uX19pbnZhbGlkLWljb24gY2RzLS1yYWRpby1idXR0b25fX2ludmFsaWQtaWNvbi0td2FybmluZ1wiXG5cdFx0XHRcdFx0c2l6ZT1cIjE2XCI+XG5cdFx0XHRcdDwvc3ZnPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzPVwiY2RzLS1mb3JtLXJlcXVpcmVtZW50XCI+XG5cdFx0XHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpc1RlbXBsYXRlKHdhcm5UZXh0KVwiPnt7d2FyblRleHR9fTwvbmctY29udGFpbmVyPlxuXHRcdFx0XHRcdDxuZy10ZW1wbGF0ZSAqbmdJZj1cImlzVGVtcGxhdGUod2FyblRleHQpXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwid2FyblRleHRcIj48L25nLXRlbXBsYXRlPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvbmctY29udGFpbmVyPlxuXHRcdDwvZGl2PlxuXHRcdDxkaXZcblx0XHRcdCpuZ0lmPVwiaGVscGVyVGV4dCAmJiAhaW52YWxpZCAmJiAhd2FyblwiXG5cdFx0XHRjbGFzcz1cImNkcy0tZm9ybV9faGVscGVyLXRleHRcIlxuXHRcdFx0W25nQ2xhc3NdPVwieydjZHMtLWZvcm1fX2hlbHBlci10ZXh0LS1kaXNhYmxlZCc6IGRpc2FibGVkfVwiPlxuXHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpc1RlbXBsYXRlKGhlbHBlclRleHQpXCI+e3toZWxwZXJUZXh0fX08L25nLWNvbnRhaW5lcj5cblx0XHRcdDxuZy10ZW1wbGF0ZSAqbmdJZj1cImlzVGVtcGxhdGUoaGVscGVyVGV4dClcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJoZWxwZXJUZXh0XCI+PC9uZy10ZW1wbGF0ZT5cblx0XHQ8L2Rpdj5cblx0YCxcblx0cHJvdmlkZXJzOiBbXG5cdFx0e1xuXHRcdFx0cHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG5cdFx0XHR1c2VFeGlzdGluZzogUmFkaW9Hcm91cCxcblx0XHRcdG11bHRpOiB0cnVlXG5cdFx0fVxuXHRdXG59KVxuZXhwb3J0IGNsYXNzIFJhZGlvR3JvdXAgaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0LCBBZnRlclZpZXdJbml0LCBDb250cm9sVmFsdWVBY2Nlc3NvciB7XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHBhc3NlZCBpbiBgUmFkaW9gIGl0ZW0gYXMgdGhlIHNlbGVjdGVkIGlucHV0IHdpdGhpbiB0aGUgYFJhZGlvR3JvdXBgLlxuXHQgKi9cblx0QElucHV0KClcblx0c2V0IHNlbGVjdGVkKHNlbGVjdGVkOiBSYWRpbyB8IG51bGwpIHtcblx0XHRjb25zdCBhbHJlYWR5U2VsZWN0ZWQgPSAodGhpcy5fc2VsZWN0ZWQgJiYgdGhpcy5fc2VsZWN0ZWQudmFsdWUpID09PSAoc2VsZWN0ZWQgJiYgc2VsZWN0ZWQudmFsdWUpO1xuXHRcdGlmIChhbHJlYWR5U2VsZWN0ZWQpIHtcblx0XHRcdC8vIG5vIG5lZWQgdG8gcmVkb1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLl9zZWxlY3RlZCkge1xuXHRcdFx0dGhpcy5fc2VsZWN0ZWQuY2hlY2tlZCA9IGZhbHNlO1xuXHRcdH1cblx0XHR0aGlzLl9zZWxlY3RlZCA9IHNlbGVjdGVkO1xuXHRcdHRoaXMudmFsdWUgPSBzZWxlY3RlZCA/IHNlbGVjdGVkLnZhbHVlIDogbnVsbDtcblx0XHR0aGlzLmNoZWNrU2VsZWN0ZWRSYWRpbygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGBSYWRpb2AgdGhhdCBpcyBzZWxlY3RlZCB3aXRoaW4gdGhlIGBSYWRpb0dyb3VwYC5cblx0ICovXG5cdGdldCBzZWxlY3RlZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5fc2VsZWN0ZWQ7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgdmFsdWUvc3RhdGUgb2YgdGhlIHNlbGVjdGVkIGBSYWRpb2Agd2l0aGluIHRoZSBgUmFkaW9Hcm91cGAgdG8gdGhlIHBhc3NlZCBpbiB2YWx1ZS5cblx0ICovXG5cdEBJbnB1dCgpXG5cdHNldCB2YWx1ZShuZXdWYWx1ZTogYW55KSB7XG5cdFx0aWYgKHRoaXMuX3ZhbHVlICE9PSBuZXdWYWx1ZSkge1xuXHRcdFx0dGhpcy5fdmFsdWUgPSBuZXdWYWx1ZTtcblxuXHRcdFx0dGhpcy51cGRhdGVTZWxlY3RlZFJhZGlvRnJvbVZhbHVlKCk7XG5cdFx0XHR0aGlzLmNoZWNrU2VsZWN0ZWRSYWRpbygpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSB2YWx1ZS9zdGF0ZSBvZiB0aGUgc2VsZWN0ZWQgYFJhZGlvYCB3aXRoaW4gdGhlIGBSYWRpb0dyb3VwYC5cblx0ICovXG5cdGdldCB2YWx1ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdmFsdWU7XG5cdH1cblxuXHQvKipcblx0ICogUmVwbGFjZXMgdGhlIG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBgUmFkaW9Hcm91cGAgd2l0aCB0aGUgcHJvdmlkZWQgcGFyYW1ldGVyLlxuXHQgKi9cblx0QElucHV0KClcblx0c2V0IG5hbWUobmFtZTogc3RyaW5nKSB7XG5cdFx0dGhpcy5fbmFtZSA9IG5hbWU7XG5cdFx0dGhpcy51cGRhdGVSYWRpb3MoKTtcblx0fVxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgYXNzb2NpYXRlZCBuYW1lIG9mIHRoZSBgUmFkaW9Hcm91cGAuXG5cdCAqL1xuXHRnZXQgbmFtZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fbmFtZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXQgdG8gdHJ1ZSB0byBkaXNhYmxlIHRoZSB3aG9sZSByYWRpbyBncm91cFxuXHQgKi9cblx0QElucHV0KClcblx0c2V0IGRpc2FibGVkKGRpc2FibGVkOiBib29sZWFuKSB7XG5cdFx0dGhpcy5fZGlzYWJsZWQgPSBkaXNhYmxlZDtcblx0XHR0aGlzLnVwZGF0ZVJhZGlvcygpO1xuXHR9XG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBkaXNhYmxlZCB2YWx1ZSBmb3IgdGhlIGBSYWRpb0dyb3VwYC5cblx0ICovXG5cdGdldCBkaXNhYmxlZCgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5fZGlzYWJsZWQ7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgc2tlbGV0b24gdmFsdWUgaW4gdGhlIGBSYWRpb0dyb3VwYCBpZiB0aGVyZSBpcyBvbmUuXG5cdCAqL1xuXHRASW5wdXQoKVxuXHRnZXQgc2tlbGV0b24oKTogYW55IHtcblx0XHRyZXR1cm4gdGhpcy5fc2tlbGV0b247XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgc2tlbGV0b24gdmFsdWUgZm9yIGFsbCBgUmFkaW9gIHRvIHRoZSBza2VsZXRvbiB2YWx1ZSBvZiBgUmFkaW9Hcm91cGAuXG5cdCAqL1xuXHRzZXQgc2tlbGV0b24odmFsdWU6IGFueSkge1xuXHRcdHRoaXMuX3NrZWxldG9uID0gdmFsdWU7XG5cdFx0dGhpcy51cGRhdGVDaGlsZHJlbigpO1xuXHR9XG5cdC8qKlxuXHQgKiBVc2VkIGZvciBjcmVhdGluZyB0aGUgYFJhZGlvR3JvdXBgICduYW1lJyBwcm9wZXJ0eSBkeW5hbWljYWxseS5cblx0ICovXG5cdHN0YXRpYyByYWRpb0dyb3VwQ291bnQgPSAwO1xuXG5cdEBJbnB1dCgpIG9yaWVudGF0aW9uOiBcImhvcml6b250YWxcIiB8IFwidmVydGljYWxcIiA9IFwiaG9yaXpvbnRhbFwiO1xuXG5cdEBJbnB1dCgpIGxhYmVsUGxhY2VtZW50OiBcInJpZ2h0XCIgfCBcImxlZnRcIiA9ICBcInJpZ2h0XCI7XG5cblx0QElucHV0KCkgbGVnZW5kOiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXG5cdC8qKlxuXHQgKiBVc2VkIHRvIHNldCB0aGUgYGFyaWEtbGFiZWxgIGF0dHJpYnV0ZSBvbiB0aGUgcmFkaW8gZ3JvdXAgZWxlbWVudC5cblx0ICovXG5cdEBJbnB1dCgpIGFyaWFMYWJlbDogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBVc2VkIHRvIHNldCB0aGUgYGFyaWEtbGFiZWxsZWRieWAgYXR0cmlidXRlIG9uIHRoZSByYWRpbyBncm91cCBlbGVtZW50LlxuXHQgKi9cblx0QElucHV0KCkgYXJpYUxhYmVsbGVkYnk6IHN0cmluZztcblxuXHQvKipcblx0ICogU2V0cyB0aGUgb3B0aW9uYWwgaGVscGVyIHRleHQuXG5cdCAqL1xuXHRASW5wdXQoKSBoZWxwZXJUZXh0OiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXG5cdC8qKlxuXHQgKiBTZXQgdG8gYHRydWVgIHRvIHNob3cgdGhlIGludmFsaWQgc3RhdGUuXG5cdCAqL1xuXHRASW5wdXQoKSBpbnZhbGlkID0gZmFsc2U7XG5cblx0LyoqXG5cdCAqIFZhbHVlIGRpc3BsYXllZCBpZiBjb21ib2JveCBpcyBpbiBhbiBpbnZhbGlkIHN0YXRlLlxuXHQgKi9cblx0QElucHV0KCkgaW52YWxpZFRleHQ6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT47XG5cblx0LyoqXG5cdCogU2V0IHRvIGB0cnVlYCB0byBzaG93IGEgd2FybmluZyAoY29udGVudHMgc2V0IGJ5IHdhcm5UZXh0KVxuXHQqL1xuXHRASW5wdXQoKSB3YXJuID0gZmFsc2U7XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHdhcm5pbmcgdGV4dFxuXHQgKi9cblx0QElucHV0KCkgd2FyblRleHQ6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT47XG5cblx0LyoqXG5cdCAqIEVtaXRzIGV2ZW50IG5vdGlmeWluZyBvdGhlciBjbGFzc2VzIG9mIGEgY2hhbmdlIHVzaW5nIGEgYFJhZGlvQ2hhbmdlYCBjbGFzcy5cblx0ICovXG5cdEBPdXRwdXQoKSBjaGFuZ2U6IEV2ZW50RW1pdHRlcjxSYWRpb0NoYW5nZT4gPSBuZXcgRXZlbnRFbWl0dGVyPFJhZGlvQ2hhbmdlPigpO1xuXG5cdC8qKlxuXHQgKiBUaGUgYFJhZGlvYCBpbnB1dCBpdGVtcyBpbiB0aGUgYFJhZGlvR3JvdXBgLlxuXHQgKi9cblx0Ly8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWZvcndhcmQtcmVmXG5cdEBDb250ZW50Q2hpbGRyZW4oZm9yd2FyZFJlZigoKSA9PiBSYWRpbykpIHJhZGlvczogUXVlcnlMaXN0PFJhZGlvPjtcblxuXHQvKipcblx0ICogQmluZHMgJ2Nkcy0tZm9ybS1pdGVtJyB2YWx1ZSB0byB0aGUgY2xhc3MgZm9yIGBSYWRpb0dyb3VwYC5cblx0ICovXG5cdEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tZm9ybS1pdGVtXCIpIHJhZGlvQnV0dG9uR3JvdXBDbGFzcyA9IHRydWU7XG5cblx0LyoqXG5cdCAqIFRvIHRyYWNrIHdoZXRoZXIgdGhlIGBSYWRpb0dyb3VwYCBoYXMgYmVlbiBpbml0aWFsaXplZC5cblx0ICovXG5cdHByb3RlY3RlZCBpc0luaXRpYWxpemVkID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBSZWZsZWN0cyB3aGV0aGVyIG9yIG5vdCB0aGUgaW5wdXQgaXMgZGlzYWJsZWQgYW5kIGNhbm5vdCBiZSBzZWxlY3RlZC5cblx0ICovXG5cdHByb3RlY3RlZCBfZGlzYWJsZWQgPSBmYWxzZTtcblx0LyoqXG5cdCAqIFJlZmxlY3RzIHdoZXRoZXIgb3Igbm90IHRoZSBkcm9wZG93biBpcyBsb2FkaW5nLlxuXHQgKi9cblx0cHJvdGVjdGVkIF9za2VsZXRvbiA9IGZhbHNlO1xuXHQvKipcblx0ICogVGhlIHZhbHVlIG9mIHRoZSBzZWxlY3RlZCBvcHRpb24gd2l0aGluIHRoZSBgUmFkaW9Hcm91cGAuXG5cdCAqL1xuXHRwcm90ZWN0ZWQgX3ZhbHVlOiBhbnkgPSBudWxsO1xuXHQvKipcblx0ICogVGhlIGBSYWRpb2Agd2l0aGluIHRoZSBgUmFkaW9Hcm91cGAgdGhhdCBpcyBzZWxlY3RlZC5cblx0ICovXG5cdHByb3RlY3RlZCBfc2VsZWN0ZWQ6IFJhZGlvID0gbnVsbDtcblx0LyoqXG5cdCAqIFRoZSBuYW1lIGF0dHJpYnV0ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGBSYWRpb0dyb3VwYC5cblx0ICovXG5cdHByb3RlY3RlZCBfbmFtZSA9IGByYWRpby1ncm91cC0ke1JhZGlvR3JvdXAucmFkaW9Hcm91cENvdW50Kyt9YDtcblxuXHQvKipcblx0ICogVXBkYXRlcyB0aGUgc2VsZWN0ZWQgYFJhZGlvYCB0byBiZSBjaGVja2VkIChzZWxlY3RlZCkuXG5cdCAqL1xuXHRjaGVja1NlbGVjdGVkUmFkaW8oKSB7XG5cdFx0aWYgKHRoaXMuc2VsZWN0ZWQgJiYgIXRoaXMuX3NlbGVjdGVkLmNoZWNrZWQpIHtcblx0XHRcdHRoaXMuc2VsZWN0ZWQuY2hlY2tlZCA9IHRydWU7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFVzZSB0aGUgdmFsdWUgb2YgdGhlIGBSYWRpb0dyb3VwYCB0byB1cGRhdGUgdGhlIHNlbGVjdGVkIHJhZGlvIHRvIHRoZSByaWdodCBzdGF0ZSAoc2VsZWN0ZWQgc3RhdGUpLlxuXHQgKi9cblx0dXBkYXRlU2VsZWN0ZWRSYWRpb0Zyb21WYWx1ZSgpIHtcblx0XHRsZXQgYWxyZWFkeVNlbGVjdGVkID0gdGhpcy5fc2VsZWN0ZWQgIT0gbnVsbCAmJiB0aGlzLl9zZWxlY3RlZC52YWx1ZSA9PT0gdGhpcy5fdmFsdWU7XG5cdFx0aWYgKHRoaXMucmFkaW9zICYmICFhbHJlYWR5U2VsZWN0ZWQpIHtcblx0XHRcdGlmICh0aGlzLnNlbGVjdGVkICYmIHRoaXMudmFsdWUpIHtcblx0XHRcdFx0dGhpcy5zZWxlY3RlZC5jaGVja2VkID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLl9zZWxlY3RlZCA9IG51bGw7XG5cdFx0XHR0aGlzLnJhZGlvcy5mb3JFYWNoKHJhZGlvID0+IHtcblx0XHRcdFx0aWYgKHJhZGlvLmNoZWNrZWQgfHwgcmFkaW8udmFsdWUgPT09IHRoaXMuX3ZhbHVlKSB7XG5cdFx0XHRcdFx0dGhpcy5fc2VsZWN0ZWQgPSByYWRpbztcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0XHRpZiAodGhpcy5zZWxlY3RlZCAmJiAhdGhpcy52YWx1ZSkge1xuXHRcdFx0XHR0aGlzLl92YWx1ZSA9IHRoaXMuc2VsZWN0ZWQudmFsdWU7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIGBDb250cm9sVmFsdWVBY2Nlc3NvcmAgbWV0aG9kIHRvIHByb2dyYW1tYXRpY2FsbHkgZGlzYWJsZSB0aGUgYFJhZGlvR3JvdXBgLlxuXHQgKlxuXHQgKiBleDogYHRoaXMuZm9ybUdyb3VwLmdldChcIm15UmFkaW9Hcm91cFwiKS5kaXNhYmxlKCk7YFxuXHQgKlxuXHQgKiBAcGFyYW0gaXNEaXNhYmxlZCBgdHJ1ZWAgdG8gZGlzYWJsZSB0aGUgaW5wdXRzXG5cdCAqL1xuXHRzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pIHtcblx0XHR0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgY2xhc3Mgb2YgYFJhZGlvQ2hhbmdlYCB0byBlbWl0IHRoZSBjaGFuZ2UgaW4gdGhlIGBSYWRpb0dyb3VwYC5cblx0ICovXG5cdGVtaXRDaGFuZ2VFdmVudChldmVudDogUmFkaW9DaGFuZ2UpIHtcblx0XHR0aGlzLmNoYW5nZS5lbWl0KGV2ZW50KTtcblx0XHR0aGlzLnByb3BhZ2F0ZUNoYW5nZShldmVudC52YWx1ZSk7XG5cdFx0dGhpcy5vblRvdWNoZWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTeW5jaHJvbml6ZXMgcmFkaW8gcHJvcGVydGllcy5cblx0ICovXG5cdHVwZGF0ZVJhZGlvcygpIHtcblx0XHRpZiAodGhpcy5yYWRpb3MpIHtcblx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHR0aGlzLnJhZGlvcy5mb3JFYWNoKHJhZGlvID0+IHtcblx0XHRcdFx0XHRyYWRpby5uYW1lID0gdGhpcy5uYW1lO1xuXHRcdFx0XHRcdHJhZGlvLnNldERpc2FibGVkRnJvbUdyb3VwKHRoaXMuZGlzYWJsZWQpO1xuXHRcdFx0XHRcdGlmICh0aGlzLmxhYmVsUGxhY2VtZW50ID09PSBcImxlZnRcIikge1xuXHRcdFx0XHRcdFx0cmFkaW8ubGFiZWxQbGFjZW1lbnQgPSBcImxlZnRcIjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFVwZGF0ZXMgdGhlIHZhbHVlIG9mIHRoZSBgUmFkaW9Hcm91cGAgdXNpbmcgdGhlIHByb3ZpZGVkIHBhcmFtZXRlci5cblx0ICovXG5cdHdyaXRlVmFsdWUodmFsdWU6IGFueSkge1xuXHRcdHRoaXMudmFsdWUgPSB2YWx1ZTtcblx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdHRoaXMudXBkYXRlU2VsZWN0ZWRSYWRpb0Zyb21WYWx1ZSgpO1xuXHRcdFx0dGhpcy5jaGVja1NlbGVjdGVkUmFkaW8oKTtcblx0XHR9KTtcblx0fVxuXG5cdG5nQWZ0ZXJDb250ZW50SW5pdCgpIHtcblx0XHR0aGlzLnJhZGlvcy5jaGFuZ2VzLnN1YnNjcmliZSgoKSA9PiB7XG5cdFx0XHR0aGlzLnVwZGF0ZVJhZGlvcygpO1xuXHRcdFx0dGhpcy51cGRhdGVSYWRpb0NoYW5nZUhhbmRsZXIoKTtcblx0XHR9KTtcblxuXHRcdHRoaXMudXBkYXRlQ2hpbGRyZW4oKTtcblx0XHR0aGlzLnVwZGF0ZVJhZGlvQ2hhbmdlSGFuZGxlcigpO1xuXHR9XG5cblx0bmdBZnRlclZpZXdJbml0KCkge1xuXHRcdHRoaXMudXBkYXRlUmFkaW9zKCk7XG5cdH1cblxuXHQvKipcblx0ICogVXNlZCB0byBzZXQgbWV0aG9kIHRvIHByb3BhZ2F0ZSBjaGFuZ2VzIGJhY2sgdG8gdGhlIGZvcm0uXG5cdCAqL1xuXHRwdWJsaWMgcmVnaXN0ZXJPbkNoYW5nZShmbjogYW55KSB7XG5cdFx0dGhpcy5wcm9wYWdhdGVDaGFuZ2UgPSBmbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZWdpc3RlcnMgYSBjYWxsYmFjayB0byBiZSB0cmlnZ2VyZWQgd2hlbiB0aGUgY29udHJvbCBoYXMgYmVlbiB0b3VjaGVkLlxuXHQgKiBAcGFyYW0gZm4gQ2FsbGJhY2sgdG8gYmUgdHJpZ2dlcmVkIHdoZW4gdGhlIGNoZWNrYm94IGlzIHRvdWNoZWQuXG5cdCAqL1xuXHRwdWJsaWMgcmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSkge1xuXHRcdHRoaXMub25Ub3VjaGVkID0gZm47XG5cdH1cblxuXHRASG9zdExpc3RlbmVyKFwiZm9jdXNvdXRcIilcblx0Zm9jdXNPdXQoKSB7XG5cdFx0dGhpcy5vblRvdWNoZWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBOZWVkZWQgdG8gcHJvcGVybHkgaW1wbGVtZW50IENvbnRyb2xWYWx1ZUFjY2Vzc29yLlxuXHQgKi9cblx0b25Ub3VjaGVkOiAoKSA9PiBhbnkgPSAoKSA9PiB7fTtcblxuXHQvKipcblx0ICogTWV0aG9kIHNldCBpbiByZWdpc3Rlck9uQ2hhbmdlIHRvIHByb3BhZ2F0ZSBjaGFuZ2VzIGJhY2sgdG8gdGhlIGZvcm0uXG5cdCAqL1xuXHRwcm9wYWdhdGVDaGFuZ2UgPSAoXzogYW55KSA9PiB7fTtcblxuXHRwdWJsaWMgaXNUZW1wbGF0ZSh2YWx1ZSkge1xuXHRcdHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFRlbXBsYXRlUmVmO1xuXHR9XG5cblx0cHJvdGVjdGVkIHVwZGF0ZUNoaWxkcmVuKCkge1xuXHRcdGlmICh0aGlzLnJhZGlvcykge1xuXHRcdFx0dGhpcy5yYWRpb3MuZm9yRWFjaChjaGlsZCA9PiBjaGlsZC5za2VsZXRvbiA9IHRoaXMuc2tlbGV0b24pO1xuXHRcdH1cblx0fVxuXG5cdHByb3RlY3RlZCB1cGRhdGVSYWRpb0NoYW5nZUhhbmRsZXIoKSB7XG5cdFx0dGhpcy5yYWRpb3MuZm9yRWFjaChyYWRpbyA9PiB7XG5cdFx0XHRyYWRpby5yZWdpc3RlclJhZGlvQ2hhbmdlSGFuZGxlcigoZXZlbnQ6IFJhZGlvQ2hhbmdlKSA9PiB7XG5cdFx0XHRcdGlmICgodGhpcy5zZWxlY3RlZCAmJiB0aGlzLnNlbGVjdGVkLnZhbHVlKSA9PT0gZXZlbnQudmFsdWUpIHtcblx0XHRcdFx0XHQvLyBubyBuZWVkIHRvIHJlZG9cblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0Ly8gZGVzZWxlY3QgcHJldmlvdXMgcmFkaW9cblx0XHRcdFx0aWYgKHRoaXMuc2VsZWN0ZWQpIHtcblx0XHRcdFx0XHR0aGlzLnNlbGVjdGVkLmNoZWNrZWQgPSBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHQvLyB1cGRhdGUgc2VsZWN0ZWQgYW5kIHZhbHVlIGZyb20gdGhlIGV2ZW50XG5cdFx0XHRcdHRoaXMuX3NlbGVjdGVkID0gZXZlbnQuc291cmNlO1xuXHRcdFx0XHR0aGlzLl92YWx1ZSA9IGV2ZW50LnZhbHVlO1xuXHRcdFx0XHQvLyBidWJibGUgdGhlIGV2ZW50XG5cdFx0XHRcdHRoaXMuZW1pdENoYW5nZUV2ZW50KGV2ZW50KTtcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9XG59XG4iXX0=