UNPKG

@jsonforms/angular-material

Version:

Material Renderer Set for Angular module of JSON Forms

171 lines (167 loc) 19.1 kB
/* The MIT License Copyright (c) 2017-2019 EclipseSource Munich https://github.com/eclipsesource/jsonforms Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ import { ChangeDetectionStrategy, Component, Input, } from '@angular/core'; import { JsonFormsAngularService, JsonFormsControl } from '@jsonforms/angular'; import { Actions, composeWithUi, isEnumControl, rankWith, } from '@jsonforms/core'; import { map, startWith } from 'rxjs/operators'; import * as i0 from "@angular/core"; import * as i1 from "@jsonforms/angular"; import * as i2 from "@angular/common"; import * as i3 from "@angular/material/form-field"; import * as i4 from "@angular/material/input"; import * as i5 from "@angular/forms"; import * as i6 from "@angular/material/core"; import * as i7 from "@angular/material/autocomplete"; /** * To use this component you will need to add your own tester: * <pre><code> * ... * export const AutocompleteControlRendererTester: RankedTester = rankWith(2, isEnumControl); * ... * </code></pre> * Add the tester and renderer to JSONForms registry: * <pre><code> * ... * { tester: AutocompleteControlRendererTester, renderer: AutocompleteControlRenderer }, * ... * </code></pre> * Furthermore you need to update your module. * <pre><code> * ... * imports: [JsonFormsAngularMaterialModule, MatAutocompleteModule], * declarations: [AutocompleteControlRenderer] * ... * </code></pre> * */ export class AutocompleteControlRenderer extends JsonFormsControl { options; filteredOptions; shouldFilter; focused = false; constructor(jsonformsService) { super(jsonformsService); } getEventValue = (event) => event.target.value; ngOnInit() { super.ngOnInit(); this.shouldFilter = false; this.filteredOptions = this.form.valueChanges.pipe(startWith(''), map((val) => this.filter(val))); } updateFilter(event) { // ENTER if (event.keyCode === 13) { this.shouldFilter = false; } else { this.shouldFilter = true; } } onSelect(ev) { const path = composeWithUi(this.uischema, this.path); this.shouldFilter = false; this.jsonFormsService.updateCore(Actions.update(path, () => ev.option.value)); this.triggerValidation(); } filter(val) { return (this.options || this.scopedSchema.enum || []).filter((option) => !this.shouldFilter || !val || option.toLowerCase().indexOf(val.toLowerCase()) === 0); } getOwnProps() { return { ...super.getOwnProps(), options: this.options, }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutocompleteControlRenderer, deps: [{ token: i1.JsonFormsAngularService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: AutocompleteControlRenderer, selector: "AutocompleteControlRenderer", inputs: { options: "options" }, usesInheritance: true, ngImport: i0, template: ` <mat-form-field [ngStyle]="{ display: hidden ? 'none' : '' }"> <mat-label>{{ label }}</mat-label> <input matInput type="text" (change)="onChange($event)" [id]="id" [formControl]="form" [matAutocomplete]="auto" (keydown)="updateFilter($event)" (focus)="focused = true" (focusout)="focused = false" /> <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete" (optionSelected)="onSelect($event)" > <mat-option *ngFor="let option of filteredOptions | async" [value]="option" > {{ option }} </mat-option> </mat-autocomplete> <mat-hint *ngIf="shouldShowUnfocusedDescription() || focused">{{ description }}</mat-hint> <mat-error>{{ error }}</mat-error> </mat-form-field> `, isInline: true, styles: [":host{display:flex;flex-direction:row}mat-form-field{flex:1 1 auto}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i7.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutocompleteControlRenderer, decorators: [{ type: Component, args: [{ selector: 'AutocompleteControlRenderer', template: ` <mat-form-field [ngStyle]="{ display: hidden ? 'none' : '' }"> <mat-label>{{ label }}</mat-label> <input matInput type="text" (change)="onChange($event)" [id]="id" [formControl]="form" [matAutocomplete]="auto" (keydown)="updateFilter($event)" (focus)="focused = true" (focusout)="focused = false" /> <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete" (optionSelected)="onSelect($event)" > <mat-option *ngFor="let option of filteredOptions | async" [value]="option" > {{ option }} </mat-option> </mat-autocomplete> <mat-hint *ngIf="shouldShowUnfocusedDescription() || focused">{{ description }}</mat-hint> <mat-error>{{ error }}</mat-error> </mat-form-field> `, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, styles: [":host{display:flex;flex-direction:row}mat-form-field{flex:1 1 auto}\n"] }] }], ctorParameters: () => [{ type: i1.JsonFormsAngularService }], propDecorators: { options: [{ type: Input }] } }); export const enumControlTester = rankWith(2, isEnumControl); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0b2NvbXBsZXRlLnJlbmRlcmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYnJhcnkvY29udHJvbHMvYXV0b2NvbXBsZXRlLnJlbmRlcmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQXVCRTtBQUNGLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULEtBQUssR0FFTixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRSxPQUFPLEVBQ0wsT0FBTyxFQUNQLGFBQWEsRUFFYixhQUFhLEVBR2IsUUFBUSxHQUNULE1BQU0saUJBQWlCLENBQUM7QUFFekIsT0FBTyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7Ozs7O0FBRWhEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFpREgsTUFBTSxPQUFPLDJCQUNYLFNBQVEsZ0JBQWdCO0lBR2YsT0FBTyxDQUFXO0lBQzNCLGVBQWUsQ0FBdUI7SUFDdEMsWUFBWSxDQUFVO0lBQ3RCLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFFaEIsWUFBWSxnQkFBeUM7UUFDbkQsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUNELGFBQWEsR0FBRyxDQUFDLEtBQVUsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7SUFFbkQsUUFBUTtRQUNOLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNqQixJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQztRQUMxQixJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FDaEQsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUNiLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUMvQixDQUFDO0lBQ0osQ0FBQztJQUVELFlBQVksQ0FBQyxLQUFVO1FBQ3JCLFFBQVE7UUFDUixJQUFJLEtBQUssQ0FBQyxPQUFPLEtBQUssRUFBRSxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDNUIsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUMzQixDQUFDO0lBQ0gsQ0FBQztJQUVELFFBQVEsQ0FBQyxFQUFnQztRQUN2QyxNQUFNLElBQUksR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLFFBQTBCLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3ZFLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDO1FBQzFCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVLENBQzlCLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQzVDLENBQUM7UUFDRixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsTUFBTSxDQUFDLEdBQVc7UUFDaEIsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUMxRCxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQ1QsQ0FBQyxJQUFJLENBQUMsWUFBWTtZQUNsQixDQUFDLEdBQUc7WUFDSixNQUFNLENBQUMsV0FBVyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FDeEQsQ0FBQztJQUNKLENBQUM7SUFDUyxXQUFXO1FBQ25CLE9BQU87WUFDTCxHQUFHLEtBQUssQ0FBQyxXQUFXLEVBQUU7WUFDdEIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO1NBQ3RCLENBQUM7SUFDSixDQUFDO3dHQXREVSwyQkFBMkI7NEZBQTNCLDJCQUEyQiwwSEE5QzVCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBK0JUOzs0RkFlVSwyQkFBMkI7a0JBaER2QyxTQUFTOytCQUNFLDZCQUE2QixZQUM3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQStCVCxtQkFZZ0IsdUJBQXVCLENBQUMsTUFBTSxjQUNuQyxLQUFLOzRGQU1SLE9BQU87c0JBQWYsS0FBSzs7QUFxRFIsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQWlCLFFBQVEsQ0FBQyxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICBUaGUgTUlUIExpY2Vuc2VcbiAgXG4gIENvcHlyaWdodCAoYykgMjAxNy0yMDE5IEVjbGlwc2VTb3VyY2UgTXVuaWNoXG4gIGh0dHBzOi8vZ2l0aHViLmNvbS9lY2xpcHNlc291cmNlL2pzb25mb3Jtc1xuICBcbiAgUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiAgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiAgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAgXG4gIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4gIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICBcbiAgVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuICBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiAgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbiAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuICBUSEUgU09GVFdBUkUuXG4qL1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIE9uSW5pdCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgdHlwZSB7IE1hdEF1dG9jb21wbGV0ZVNlbGVjdGVkRXZlbnQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9hdXRvY29tcGxldGUnO1xuaW1wb3J0IHsgSnNvbkZvcm1zQW5ndWxhclNlcnZpY2UsIEpzb25Gb3Jtc0NvbnRyb2wgfSBmcm9tICdAanNvbmZvcm1zL2FuZ3VsYXInO1xuaW1wb3J0IHtcbiAgQWN0aW9ucyxcbiAgY29tcG9zZVdpdGhVaSxcbiAgQ29udHJvbEVsZW1lbnQsXG4gIGlzRW51bUNvbnRyb2wsXG4gIE93blByb3BzT2ZDb250cm9sLFxuICBSYW5rZWRUZXN0ZXIsXG4gIHJhbmtXaXRoLFxufSBmcm9tICdAanNvbmZvcm1zL2NvcmUnO1xuaW1wb3J0IHR5cGUgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAsIHN0YXJ0V2l0aCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuLyoqXG4gKiBUbyB1c2UgdGhpcyBjb21wb25lbnQgeW91IHdpbGwgbmVlZCB0byBhZGQgeW91ciBvd24gdGVzdGVyOlxuICogPHByZT48Y29kZT5cbiAqIC4uLlxuICogZXhwb3J0IGNvbnN0IEF1dG9jb21wbGV0ZUNvbnRyb2xSZW5kZXJlclRlc3RlcjogUmFua2VkVGVzdGVyID0gcmFua1dpdGgoMiwgaXNFbnVtQ29udHJvbCk7XG4gKiAuLi5cbiAqIDwvY29kZT48L3ByZT5cbiAqIEFkZCB0aGUgdGVzdGVyIGFuZCByZW5kZXJlciB0byBKU09ORm9ybXMgcmVnaXN0cnk6XG4gKiA8cHJlPjxjb2RlPlxuICogLi4uXG4gKiB7IHRlc3RlcjogQXV0b2NvbXBsZXRlQ29udHJvbFJlbmRlcmVyVGVzdGVyLCByZW5kZXJlcjogQXV0b2NvbXBsZXRlQ29udHJvbFJlbmRlcmVyIH0sXG4gKiAuLi5cbiAqIDwvY29kZT48L3ByZT5cbiAqIEZ1cnRoZXJtb3JlIHlvdSBuZWVkIHRvIHVwZGF0ZSB5b3VyIG1vZHVsZS5cbiAqIDxwcmU+PGNvZGU+XG4gKiAuLi5cbiAqIGltcG9ydHM6IFtKc29uRm9ybXNBbmd1bGFyTWF0ZXJpYWxNb2R1bGUsIE1hdEF1dG9jb21wbGV0ZU1vZHVsZV0sXG4gKiBkZWNsYXJhdGlvbnM6IFtBdXRvY29tcGxldGVDb250cm9sUmVuZGVyZXJdXG4gKiAuLi5cbiAqIDwvY29kZT48L3ByZT5cbiAqXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ0F1dG9jb21wbGV0ZUNvbnRyb2xSZW5kZXJlcicsXG4gIHRlbXBsYXRlOiBgXG4gICAgPG1hdC1mb3JtLWZpZWxkIFtuZ1N0eWxlXT1cInsgZGlzcGxheTogaGlkZGVuID8gJ25vbmUnIDogJycgfVwiPlxuICAgICAgPG1hdC1sYWJlbD57eyBsYWJlbCB9fTwvbWF0LWxhYmVsPlxuICAgICAgPGlucHV0XG4gICAgICAgIG1hdElucHV0XG4gICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgKGNoYW5nZSk9XCJvbkNoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgW2lkXT1cImlkXCJcbiAgICAgICAgW2Zvcm1Db250cm9sXT1cImZvcm1cIlxuICAgICAgICBbbWF0QXV0b2NvbXBsZXRlXT1cImF1dG9cIlxuICAgICAgICAoa2V5ZG93bik9XCJ1cGRhdGVGaWx0ZXIoJGV2ZW50KVwiXG4gICAgICAgIChmb2N1cyk9XCJmb2N1c2VkID0gdHJ1ZVwiXG4gICAgICAgIChmb2N1c291dCk9XCJmb2N1c2VkID0gZmFsc2VcIlxuICAgICAgLz5cbiAgICAgIDxtYXQtYXV0b2NvbXBsZXRlXG4gICAgICAgIGF1dG9BY3RpdmVGaXJzdE9wdGlvblxuICAgICAgICAjYXV0bz1cIm1hdEF1dG9jb21wbGV0ZVwiXG4gICAgICAgIChvcHRpb25TZWxlY3RlZCk9XCJvblNlbGVjdCgkZXZlbnQpXCJcbiAgICAgID5cbiAgICAgICAgPG1hdC1vcHRpb25cbiAgICAgICAgICAqbmdGb3I9XCJsZXQgb3B0aW9uIG9mIGZpbHRlcmVkT3B0aW9ucyB8IGFzeW5jXCJcbiAgICAgICAgICBbdmFsdWVdPVwib3B0aW9uXCJcbiAgICAgICAgPlxuICAgICAgICAgIHt7IG9wdGlvbiB9fVxuICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICA8L21hdC1hdXRvY29tcGxldGU+XG4gICAgICA8bWF0LWhpbnQgKm5nSWY9XCJzaG91bGRTaG93VW5mb2N1c2VkRGVzY3JpcHRpb24oKSB8fCBmb2N1c2VkXCI+e3tcbiAgICAgICAgZGVzY3JpcHRpb25cbiAgICAgIH19PC9tYXQtaGludD5cbiAgICAgIDxtYXQtZXJyb3I+e3sgZXJyb3IgfX08L21hdC1lcnJvcj5cbiAgICA8L21hdC1mb3JtLWZpZWxkPlxuICBgLFxuICBzdHlsZXM6IFtcbiAgICBgXG4gICAgICA6aG9zdCB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gICAgICB9XG4gICAgICBtYXQtZm9ybS1maWVsZCB7XG4gICAgICAgIGZsZXg6IDEgMSBhdXRvO1xuICAgICAgfVxuICAgIGAsXG4gIF0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzdGFuZGFsb25lOiBmYWxzZSxcbn0pXG5leHBvcnQgY2xhc3MgQXV0b2NvbXBsZXRlQ29udHJvbFJlbmRlcmVyXG4gIGV4dGVuZHMgSnNvbkZvcm1zQ29udHJvbFxuICBpbXBsZW1lbnRzIE9uSW5pdFxue1xuICBASW5wdXQoKSBvcHRpb25zOiBzdHJpbmdbXTtcbiAgZmlsdGVyZWRPcHRpb25zOiBPYnNlcnZhYmxlPHN0cmluZ1tdPjtcbiAgc2hvdWxkRmlsdGVyOiBib29sZWFuO1xuICBmb2N1c2VkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoanNvbmZvcm1zU2VydmljZTogSnNvbkZvcm1zQW5ndWxhclNlcnZpY2UpIHtcbiAgICBzdXBlcihqc29uZm9ybXNTZXJ2aWNlKTtcbiAgfVxuICBnZXRFdmVudFZhbHVlID0gKGV2ZW50OiBhbnkpID0+IGV2ZW50LnRhcmdldC52YWx1ZTtcblxuICBuZ09uSW5pdCgpIHtcbiAgICBzdXBlci5uZ09uSW5pdCgpO1xuICAgIHRoaXMuc2hvdWxkRmlsdGVyID0gZmFsc2U7XG4gICAgdGhpcy5maWx0ZXJlZE9wdGlvbnMgPSB0aGlzLmZvcm0udmFsdWVDaGFuZ2VzLnBpcGUoXG4gICAgICBzdGFydFdpdGgoJycpLFxuICAgICAgbWFwKCh2YWwpID0+IHRoaXMuZmlsdGVyKHZhbCkpXG4gICAgKTtcbiAgfVxuXG4gIHVwZGF0ZUZpbHRlcihldmVudDogYW55KSB7XG4gICAgLy8gRU5URVJcbiAgICBpZiAoZXZlbnQua2V5Q29kZSA9PT0gMTMpIHtcbiAgICAgIHRoaXMuc2hvdWxkRmlsdGVyID0gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2hvdWxkRmlsdGVyID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBvblNlbGVjdChldjogTWF0QXV0b2NvbXBsZXRlU2VsZWN0ZWRFdmVudCkge1xuICAgIGNvbnN0IHBhdGggPSBjb21wb3NlV2l0aFVpKHRoaXMudWlzY2hlbWEgYXMgQ29udHJvbEVsZW1lbnQsIHRoaXMucGF0aCk7XG4gICAgdGhpcy5zaG91bGRGaWx0ZXIgPSBmYWxzZTtcbiAgICB0aGlzLmpzb25Gb3Jtc1NlcnZpY2UudXBkYXRlQ29yZShcbiAgICAgIEFjdGlvbnMudXBkYXRlKHBhdGgsICgpID0+IGV2Lm9wdGlvbi52YWx1ZSlcbiAgICApO1xuICAgIHRoaXMudHJpZ2dlclZhbGlkYXRpb24oKTtcbiAgfVxuXG4gIGZpbHRlcih2YWw6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gKHRoaXMub3B0aW9ucyB8fCB0aGlzLnNjb3BlZFNjaGVtYS5lbnVtIHx8IFtdKS5maWx0ZXIoXG4gICAgICAob3B0aW9uKSA9PlxuICAgICAgICAhdGhpcy5zaG91bGRGaWx0ZXIgfHxcbiAgICAgICAgIXZhbCB8fFxuICAgICAgICBvcHRpb24udG9Mb3dlckNhc2UoKS5pbmRleE9mKHZhbC50b0xvd2VyQ2FzZSgpKSA9PT0gMFxuICAgICk7XG4gIH1cbiAgcHJvdGVjdGVkIGdldE93blByb3BzKCk6IE93blByb3BzT2ZBdXRvQ29tcGxldGUge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5zdXBlci5nZXRPd25Qcm9wcygpLFxuICAgICAgb3B0aW9uczogdGhpcy5vcHRpb25zLFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGVudW1Db250cm9sVGVzdGVyOiBSYW5rZWRUZXN0ZXIgPSByYW5rV2l0aCgyLCBpc0VudW1Db250cm9sKTtcblxuaW50ZXJmYWNlIE93blByb3BzT2ZBdXRvQ29tcGxldGUgZXh0ZW5kcyBPd25Qcm9wc09mQ29udHJvbCB7XG4gIG9wdGlvbnM6IHN0cmluZ1tdO1xufVxuIl19