@myrmidon/gve-core 0.0.5 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +2 -0
  2. package/fesm2022/myrmidon-gve-core.mjs +370 -259
  3. package/fesm2022/myrmidon-gve-core.mjs.map +1 -1
  4. package/lib/components/batch-operation-editor/batch-operation-editor.component.d.ts +46 -0
  5. package/lib/components/chain-result-view/chain-result-view.component.d.ts +4 -1
  6. package/lib/components/feature-editor/feature-editor.component.d.ts +1 -1
  7. package/lib/components/feature-set-editor/feature-set-editor.component.d.ts +1 -1
  8. package/lib/components/snapshot-editor/snapshot-editor.component.d.ts +11 -9
  9. package/lib/components/steps-map/steps-map.component.d.ts +2 -0
  10. package/lib/models.d.ts +8 -0
  11. package/lib/services/gve-api.service.d.ts +33 -0
  12. package/package.json +10 -12
  13. package/public-api.d.ts +1 -0
  14. package/esm2022/lib/components/animation-timeline/animation-timeline.component.mjs +0 -207
  15. package/esm2022/lib/components/animation-timeline-set/animation-timeline-set.component.mjs +0 -154
  16. package/esm2022/lib/components/animation-tween/animation-tween.component.mjs +0 -184
  17. package/esm2022/lib/components/base-text-char/base-text-char.component.mjs +0 -46
  18. package/esm2022/lib/components/base-text-editor/base-text-editor.component.mjs +0 -115
  19. package/esm2022/lib/components/base-text-view/base-text-view.component.mjs +0 -159
  20. package/esm2022/lib/components/chain-operation-editor/chain-operation-editor.component.mjs +0 -570
  21. package/esm2022/lib/components/chain-result-view/chain-result-view.component.mjs +0 -222
  22. package/esm2022/lib/components/feature-editor/feature-editor.component.mjs +0 -200
  23. package/esm2022/lib/components/feature-set-editor/feature-set-editor.component.mjs +0 -175
  24. package/esm2022/lib/components/feature-set-view/feature-set-view.component.mjs +0 -100
  25. package/esm2022/lib/components/ln-heights-editor/ln-heights-editor.component.mjs +0 -126
  26. package/esm2022/lib/components/operation-source-editor/operation-source-editor.component.mjs +0 -131
  27. package/esm2022/lib/components/simple-tree/simple-tree.component.mjs +0 -72
  28. package/esm2022/lib/components/snapshot-editor/snapshot-editor.component.mjs +0 -863
  29. package/esm2022/lib/components/steps-map/steps-map.component.mjs +0 -77
  30. package/esm2022/lib/models.mjs +0 -2
  31. package/esm2022/lib/services/gve-api.service.mjs +0 -65
  32. package/esm2022/lib/services/settings.service.mjs +0 -87
  33. package/esm2022/lib/validators/svg-validators.mjs +0 -34
  34. package/esm2022/myrmidon-gve-core.mjs +0 -5
  35. package/esm2022/public-api.mjs +0 -22
@@ -1,175 +0,0 @@
1
- import { CommonModule } from '@angular/common';
2
- import { Component, EventEmitter, Input, Output, } from '@angular/core';
3
- import { ReactiveFormsModule } from '@angular/forms';
4
- import { MatButtonModule } from '@angular/material/button';
5
- import { MatExpansionModule } from '@angular/material/expansion';
6
- import { MatFormFieldModule } from '@angular/material/form-field';
7
- import { MatIconModule } from '@angular/material/icon';
8
- import { MatInputModule } from '@angular/material/input';
9
- import { MatSelectModule } from '@angular/material/select';
10
- import { MatTooltipModule } from '@angular/material/tooltip';
11
- import { debounceTime, distinctUntilChanged } from 'rxjs';
12
- import { NgToolsModule } from '@myrmidon/ng-tools';
13
- import { FeatureSetPolicy, } from '@myrmidon/gve-snapshot-view';
14
- import { FeatureEditorComponent, } from '../feature-editor/feature-editor.component';
15
- import * as i0 from "@angular/core";
16
- import * as i1 from "@angular/forms";
17
- import * as i2 from "@angular/material/button";
18
- import * as i3 from "@angular/material/expansion";
19
- import * as i4 from "@angular/material/form-field";
20
- import * as i5 from "@angular/material/icon";
21
- import * as i6 from "@angular/material/input";
22
- import * as i7 from "@angular/material/tooltip";
23
- import * as i8 from "@myrmidon/ng-tools";
24
- /**
25
- * 🔑 `gve-feature-set-editor`
26
- *
27
- * Component for editing a set of features. It shows a list of features,
28
- * allowing to edit each of them or adding new ones. Optionally you can
29
- * specify a list of feature names and values to use in the selection.
30
- * Used by base text editor and chain operation editor components.
31
- *
32
- * - ▶️ `featNames` (`LabeledId[]`): the list of feature names to display
33
- * in the _name_ selection. This is used when you have a closed list of features.
34
- * - ▶️ `featValues` (`FeatureMap`): the feature values map. When specified
35
- * and the user selects a feature name present in the map keys, the corresponding
36
- * values will be used to populate the value selection.
37
- * - ▶️ `filterThreshold` (`number`): the threshold at which the features filter
38
- * should become visible. If set to 0, the filter is always visible; if set to -1,
39
- * it is always invisible; otherwise, it gets visible when the number of features
40
- * is greater than the threshold. Default is 5.
41
- * - ▶️ `features` (`Feature[]`): the features to edit.
42
- * - ▶️ `isVar`: true if the feature is a variant operation feature, which
43
- * has additional properties like negation, global, and short-lived.
44
- * - 🔥 `featuresChange` (`Feature[]`): emitted when features have changed.
45
- */
46
- export class FeatureSetEditorComponent {
47
- /**
48
- * The features to edit.
49
- */
50
- get features() {
51
- return this._features;
52
- }
53
- set features(value) {
54
- if (this._features === value) {
55
- return;
56
- }
57
- this._features = value;
58
- this.applyFeatureFilter(this.filter.value);
59
- }
60
- constructor(formBuilder) {
61
- this.POLICIES = ['M', 'S', 'SF'];
62
- /**
63
- * True if the features are variable features.
64
- */
65
- this.isVar = false;
66
- /**
67
- * The threshold at which the features filter should become visible.
68
- * If set to 0, the filter is always visible; if set to -1, it is always
69
- * invisible; otherwise, it gets visible when the number of features
70
- * is greater than the threshold. Default is 5.
71
- */
72
- this.filterThreshold = 5;
73
- /**
74
- * Emitted when the features change.
75
- */
76
- this.featuresChange = new EventEmitter();
77
- this._features = [];
78
- this.filteredFeatures = [];
79
- this.filter = formBuilder.control(null);
80
- this._editedFeatureIndex = -1;
81
- }
82
- applyFeatureFilter(name) {
83
- this.filteredFeatures = this.features.filter((feature) => {
84
- return !name || feature.name.toLowerCase().includes(name.toLowerCase());
85
- });
86
- }
87
- ngOnInit() {
88
- this._sub = this.filter.valueChanges
89
- .pipe(distinctUntilChanged(), debounceTime(300))
90
- .subscribe((value) => {
91
- this.applyFeatureFilter(value);
92
- });
93
- }
94
- ngOnDestroy() {
95
- this._sub?.unsubscribe();
96
- }
97
- addFeature() {
98
- this.editedFeature = {
99
- name: '',
100
- value: '',
101
- setPolicy: FeatureSetPolicy.multiple,
102
- };
103
- this._editedFeatureIndex = -1;
104
- }
105
- editFeature(feature) {
106
- this.editedFeature = feature;
107
- this._editedFeatureIndex = this.features.indexOf(feature);
108
- }
109
- deleteFeature(feature) {
110
- const index = this.features.indexOf(feature);
111
- if (index < 0) {
112
- return;
113
- }
114
- const features = [...this.features];
115
- features.splice(index, 1);
116
- this.features = features;
117
- this.featuresChange.emit(this.features);
118
- }
119
- onFeatureChange(feature) {
120
- const features = [...this.features];
121
- for (let i = features.length - 1; i >= 0; i--) {
122
- if (features[i].name === feature.name) {
123
- if (feature.setPolicy === FeatureSetPolicy.single ||
124
- features[i].setPolicy === FeatureSetPolicy.single) {
125
- features.splice(i, 1);
126
- }
127
- }
128
- }
129
- if (this._editedFeatureIndex === -1) {
130
- features.push(feature);
131
- }
132
- else {
133
- features.splice(this._editedFeatureIndex, 1, feature);
134
- }
135
- this.features = features;
136
- this.editedFeature = undefined;
137
- this._editedFeatureIndex = -1;
138
- this.featuresChange.emit(this.features);
139
- }
140
- onFeatureCancel() {
141
- this.editedFeature = undefined;
142
- this._editedFeatureIndex = -1;
143
- }
144
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: FeatureSetEditorComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
145
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", type: FeatureSetEditorComponent, isStandalone: true, selector: "gve-feature-set-editor", inputs: { isVar: "isVar", featNames: "featNames", featValues: "featValues", filterThreshold: "filterThreshold", features: "features" }, outputs: { featuresChange: "featuresChange" }, ngImport: i0, template: "<div>\r\n <div class=\"form-row\">\r\n <!-- filter -->\r\n @if (filterThreshold === 0 || features.length > filterThreshold) {\r\n <mat-form-field>\r\n <input matInput placeholder=\"filter\" [formControl]=\"filter\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n (click)=\"filter.reset()\"\r\n [disabled]=\"!filter.value\"\r\n [attr.aria-label]=\"'Reset filter'\"\r\n >\r\n <mat-icon color=\"warn\" class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n\r\n <!-- add feature button -->\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Add a new feature\"\r\n (click)=\"addFeature()\"\r\n [class.in-row-button]=\"\r\n filterThreshold === 0 || features.length > filterThreshold\r\n \"\r\n >\r\n <mat-icon>add</mat-icon>\r\n feature\r\n </button>\r\n </div>\r\n\r\n <!-- list -->\r\n @if (features.length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>feature</th>\r\n <th>value</th>\r\n <th>policy</th>\r\n @if (isVar) {\r\n <th>negated</th>\r\n <th>global</th>\r\n <th>short-lived</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (feature of filteredFeatures; track feature) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Edit this feature\"\r\n (click)=\"editFeature(feature)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Delete this feature\"\r\n (click)=\"deleteFeature(feature)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n @if (featNames?.length) {\r\n <span>{{\r\n feature.name | flatLookup : featNames : \"id\" : \"label\"\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.name }}</span>\r\n }\r\n </td>\r\n <td>\r\n @if (featValues) {\r\n <span>{{\r\n feature.value | flatLookup : featValues[feature.name]\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.value }}</span>\r\n }\r\n </td>\r\n <td>\r\n <span>{{ POLICIES[feature.setPolicy] }}</span>\r\n </td>\r\n @if (isVar) {\r\n <td>\r\n <span>{{ $any(feature).isNegated ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n <td>\r\n <span>{{ $any(feature).isGlobal ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n <td>\r\n <span>{{ $any(feature).isShortLived ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- editor -->\r\n <mat-expansion-panel [disabled]=\"!editedFeature\" [expanded]=\"editedFeature\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>\r\n <span>{{ editedFeature?.name || \"feature\" }}</span>\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-feature-editor\r\n [isVar]=\"isVar\"\r\n [featNames]=\"featNames\"\r\n [featValues]=\"featValues\"\r\n [feature]=\"editedFeature\"\r\n (featureChange)=\"onFeatureChange($event)\"\r\n (featureCancel)=\"onFeatureCancel()\"\r\n />\r\n </mat-expansion-panel>\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.in-row-button{margin-top:-16px}table{width:100%;border-collapse:collapse;margin-top:8px}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.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: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: NgToolsModule }, { kind: "pipe", type: i8.FlatLookupPipe, name: "flatLookup" }, { kind: "component", type: FeatureEditorComponent, selector: "gve-feature-editor", inputs: ["featNames", "featValues", "feature", "isVar"], outputs: ["featureCancel", "featureChange"] }] }); }
146
- }
147
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: FeatureSetEditorComponent, decorators: [{
148
- type: Component,
149
- args: [{ selector: 'gve-feature-set-editor', standalone: true, imports: [
150
- CommonModule,
151
- ReactiveFormsModule,
152
- MatButtonModule,
153
- MatExpansionModule,
154
- MatFormFieldModule,
155
- MatIconModule,
156
- MatInputModule,
157
- MatSelectModule,
158
- MatTooltipModule,
159
- NgToolsModule,
160
- FeatureEditorComponent,
161
- ], template: "<div>\r\n <div class=\"form-row\">\r\n <!-- filter -->\r\n @if (filterThreshold === 0 || features.length > filterThreshold) {\r\n <mat-form-field>\r\n <input matInput placeholder=\"filter\" [formControl]=\"filter\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n (click)=\"filter.reset()\"\r\n [disabled]=\"!filter.value\"\r\n [attr.aria-label]=\"'Reset filter'\"\r\n >\r\n <mat-icon color=\"warn\" class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n\r\n <!-- add feature button -->\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Add a new feature\"\r\n (click)=\"addFeature()\"\r\n [class.in-row-button]=\"\r\n filterThreshold === 0 || features.length > filterThreshold\r\n \"\r\n >\r\n <mat-icon>add</mat-icon>\r\n feature\r\n </button>\r\n </div>\r\n\r\n <!-- list -->\r\n @if (features.length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>feature</th>\r\n <th>value</th>\r\n <th>policy</th>\r\n @if (isVar) {\r\n <th>negated</th>\r\n <th>global</th>\r\n <th>short-lived</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (feature of filteredFeatures; track feature) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Edit this feature\"\r\n (click)=\"editFeature(feature)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Delete this feature\"\r\n (click)=\"deleteFeature(feature)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n @if (featNames?.length) {\r\n <span>{{\r\n feature.name | flatLookup : featNames : \"id\" : \"label\"\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.name }}</span>\r\n }\r\n </td>\r\n <td>\r\n @if (featValues) {\r\n <span>{{\r\n feature.value | flatLookup : featValues[feature.name]\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.value }}</span>\r\n }\r\n </td>\r\n <td>\r\n <span>{{ POLICIES[feature.setPolicy] }}</span>\r\n </td>\r\n @if (isVar) {\r\n <td>\r\n <span>{{ $any(feature).isNegated ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n <td>\r\n <span>{{ $any(feature).isGlobal ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n <td>\r\n <span>{{ $any(feature).isShortLived ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- editor -->\r\n <mat-expansion-panel [disabled]=\"!editedFeature\" [expanded]=\"editedFeature\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>\r\n <span>{{ editedFeature?.name || \"feature\" }}</span>\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-feature-editor\r\n [isVar]=\"isVar\"\r\n [featNames]=\"featNames\"\r\n [featValues]=\"featValues\"\r\n [feature]=\"editedFeature\"\r\n (featureChange)=\"onFeatureChange($event)\"\r\n (featureCancel)=\"onFeatureCancel()\"\r\n />\r\n </mat-expansion-panel>\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.in-row-button{margin-top:-16px}table{width:100%;border-collapse:collapse;margin-top:8px}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}\n"] }]
162
- }], ctorParameters: () => [{ type: i1.FormBuilder }], propDecorators: { isVar: [{
163
- type: Input
164
- }], featNames: [{
165
- type: Input
166
- }], featValues: [{
167
- type: Input
168
- }], filterThreshold: [{
169
- type: Input
170
- }], features: [{
171
- type: Input
172
- }], featuresChange: [{
173
- type: Output
174
- }] } });
175
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmVhdHVyZS1zZXQtZWRpdG9yLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL215cm1pZG9uL2d2ZS1jb3JlL3NyYy9saWIvY29tcG9uZW50cy9mZWF0dXJlLXNldC1lZGl0b3IvZmVhdHVyZS1zZXQtZWRpdG9yLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL215cm1pZG9uL2d2ZS1jb3JlL3NyYy9saWIvY29tcG9uZW50cy9mZWF0dXJlLXNldC1lZGl0b3IvZmVhdHVyZS1zZXQtZWRpdG9yLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQ0wsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBR0wsTUFBTSxHQUNQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBNEIsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUvRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDakUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDbEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFN0QsT0FBTyxFQUFnQixZQUFZLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFeEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG9C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O1FBQ3pCLElBQUksQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDO1FBQy9CLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM5QixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVNLGVBQWU7UUFDcEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxTQUFTLENBQUM7UUFDL0IsSUFBSSxDQUFDLG1CQUFtQixHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7OEdBL0lVLHlCQUF5QjtrR0FBekIseUJBQXlCLHlRQzNFdEMsNnlIQW9JQSxvY0R4RUksWUFBWSw4QkFDWixtQkFBbUIseWtCQUNuQixlQUFlLHdVQUNmLGtCQUFrQix5ZEFDbEIsa0JBQWtCLDBXQUNsQixhQUFhLG1MQUNiLGNBQWMsMFdBQ2QsZUFBZSw4QkFDZixnQkFBZ0IsNFRBQ2hCLGFBQWEsOEZBQ2Isc0JBQXNCOzsyRkFLYix5QkFBeUI7a0JBbkJyQyxTQUFTOytCQUNFLHdCQUF3QixjQUN0QixJQUFJLFdBQ1A7d0JBQ1AsWUFBWTt3QkFDWixtQkFBbUI7d0JBQ25CLGVBQWU7d0JBQ2Ysa0JBQWtCO3dCQUNsQixrQkFBa0I7d0JBQ2xCLGFBQWE7d0JBQ2IsY0FBYzt3QkFDZCxlQUFlO3dCQUNmLGdCQUFnQjt3QkFDaEIsYUFBYTt3QkFDYixzQkFBc0I7cUJBQ3ZCO2dGQWVNLEtBQUs7c0JBRFgsS0FBSztnQkFRQyxTQUFTO3NCQURmLEtBQUs7Z0JBU0MsVUFBVTtzQkFEaEIsS0FBSztnQkFVQyxlQUFlO3NCQURyQixLQUFLO2dCQU9LLFFBQVE7c0JBRGxCLEtBQUs7Z0JBZ0JDLGNBQWM7c0JBRHBCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQge1xyXG4gIENvbXBvbmVudCxcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgSW5wdXQsXHJcbiAgT25EZXN0cm95LFxyXG4gIE9uSW5pdCxcclxuICBPdXRwdXQsXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEZvcm1CdWlsZGVyLCBGb3JtQ29udHJvbCwgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuXHJcbmltcG9ydCB7IE1hdEJ1dHRvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2J1dHRvbic7XHJcbmltcG9ydCB7IE1hdEV4cGFuc2lvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2V4cGFuc2lvbic7XHJcbmltcG9ydCB7IE1hdEZvcm1GaWVsZE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xyXG5pbXBvcnQgeyBNYXRJY29uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XHJcbmltcG9ydCB7IE1hdElucHV0TW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaW5wdXQnO1xyXG5pbXBvcnQgeyBNYXRTZWxlY3RNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zZWxlY3QnO1xyXG5pbXBvcnQgeyBNYXRUb29sdGlwTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCc7XHJcblxyXG5pbXBvcnQgeyBTdWJzY3JpcHRpb24sIGRlYm91bmNlVGltZSwgZGlzdGluY3RVbnRpbENoYW5nZWQgfSBmcm9tICdyeGpzJztcclxuXHJcbmltcG9ydCB7IE5nVG9vbHNNb2R1bGUgfSBmcm9tICdAbXlybWlkb24vbmctdG9vbHMnO1xyXG5cclxuaW1wb3J0IHtcclxuICBGZWF0dXJlU2V0UG9saWN5LFxyXG4gIExhYmVsZWRJZCxcclxuICBGZWF0dXJlLFxyXG4gIE9wZXJhdGlvbkZlYXR1cmUsXHJcbn0gZnJvbSAnQG15cm1pZG9uL2d2ZS1zbmFwc2hvdC12aWV3JztcclxuaW1wb3J0IHtcclxuICBGZWF0dXJlRWRpdG9yQ29tcG9uZW50LFxyXG4gIEZlYXR1cmVNYXAsXHJcbn0gZnJvbSAnLi4vZmVhdHVyZS1lZGl0b3IvZmVhdHVyZS1lZGl0b3IuY29tcG9uZW50JztcclxuXHJcbi8qKlxyXG4gKiDwn5SRIGBndmUtZmVhdHVyZS1zZXQtZWRpdG9yYFxyXG4gKlxyXG4gKiBDb21wb25lbnQgZm9yIGVkaXRpbmcgYSBzZXQgb2YgZmVhdHVyZXMuIEl0IHNob3dzIGEgbGlzdCBvZiBmZWF0dXJlcyxcclxuICogYWxsb3dpbmcgdG8gZWRpdCBlYWNoIG9mIHRoZW0gb3IgYWRkaW5nIG5ldyBvbmVzLiBPcHRpb25hbGx5IHlvdSBjYW5cclxuICogc3BlY2lmeSBhIGxpc3Qgb2YgZmVhdHVyZSBuYW1lcyBhbmQgdmFsdWVzIHRvIHVzZSBpbiB0aGUgc2VsZWN0aW9uLlxyXG4gKiBVc2VkIGJ5IGJhc2UgdGV4dCBlZGl0b3IgYW5kIGNoYWluIG9wZXJhdGlvbiBlZGl0b3IgY29tcG9uZW50cy5cclxuICpcclxuICogLSDilrbvuI8gYGZlYXROYW1lc2AgKGBMYWJlbGVkSWRbXWApOiB0aGUgbGlzdCBvZiBmZWF0dXJlIG5hbWVzIHRvIGRpc3BsYXlcclxuICogaW4gdGhlIF9uYW1lXyBzZWxlY3Rpb24uIFRoaXMgaXMgdXNlZCB3aGVuIHlvdSBoYXZlIGEgY2xvc2VkIGxpc3Qgb2YgZmVhdHVyZXMuXHJcbiAqIC0g4pa277iPIGBmZWF0VmFsdWVzYCAoYEZlYXR1cmVNYXBgKTogdGhlIGZlYXR1cmUgdmFsdWVzIG1hcC4gV2hlbiBzcGVjaWZpZWRcclxuICogYW5kIHRoZSB1c2VyIHNlbGVjdHMgYSBmZWF0dXJlIG5hbWUgcHJlc2VudCBpbiB0aGUgbWFwIGtleXMsIHRoZSBjb3JyZXNwb25kaW5nXHJcbiAqIHZhbHVlcyB3aWxsIGJlIHVzZWQgdG8gcG9wdWxhdGUgdGhlIHZhbHVlIHNlbGVjdGlvbi5cclxuICogLSDilrbvuI8gYGZpbHRlclRocmVzaG9sZGAgKGBudW1iZXJgKTogdGhlIHRocmVzaG9sZCBhdCB3aGljaCB0aGUgZmVhdHVyZXMgZmlsdGVyXHJcbiAqIHNob3VsZCBiZWNvbWUgdmlzaWJsZS4gSWYgc2V0IHRvIDAsIHRoZSBmaWx0ZXIgaXMgYWx3YXlzIHZpc2libGU7IGlmIHNldCB0byAtMSxcclxuICogaXQgaXMgYWx3YXlzIGludmlzaWJsZTsgb3RoZXJ3aXNlLCBpdCBnZXRzIHZpc2libGUgd2hlbiB0aGUgbnVtYmVyIG9mIGZlYXR1cmVzXHJcbiAqIGlzIGdyZWF0ZXIgdGhhbiB0aGUgdGhyZXNob2xkLiBEZWZhdWx0IGlzIDUuXHJcbiAqIC0g4pa277iPIGBmZWF0dXJlc2AgKGBGZWF0dXJlW11gKTogdGhlIGZlYXR1cmVzIHRvIGVkaXQuXHJcbiAqIC0g4pa277iPIGBpc1ZhcmA6IHRydWUgaWYgdGhlIGZlYXR1cmUgaXMgYSB2YXJpYW50IG9wZXJhdGlvbiBmZWF0dXJlLCB3aGljaFxyXG4gKiBoYXMgYWRkaXRpb25hbCBwcm9wZXJ0aWVzIGxpa2UgbmVnYXRpb24sIGdsb2JhbCwgYW5kIHNob3J0LWxpdmVkLlxyXG4gKiAtIPCflKUgYGZlYXR1cmVzQ2hhbmdlYCAoYEZlYXR1cmVbXWApOiBlbWl0dGVkIHdoZW4gZmVhdHVyZXMgaGF2ZSBjaGFuZ2VkLlxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdndmUtZmVhdHVyZS1zZXQtZWRpdG9yJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtcclxuICAgIENvbW1vbk1vZHVsZSxcclxuICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXHJcbiAgICBNYXRCdXR0b25Nb2R1bGUsXHJcbiAgICBNYXRFeHBhbnNpb25Nb2R1bGUsXHJcbiAgICBNYXRGb3JtRmllbGRNb2R1bGUsXHJcbiAgICBNYXRJY29uTW9kdWxlLFxyXG4gICAgTWF0SW5wdXRNb2R1bGUsXHJcbiAgICBNYXRTZWxlY3RNb2R1bGUsXHJcbiAgICBNYXRUb29sdGlwTW9kdWxlLFxyXG4gICAgTmdUb29sc01vZHVsZSxcclxuICAgIEZlYXR1cmVFZGl0b3JDb21wb25lbnQsXHJcbiAgXSxcclxuICB0ZW1wbGF0ZVVybDogJy4vZmVhdHVyZS1zZXQtZWRpdG9yLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybDogJy4vZmVhdHVyZS1zZXQtZWRpdG9yLmNvbXBvbmVudC5jc3MnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgRmVhdHVyZVNldEVkaXRvckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcclxuICBwcml2YXRlIF9zdWI/OiBTdWJzY3JpcHRpb247XHJcbiAgcHJpdmF0ZSBfZmVhdHVyZXM6IEZlYXR1cmVbXSB8IE9wZXJhdGlvbkZlYXR1cmVbXTtcclxuICBwcml2YXRlIF9lZGl0ZWRGZWF0dXJlSW5kZXg6IG51bWJlcjtcclxuXHJcbiAgcHVibGljIFBPTElDSUVTID0gWydNJywgJ1MnLCAnU0YnXTtcclxuXHJcbiAgLyoqXHJcbiAgICogVHJ1ZSBpZiB0aGUgZmVhdHVyZXMgYXJlIHZhcmlhYmxlIGZlYXR1cmVzLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGlzVmFyID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFRoZSBsaXN0IG9mIGZlYXR1cmUgbmFtZXMgdG8gZGlzcGxheSBpbiB0aGUgbmFtZSBzZWxlY3Rpb24uXHJcbiAgICogVGhpcyBpcyB1c2VkIHdoZW4geW91IGhhdmUgYSBjbG9zZWQgbGlzdCBvZiBmZWF0dXJlcy5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBmZWF0TmFtZXM6IExhYmVsZWRJZFtdIHwgdW5kZWZpbmVkO1xyXG5cclxuICAvKipcclxuICAgKiBUaGUgZmVhdHVyZSB2YWx1ZXMgbWFwLiBXaGVuIHNwZWNpZmllZCBhbmQgdGhlIHVzZXIgc2VsZWN0cyBhIGZlYXR1cmVcclxuICAgKiBuYW1lIHByZXNlbnQgaW4gdGhlIG1hcCBrZXlzLCB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZXMgd2lsbCBiZSB1c2VkXHJcbiAgICogdG8gcG9wdWxhdGUgdGhlIHZhbHVlIHNlbGVjdGlvbi5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBmZWF0VmFsdWVzOiBGZWF0dXJlTWFwIHwgdW5kZWZpbmVkO1xyXG5cclxuICAvKipcclxuICAgKiBUaGUgdGhyZXNob2xkIGF0IHdoaWNoIHRoZSBmZWF0dXJlcyBmaWx0ZXIgc2hvdWxkIGJlY29tZSB2aXNpYmxlLlxyXG4gICAqIElmIHNldCB0byAwLCB0aGUgZmlsdGVyIGlzIGFsd2F5cyB2aXNpYmxlOyBpZiBzZXQgdG8gLTEsIGl0IGlzIGFsd2F5c1xyXG4gICAqIGludmlzaWJsZTsgb3RoZXJ3aXNlLCBpdCBnZXRzIHZpc2libGUgd2hlbiB0aGUgbnVtYmVyIG9mIGZlYXR1cmVzXHJcbiAgICogaXMgZ3JlYXRlciB0aGFuIHRoZSB0aHJlc2hvbGQuIERlZmF1bHQgaXMgNS5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBmaWx0ZXJUaHJlc2hvbGQgPSA1O1xyXG5cclxuICAvKipcclxuICAgKiBUaGUgZmVhdHVyZXMgdG8gZWRpdC5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBnZXQgZmVhdHVyZXMoKTogRmVhdHVyZVtdIHwgT3BlcmF0aW9uRmVhdHVyZVtdIHtcclxuICAgIHJldHVybiB0aGlzLl9mZWF0dXJlcztcclxuICB9XHJcbiAgcHVibGljIHNldCBmZWF0dXJlcyh2YWx1ZTogRmVhdHVyZVtdIHwgT3BlcmF0aW9uRmVhdHVyZVtdKSB7XHJcbiAgICBpZiAodGhpcy5fZmVhdHVyZXMgPT09IHZhbHVlKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMuX2ZlYXR1cmVzID0gdmFsdWU7XHJcbiAgICB0aGlzLmFwcGx5RmVhdHVyZUZpbHRlcih0aGlzLmZpbHRlci52YWx1ZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFbWl0dGVkIHdoZW4gdGhlIGZlYXR1cmVzIGNoYW5nZS5cclxuICAgKi9cclxuICBAT3V0cHV0KClcclxuICBwdWJsaWMgZmVhdHVyZXNDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPEZlYXR1cmVbXSB8IE9wZXJhdGlvbkZlYXR1cmVbXT4oKTtcclxuXHJcbiAgcHVibGljIGVkaXRlZEZlYXR1cmU/OiBGZWF0dXJlIHwgT3BlcmF0aW9uRmVhdHVyZTtcclxuXHJcbiAgLy8gZmlsdGVyXHJcbiAgcHVibGljIGZpbHRlcjogRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD47XHJcbiAgcHVibGljIGZpbHRlcmVkRmVhdHVyZXM6IEZlYXR1cmVbXSB8IE9wZXJhdGlvbkZlYXR1cmVbXTtcclxuXHJcbiAgY29uc3RydWN0b3IoZm9ybUJ1aWxkZXI6IEZvcm1CdWlsZGVyKSB7XHJcbiAgICB0aGlzLl9mZWF0dXJlcyA9IFtdO1xyXG4gICAgdGhpcy5maWx0ZXJlZEZlYXR1cmVzID0gW107XHJcbiAgICB0aGlzLmZpbHRlciA9IGZvcm1CdWlsZGVyLmNvbnRyb2w8c3RyaW5nIHwgbnVsbD4obnVsbCk7XHJcbiAgICB0aGlzLl9lZGl0ZWRGZWF0dXJlSW5kZXggPSAtMTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXBwbHlGZWF0dXJlRmlsdGVyKG5hbWU/OiBzdHJpbmcgfCBudWxsKTogdm9pZCB7XHJcbiAgICB0aGlzLmZpbHRlcmVkRmVhdHVyZXMgPSB0aGlzLmZlYXR1cmVzLmZpbHRlcigoZmVhdHVyZSkgPT4ge1xyXG4gICAgICByZXR1cm4gIW5hbWUgfHwgZmVhdHVyZS5uYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMobmFtZS50b0xvd2VyQ2FzZSgpKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5fc3ViID0gdGhpcy5maWx0ZXIudmFsdWVDaGFuZ2VzXHJcbiAgICAgIC5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksIGRlYm91bmNlVGltZSgzMDApKVxyXG4gICAgICAuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xyXG4gICAgICAgIHRoaXMuYXBwbHlGZWF0dXJlRmlsdGVyKHZhbHVlKTtcclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLl9zdWI/LnVuc3Vic2NyaWJlKCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYWRkRmVhdHVyZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuZWRpdGVkRmVhdHVyZSA9IHtcclxuICAgICAgbmFtZTogJycsXHJcbiAgICAgIHZhbHVlOiAnJyxcclxuICAgICAgc2V0UG9saWN5OiBGZWF0dXJlU2V0UG9saWN5Lm11bHRpcGxlLFxyXG4gICAgfTtcclxuICAgIHRoaXMuX2VkaXRlZEZlYXR1cmVJbmRleCA9IC0xO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGVkaXRGZWF0dXJlKGZlYXR1cmU6IEZlYXR1cmUgfCBPcGVyYXRpb25GZWF0dXJlKTogdm9pZCB7XHJcbiAgICB0aGlzLmVkaXRlZEZlYXR1cmUgPSBmZWF0dXJlO1xyXG4gICAgdGhpcy5fZWRpdGVkRmVhdHVyZUluZGV4ID0gdGhpcy5mZWF0dXJlcy5pbmRleE9mKGZlYXR1cmUpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGRlbGV0ZUZlYXR1cmUoZmVhdHVyZTogRmVhdHVyZSB8IE9wZXJhdGlvbkZlYXR1cmUpOiB2b2lkIHtcclxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5mZWF0dXJlcy5pbmRleE9mKGZlYXR1cmUpO1xyXG4gICAgaWYgKGluZGV4IDwgMCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBjb25zdCBmZWF0dXJlcyA9IFsuLi50aGlzLmZlYXR1cmVzXTtcclxuICAgIGZlYXR1cmVzLnNwbGljZShpbmRleCwgMSk7XHJcbiAgICB0aGlzLmZlYXR1cmVzID0gZmVhdHVyZXM7XHJcbiAgICB0aGlzLmZlYXR1cmVzQ2hhbmdlLmVtaXQodGhpcy5mZWF0dXJlcyk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25GZWF0dXJlQ2hhbmdlKGZlYXR1cmU6IEZlYXR1cmUgfCBPcGVyYXRpb25GZWF0dXJlKTogdm9pZCB7XHJcbiAgICBjb25zdCBmZWF0dXJlcyA9IFsuLi50aGlzLmZlYXR1cmVzXTtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gZmVhdHVyZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgaWYgKGZlYXR1cmVzW2ldLm5hbWUgPT09IGZlYXR1cmUubmFtZSkge1xyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgIGZlYXR1cmUuc2V0UG9saWN5ID09PSBGZWF0dXJlU2V0UG9saWN5LnNpbmdsZSB8fFxyXG4gICAgICAgICAgZmVhdHVyZXNbaV0uc2V0UG9saWN5ID09PSBGZWF0dXJlU2V0UG9saWN5LnNpbmdsZVxyXG4gICAgICAgICkge1xyXG4gICAgICAgICAgZmVhdHVyZXMuc3BsaWNlKGksIDEpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLl9lZGl0ZWRGZWF0dXJlSW5kZXggPT09IC0xKSB7XHJcbiAgICAgIGZlYXR1cmVzLnB1c2goZmVhdHVyZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBmZWF0dXJlcy5zcGxpY2UodGhpcy5fZWRpdGVkRmVhdHVyZUluZGV4LCAxLCBmZWF0dXJlKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmZlYXR1cmVzID0gZmVhdHVyZXM7XHJcbiAgICB0aGlzLmVkaXRlZEZlYXR1cmUgPSB1bmRlZmluZWQ7XHJcbiAgICB0aGlzLl9lZGl0ZWRGZWF0dXJlSW5kZXggPSAtMTtcclxuICAgIHRoaXMuZmVhdHVyZXNDaGFuZ2UuZW1pdCh0aGlzLmZlYXR1cmVzKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBvbkZlYXR1cmVDYW5jZWwoKTogdm9pZCB7XHJcbiAgICB0aGlzLmVkaXRlZEZlYXR1cmUgPSB1bmRlZmluZWQ7XHJcbiAgICB0aGlzLl9lZGl0ZWRGZWF0dXJlSW5kZXggPSAtMTtcclxuICB9XHJcbn1cclxuIiwiPGRpdj5cclxuICA8ZGl2IGNsYXNzPVwiZm9ybS1yb3dcIj5cclxuICAgIDwhLS0gZmlsdGVyIC0tPlxyXG4gICAgQGlmIChmaWx0ZXJUaHJlc2hvbGQgPT09IDAgfHwgZmVhdHVyZXMubGVuZ3RoID4gZmlsdGVyVGhyZXNob2xkKSB7XHJcbiAgICA8bWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgIDxpbnB1dCBtYXRJbnB1dCBwbGFjZWhvbGRlcj1cImZpbHRlclwiIFtmb3JtQ29udHJvbF09XCJmaWx0ZXJcIiAvPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgbWF0U3VmZml4XHJcbiAgICAgICAgKGNsaWNrKT1cImZpbHRlci5yZXNldCgpXCJcclxuICAgICAgICBbZGlzYWJsZWRdPVwiIWZpbHRlci52YWx1ZVwiXHJcbiAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInUmVzZXQgZmlsdGVyJ1wiXHJcbiAgICAgID5cclxuICAgICAgICA8bWF0LWljb24gY29sb3I9XCJ3YXJuXCIgY2xhc3M9XCJtYXQtd2FyblwiPmNhbmNlbDwvbWF0LWljb24+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgIH1cclxuXHJcbiAgICA8IS0tIGFkZCBmZWF0dXJlIGJ1dHRvbiAtLT5cclxuICAgIDxidXR0b25cclxuICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgIGNsYXNzPVwibWF0LXByaW1hcnlcIlxyXG4gICAgICBtYXQtZmxhdC1idXR0b25cclxuICAgICAgbWF0VG9vbHRpcD1cIkFkZCBhIG5ldyBmZWF0dXJlXCJcclxuICAgICAgKGNsaWNrKT1cImFkZEZlYXR1cmUoKVwiXHJcbiAgICAgIFtjbGFzcy5pbi1yb3ctYnV0dG9uXT1cIlxyXG4gICAgICAgIGZpbHRlclRocmVzaG9sZCA9PT0gMCB8fCBmZWF0dXJlcy5sZW5ndGggPiBmaWx0ZXJUaHJlc2hvbGRcclxuICAgICAgXCJcclxuICAgID5cclxuICAgICAgPG1hdC1pY29uPmFkZDwvbWF0LWljb24+XHJcbiAgICAgIGZlYXR1cmVcclxuICAgIDwvYnV0dG9uPlxyXG4gIDwvZGl2PlxyXG5cclxuICA8IS0tIGxpc3QgLS0+XHJcbiAgQGlmIChmZWF0dXJlcy5sZW5ndGgpIHtcclxuICA8dGFibGU+XHJcbiAgICA8dGhlYWQ+XHJcbiAgICAgIDx0cj5cclxuICAgICAgICA8dGg+PC90aD5cclxuICAgICAgICA8dGg+ZmVhdHVyZTwvdGg+XHJcbiAgICAgICAgPHRoPnZhbHVlPC90aD5cclxuICAgICAgICA8dGg+cG9saWN5PC90aD5cclxuICAgICAgICBAaWYgKGlzVmFyKSB7XHJcbiAgICAgICAgPHRoPm5lZ2F0ZWQ8L3RoPlxyXG4gICAgICAgIDx0aD5nbG9iYWw8L3RoPlxyXG4gICAgICAgIDx0aD5zaG9ydC1saXZlZDwvdGg+XHJcbiAgICAgICAgfVxyXG4gICAgICA8L3RyPlxyXG4gICAgPC90aGVhZD5cclxuICAgIDx0Ym9keT5cclxuICAgICAgQGZvciAoZmVhdHVyZSBvZiBmaWx0ZXJlZEZlYXR1cmVzOyB0cmFjayBmZWF0dXJlKSB7XHJcbiAgICAgIDx0cj5cclxuICAgICAgICA8dGQgY2xhc3M9XCJmaXQtd2lkdGhcIj5cclxuICAgICAgICAgIDwhLS0gZWRpdCAtLT5cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxyXG4gICAgICAgICAgICBtYXRUb29sdGlwPVwiRWRpdCB0aGlzIGZlYXR1cmVcIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwiZWRpdEZlYXR1cmUoZmVhdHVyZSlcIlxyXG4gICAgICAgICAgPlxyXG4gICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJtYXQtcHJpbWFyeVwiPmVkaXQ8L21hdC1pY29uPlxyXG4gICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICA8IS0tIGRlbGV0ZSAtLT5cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgIGNvbG9yPVwid2FyblwiXHJcbiAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxyXG4gICAgICAgICAgICBtYXRUb29sdGlwPVwiRGVsZXRlIHRoaXMgZmVhdHVyZVwiXHJcbiAgICAgICAgICAgIChjbGljayk9XCJkZWxldGVGZWF0dXJlKGZlYXR1cmUpXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWF0LXdhcm5cIj5kZWxldGU8L21hdC1pY29uPlxyXG4gICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgPC90ZD5cclxuICAgICAgICA8dGQ+XHJcbiAgICAgICAgICBAaWYgKGZlYXROYW1lcz8ubGVuZ3RoKSB7XHJcbiAgICAgICAgICA8c3Bhbj57e1xyXG4gICAgICAgICAgICBmZWF0dXJlLm5hbWUgfCBmbGF0TG9va3VwIDogZmVhdE5hbWVzIDogXCJpZFwiIDogXCJsYWJlbFwiXHJcbiAgICAgICAgICB9fTwvc3Bhbj5cclxuICAgICAgICAgIH0gQGVsc2Uge1xyXG4gICAgICAgICAgPHNwYW4+e3sgZmVhdHVyZS5uYW1lIH19PC9zcGFuPlxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIDwvdGQ+XHJcbiAgICAgICAgPHRkPlxyXG4gICAgICAgICAgQGlmIChmZWF0VmFsdWVzKSB7XHJcbiAgICAgICAgICA8c3Bhbj57e1xyXG4gICAgICAgICAgICBmZWF0dXJlLnZhbHVlIHwgZmxhdExvb2t1cCA6IGZlYXRWYWx1ZXNbZmVhdHVyZS5uYW1lXVxyXG4gICAgICAgICAgfX08L3NwYW4+XHJcbiAgICAgICAgICB9IEBlbHNlIHtcclxuICAgICAgICAgIDxzcGFuPnt7IGZlYXR1cmUudmFsdWUgfX08L3NwYW4+XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgPC90ZD5cclxuICAgICAgICA8dGQ+XHJcbiAgICAgICAgICA8c3Bhbj57eyBQT0xJQ0lFU1tmZWF0dXJlLnNldFBvbGljeV0gfX08L3NwYW4+XHJcbiAgICAgICAgPC90ZD5cclxuICAgICAgICBAaWYgKGlzVmFyKSB7XHJcbiAgICAgICAgPHRkPlxyXG4gICAgICAgICAgPHNwYW4+e3sgJGFueShmZWF0dXJlKS5pc05lZ2F0ZWQgPyBcInllc1wiIDogXCJub1wiIH19PC9zcGFuPlxyXG4gICAgICAgIDwvdGQ+XHJcbiAgICAgICAgPHRkPlxyXG4gICAgICAgICAgPHNwYW4+e3sgJGFueShmZWF0dXJlKS5pc0dsb2JhbCA/IFwieWVzXCIgOiBcIm5vXCIgfX08L3NwYW4+XHJcbiAgICAgICAgPC90ZD5cclxuICAgICAgICA8dGQ+XHJcbiAgICAgICAgICA8c3Bhbj57eyAkYW55KGZlYXR1cmUpLmlzU2hvcnRMaXZlZCA/IFwieWVzXCIgOiBcIm5vXCIgfX08L3NwYW4+XHJcbiAgICAgICAgPC90ZD5cclxuICAgICAgICB9XHJcbiAgICAgIDwvdHI+XHJcbiAgICAgIH1cclxuICAgIDwvdGJvZHk+XHJcbiAgPC90YWJsZT5cclxuICB9XHJcblxyXG4gIDwhLS0gZWRpdG9yIC0tPlxyXG4gIDxtYXQtZXhwYW5zaW9uLXBhbmVsIFtkaXNhYmxlZF09XCIhZWRpdGVkRmVhdHVyZVwiIFtleHBhbmRlZF09XCJlZGl0ZWRGZWF0dXJlXCI+XHJcbiAgICA8bWF0LWV4cGFuc2lvbi1wYW5lbC1oZWFkZXI+XHJcbiAgICAgIDxtYXQtcGFuZWwtdGl0bGU+XHJcbiAgICAgICAgPHNwYW4+e3sgZWRpdGVkRmVhdHVyZT8ubmFtZSB8fCBcImZlYXR1cmVcIiB9fTwvc3Bhbj5cclxuICAgICAgPC9tYXQtcGFuZWwtdGl0bGU+XHJcbiAgICA8L21hdC1leHBhbnNpb24tcGFuZWwtaGVhZGVyPlxyXG4gICAgPGd2ZS1mZWF0dXJlLWVkaXRvclxyXG4gICAgICBbaXNWYXJdPVwiaXNWYXJcIlxyXG4gICAgICBbZmVhdE5hbWVzXT1cImZlYXROYW1lc1wiXHJcbiAgICAgIFtmZWF0VmFsdWVzXT1cImZlYXRWYWx1ZXNcIlxyXG4gICAgICBbZmVhdHVyZV09XCJlZGl0ZWRGZWF0dXJlXCJcclxuICAgICAgKGZlYXR1cmVDaGFuZ2UpPVwib25GZWF0dXJlQ2hhbmdlKCRldmVudClcIlxyXG4gICAgICAoZmVhdHVyZUNhbmNlbCk9XCJvbkZlYXR1cmVDYW5jZWwoKVwiXHJcbiAgICAvPlxyXG4gIDwvbWF0LWV4cGFuc2lvbi1wYW5lbD5cclxuPC9kaXY+XHJcbiJdfQ==
@@ -1,100 +0,0 @@
1
- import { Component, Input } from '@angular/core';
2
- import { ReactiveFormsModule } from '@angular/forms';
3
- import { CommonModule } from '@angular/common';
4
- import { debounceTime, distinctUntilChanged } from 'rxjs';
5
- import { MatButtonModule } from '@angular/material/button';
6
- import { MatFormFieldModule } from '@angular/material/form-field';
7
- import { MatIconModule } from '@angular/material/icon';
8
- import { MatInputModule } from '@angular/material/input';
9
- import { NgToolsModule } from '@myrmidon/ng-tools';
10
- import * as i0 from "@angular/core";
11
- import * as i1 from "@angular/forms";
12
- import * as i2 from "@angular/material/button";
13
- import * as i3 from "@angular/material/form-field";
14
- import * as i4 from "@angular/material/icon";
15
- import * as i5 from "@angular/material/input";
16
- import * as i6 from "@myrmidon/ng-tools";
17
- /**
18
- * 🔑 `gve-feature-set-view`
19
- *
20
- * A component to display a list of features.
21
- * Used by the chain result view component.
22
- *
23
- * - ▶️ `features` (`Feature[]`): the features to display.
24
- * - ▶️ `featNames` (`LabeledId[]`): the list of feature names to display
25
- * in the _name_ selection. This is used when you have a closed list of features.
26
- * - ▶️ `featValues` (`FeatureMap`): the feature values map. When specified
27
- * and the user selects a feature name present in the map keys, the corresponding
28
- * values will be used to populate the value selection.
29
- * - ▶️ `filterThreshold` (`number`): the threshold at which the features filter
30
- * should become visible. If set to 0, the filter is always visible; if set to -1,
31
- * it is always invisible; otherwise, it gets visible when the number of features
32
- * is greater than the threshold. Default is 5.
33
- */
34
- export class FeatureSetViewComponent {
35
- /**
36
- * The features.
37
- */
38
- get features() {
39
- return this._features;
40
- }
41
- set features(value) {
42
- if (this._features === value) {
43
- return;
44
- }
45
- this._features = value || undefined;
46
- this.filter.reset();
47
- this.applyFeatureFilter();
48
- }
49
- constructor(formBuilder) {
50
- this._features = [];
51
- /**
52
- * The threshold at which the features filter should become visible.
53
- * If set to 0, the filter is always visible; if set to -1, it is always
54
- * invisible; otherwise, it gets visible when the number of features
55
- * is greater than the threshold. Default is 5.
56
- */
57
- this.filterThreshold = 5;
58
- this.filteredFeatures = [];
59
- this.filter = formBuilder.control(null);
60
- }
61
- applyFeatureFilter(name) {
62
- this.filteredFeatures = this._features.filter((feature) => {
63
- return !name || feature.name.toLowerCase().includes(name.toLowerCase());
64
- });
65
- }
66
- ngOnInit() {
67
- this._sub = this.filter.valueChanges
68
- .pipe(distinctUntilChanged(), debounceTime(300))
69
- .subscribe((value) => {
70
- this.applyFeatureFilter(value);
71
- });
72
- this.applyFeatureFilter();
73
- }
74
- ngOnDestroy() {
75
- this._sub?.unsubscribe();
76
- }
77
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: FeatureSetViewComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
78
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", type: FeatureSetViewComponent, isStandalone: true, selector: "gve-feature-set-view", inputs: { features: "features", featNames: "featNames", featValues: "featValues", filterThreshold: "filterThreshold" }, ngImport: i0, template: "<div>\r\n <!-- filter -->\r\n <div>\r\n @if (filterThreshold === 0 || features.length > filterThreshold) {\r\n <div class=\"form-row\">\r\n <mat-form-field id=\"filter\">\r\n <mat-label>filter</mat-label>\r\n <input matInput placeholder=\"filter\" [formControl]=\"filter\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n (click)=\"filter.reset()\"\r\n [disabled]=\"!filter.value\"\r\n [attr.aria-label]=\"'Reset filter'\"\r\n >\r\n <mat-icon color=\"warn\" class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n\r\n <span>{{ filteredFeatures.length }}</span>\r\n </div>\r\n }\r\n\r\n <!-- list -->\r\n @if (filteredFeatures.length) {\r\n <table>\r\n <tbody>\r\n @for (feature of filteredFeatures; track $index) {\r\n <tr>\r\n <th>\r\n @if (featNames?.length) {\r\n <span>{{\r\n feature.name | flatLookup : featNames : \"id\" : \"label\"\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.name }}</span>\r\n }\r\n </th>\r\n <td>\r\n @if (featValues) {\r\n <span>{{\r\n feature.value | flatLookup : featValues[feature.name]\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.value }}</span>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.in-row-button{margin-top:-16px}table{width:100%;border-collapse:collapse}th{text-align:left;background-color:#c8d9eb;color:#333;font-weight:400}th,td{border:1px solid silver;padding:4px}tr:nth-child(2n){background-color:#dfdfdf}#filter{width:7em}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatFormFieldModule }, { 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.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.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: "ngmodule", type: NgToolsModule }, { kind: "pipe", type: i6.FlatLookupPipe, name: "flatLookup" }] }); }
79
- }
80
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: FeatureSetViewComponent, decorators: [{
81
- type: Component,
82
- args: [{ selector: 'gve-feature-set-view', standalone: true, imports: [
83
- CommonModule,
84
- ReactiveFormsModule,
85
- MatButtonModule,
86
- MatFormFieldModule,
87
- MatIconModule,
88
- MatInputModule,
89
- NgToolsModule,
90
- ], template: "<div>\r\n <!-- filter -->\r\n <div>\r\n @if (filterThreshold === 0 || features.length > filterThreshold) {\r\n <div class=\"form-row\">\r\n <mat-form-field id=\"filter\">\r\n <mat-label>filter</mat-label>\r\n <input matInput placeholder=\"filter\" [formControl]=\"filter\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n (click)=\"filter.reset()\"\r\n [disabled]=\"!filter.value\"\r\n [attr.aria-label]=\"'Reset filter'\"\r\n >\r\n <mat-icon color=\"warn\" class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n\r\n <span>{{ filteredFeatures.length }}</span>\r\n </div>\r\n }\r\n\r\n <!-- list -->\r\n @if (filteredFeatures.length) {\r\n <table>\r\n <tbody>\r\n @for (feature of filteredFeatures; track $index) {\r\n <tr>\r\n <th>\r\n @if (featNames?.length) {\r\n <span>{{\r\n feature.name | flatLookup : featNames : \"id\" : \"label\"\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.name }}</span>\r\n }\r\n </th>\r\n <td>\r\n @if (featValues) {\r\n <span>{{\r\n feature.value | flatLookup : featValues[feature.name]\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.value }}</span>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.in-row-button{margin-top:-16px}table{width:100%;border-collapse:collapse}th{text-align:left;background-color:#c8d9eb;color:#333;font-weight:400}th,td{border:1px solid silver;padding:4px}tr:nth-child(2n){background-color:#dfdfdf}#filter{width:7em}\n"] }]
91
- }], ctorParameters: () => [{ type: i1.FormBuilder }], propDecorators: { features: [{
92
- type: Input
93
- }], featNames: [{
94
- type: Input
95
- }], featValues: [{
96
- type: Input
97
- }], filterThreshold: [{
98
- type: Input
99
- }] } });
100
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmVhdHVyZS1zZXQtdmlldy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9teXJtaWRvbi9ndmUtY29yZS9zcmMvbGliL2NvbXBvbmVudHMvZmVhdHVyZS1zZXQtdmlldy9mZWF0dXJlLXNldC12aWV3LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL215cm1pZG9uL2d2ZS1jb3JlL3NyYy9saWIvY29tcG9uZW50cy9mZWF0dXJlLXNldC12aWV3L2ZlYXR1cmUtc2V0LXZpZXcuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakQsT0FBTyxFQUE0QixtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQWdCLFlBQVksRUFBRSxvQkFBb0IsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUV4RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDbEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV6RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7Ozs7Ozs7O0FBU25EOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBZ0JILE1BQU0sT0FBTyx1QkFBdUI7SUFJbEM7O09BRUc7SUFDSCxJQUNXLFFBQVE7UUFDakIsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ3hCLENBQUM7SUFDRCxJQUFXLFFBQVEsQ0FBQyxLQUFxQztRQUN2RCxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssS0FBSyxFQUFFLENBQUM7WUFDN0IsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssSUFBSSxTQUFTLENBQUM7UUFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNwQixJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBOEJELFlBQVksV0FBd0I7UUE5QzVCLGNBQVMsR0FBbUMsRUFBRSxDQUFDO1FBaUN2RDs7Ozs7V0FLRztRQUVJLG9CQUFlLEdBQUcsQ0FBQyxDQUFDO1FBSXBCLHFCQUFnQixHQUFtQyxFQUFFLENBQUM7UUFHM0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFTyxrQkFBa0IsQ0FBQyxJQUFvQjtRQUM3QyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUN4RCxPQUFPLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQzFFLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLFFBQVE7UUFDYixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWTthQUNqQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7YUFDL0MsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDbkIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxDQUFDO1FBQ0wsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVNLFdBQVc7UUFDaEIsSUFBSSxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsQ0FBQztJQUMzQixDQUFDOzhHQXJFVSx1QkFBdUI7a0dBQXZCLHVCQUF1Qix3TUNuRHBDLDhqREF1REEsNllEZkksWUFBWSw4QkFDWixtQkFBbUIseWtCQUNuQixlQUFlLDJJQUNmLGtCQUFrQiwyYUFDbEIsYUFBYSxtTEFDYixjQUFjLDBXQUNkLGFBQWE7OzJGQUtKLHVCQUF1QjtrQkFmbkMsU0FBUzsrQkFDRSxzQkFBc0IsY0FDcEIsSUFBSSxXQUNQO3dCQUNQLFlBQVk7d0JBQ1osbUJBQW1CO3dCQUNuQixlQUFlO3dCQUNmLGtCQUFrQjt3QkFDbEIsYUFBYTt3QkFDYixjQUFjO3dCQUNkLGFBQWE7cUJBQ2Q7Z0ZBWVUsUUFBUTtzQkFEbEIsS0FBSztnQkFrQkMsU0FBUztzQkFEZixLQUFLO2dCQVNDLFVBQVU7c0JBRGhCLEtBQUs7Z0JBVUMsZUFBZTtzQkFEckIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRm9ybUJ1aWxkZXIsIEZvcm1Db250cm9sLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBTdWJzY3JpcHRpb24sIGRlYm91bmNlVGltZSwgZGlzdGluY3RVbnRpbENoYW5nZWQgfSBmcm9tICdyeGpzJztcclxuXHJcbmltcG9ydCB7IE1hdEJ1dHRvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2J1dHRvbic7XHJcbmltcG9ydCB7IE1hdEZvcm1GaWVsZE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xyXG5pbXBvcnQgeyBNYXRJY29uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XHJcbmltcG9ydCB7IE1hdElucHV0TW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaW5wdXQnO1xyXG5cclxuaW1wb3J0IHsgTmdUb29sc01vZHVsZSB9IGZyb20gJ0BteXJtaWRvbi9uZy10b29scyc7XHJcblxyXG5pbXBvcnQge1xyXG4gIEZlYXR1cmUsXHJcbiAgTGFiZWxlZElkLFxyXG4gIE9wZXJhdGlvbkZlYXR1cmUsXHJcbn0gZnJvbSAnQG15cm1pZG9uL2d2ZS1zbmFwc2hvdC12aWV3JztcclxuaW1wb3J0IHsgRmVhdHVyZU1hcCB9IGZyb20gJy4uL2ZlYXR1cmUtZWRpdG9yL2ZlYXR1cmUtZWRpdG9yLmNvbXBvbmVudCc7XHJcblxyXG4vKipcclxuICog8J+UkSBgZ3ZlLWZlYXR1cmUtc2V0LXZpZXdgXHJcbiAqXHJcbiAqIEEgY29tcG9uZW50IHRvIGRpc3BsYXkgYSBsaXN0IG9mIGZlYXR1cmVzLlxyXG4gKiBVc2VkIGJ5IHRoZSBjaGFpbiByZXN1bHQgdmlldyBjb21wb25lbnQuXHJcbiAqXHJcbiAqIC0g4pa277iPIGBmZWF0dXJlc2AgKGBGZWF0dXJlW11gKTogdGhlIGZlYXR1cmVzIHRvIGRpc3BsYXkuXHJcbiAqIC0g4pa277iPIGBmZWF0TmFtZXNgIChgTGFiZWxlZElkW11gKTogdGhlIGxpc3Qgb2YgZmVhdHVyZSBuYW1lcyB0byBkaXNwbGF5XHJcbiAqIGluIHRoZSBfbmFtZV8gc2VsZWN0aW9uLiBUaGlzIGlzIHVzZWQgd2hlbiB5b3UgaGF2ZSBhIGNsb3NlZCBsaXN0IG9mIGZlYXR1cmVzLlxyXG4gKiAtIOKWtu+4jyBgZmVhdFZhbHVlc2AgKGBGZWF0dXJlTWFwYCk6IHRoZSBmZWF0dXJlIHZhbHVlcyBtYXAuIFdoZW4gc3BlY2lmaWVkXHJcbiAqIGFuZCB0aGUgdXNlciBzZWxlY3RzIGEgZmVhdHVyZSBuYW1lIHByZXNlbnQgaW4gdGhlIG1hcCBrZXlzLCB0aGUgY29ycmVzcG9uZGluZ1xyXG4gKiB2YWx1ZXMgd2lsbCBiZSB1c2VkIHRvIHBvcHVsYXRlIHRoZSB2YWx1ZSBzZWxlY3Rpb24uXHJcbiAqIC0g4pa277iPIGBmaWx0ZXJUaHJlc2hvbGRgIChgbnVtYmVyYCk6IHRoZSB0aHJlc2hvbGQgYXQgd2hpY2ggdGhlIGZlYXR1cmVzIGZpbHRlclxyXG4gKiBzaG91bGQgYmVjb21lIHZpc2libGUuIElmIHNldCB0byAwLCB0aGUgZmlsdGVyIGlzIGFsd2F5cyB2aXNpYmxlOyBpZiBzZXQgdG8gLTEsXHJcbiAqIGl0IGlzIGFsd2F5cyBpbnZpc2libGU7IG90aGVyd2lzZSwgaXQgZ2V0cyB2aXNpYmxlIHdoZW4gdGhlIG51bWJlciBvZiBmZWF0dXJlc1xyXG4gKiBpcyBncmVhdGVyIHRoYW4gdGhlIHRocmVzaG9sZC4gRGVmYXVsdCBpcyA1LlxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdndmUtZmVhdHVyZS1zZXQtdmlldycsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbXHJcbiAgICBDb21tb25Nb2R1bGUsXHJcbiAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxyXG4gICAgTWF0QnV0dG9uTW9kdWxlLFxyXG4gICAgTWF0Rm9ybUZpZWxkTW9kdWxlLFxyXG4gICAgTWF0SWNvbk1vZHVsZSxcclxuICAgIE1hdElucHV0TW9kdWxlLFxyXG4gICAgTmdUb29sc01vZHVsZSxcclxuICBdLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9mZWF0dXJlLXNldC12aWV3LmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybDogJy4vZmVhdHVyZS1zZXQtdmlldy5jb21wb25lbnQuY3NzJyxcclxufSlcclxuZXhwb3J0IGNsYXNzIEZlYXR1cmVTZXRWaWV3Q29tcG9uZW50IHtcclxuICBwcml2YXRlIF9zdWI/OiBTdWJzY3JpcHRpb247XHJcbiAgcHJpdmF0ZSBfZmVhdHVyZXM6IEZlYXR1cmVbXSB8IE9wZXJhdGlvbkZlYXR1cmVbXSA9IFtdO1xyXG5cclxuICAvKipcclxuICAgKiBUaGUgZmVhdHVyZXMuXHJcbiAgICovXHJcbiAgQElucHV0KClcclxuICBwdWJsaWMgZ2V0IGZlYXR1cmVzKCk6IEZlYXR1cmVbXSB8IE9wZXJhdGlvbkZlYXR1cmVbXSB7XHJcbiAgICByZXR1cm4gdGhpcy5fZmVhdHVyZXM7XHJcbiAgfVxyXG4gIHB1YmxpYyBzZXQgZmVhdHVyZXModmFsdWU6IEZlYXR1cmVbXSB8IE9wZXJhdGlvbkZlYXR1cmVbXSkge1xyXG4gICAgaWYgKHRoaXMuX2ZlYXR1cmVzID09PSB2YWx1ZSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLl9mZWF0dXJlcyA9IHZhbHVlIHx8IHVuZGVmaW5lZDtcclxuICAgIHRoaXMuZmlsdGVyLnJlc2V0KCk7XHJcbiAgICB0aGlzLmFwcGx5RmVhdHVyZUZpbHRlcigpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGhlIGxpc3Qgb2YgZmVhdHVyZSBuYW1lcyB0byBkaXNwbGF5IGluIHRoZSBuYW1lIHNlbGVjdGlvbi5cclxuICAgKiBUaGlzIGlzIHVzZWQgd2hlbiB5b3UgaGF2ZSBhIGNsb3NlZCBsaXN0IG9mIGZlYXR1cmVzLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGZlYXROYW1lczogTGFiZWxlZElkW10gfCB1bmRlZmluZWQ7XHJcblxyXG4gIC8qKlxyXG4gICAqIFRoZSBmZWF0dXJlIHZhbHVlcyBtYXAuIFdoZW4gc3BlY2lmaWVkIGFuZCB0aGUgdXNlciBzZWxlY3RzIGEgZmVhdHVyZVxyXG4gICAqIG5hbWUgcHJlc2VudCBpbiB0aGUgbWFwIGtleXMsIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlcyB3aWxsIGJlIHVzZWRcclxuICAgKiB0byBwb3B1bGF0ZSB0aGUgdmFsdWUgc2VsZWN0aW9uLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGZlYXRWYWx1ZXM6IEZlYXR1cmVNYXAgfCB1bmRlZmluZWQ7XHJcblxyXG4gIC8qKlxyXG4gICAqIFRoZSB0aHJlc2hvbGQgYXQgd2hpY2ggdGhlIGZlYXR1cmVzIGZpbHRlciBzaG91bGQgYmVjb21lIHZpc2libGUuXHJcbiAgICogSWYgc2V0IHRvIDAsIHRoZSBmaWx0ZXIgaXMgYWx3YXlzIHZpc2libGU7IGlmIHNldCB0byAtMSwgaXQgaXMgYWx3YXlzXHJcbiAgICogaW52aXNpYmxlOyBvdGhlcndpc2UsIGl0IGdldHMgdmlzaWJsZSB3aGVuIHRoZSBudW1iZXIgb2YgZmVhdHVyZXNcclxuICAgKiBpcyBncmVhdGVyIHRoYW4gdGhlIHRocmVzaG9sZC4gRGVmYXVsdCBpcyA1LlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGZpbHRlclRocmVzaG9sZCA9IDU7XHJcblxyXG4gIC8vIGZpbHRlclxyXG4gIHB1YmxpYyBmaWx0ZXI6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xyXG4gIHB1YmxpYyBmaWx0ZXJlZEZlYXR1cmVzOiBGZWF0dXJlW10gfCBPcGVyYXRpb25GZWF0dXJlW10gPSBbXTtcclxuXHJcbiAgY29uc3RydWN0b3IoZm9ybUJ1aWxkZXI6IEZvcm1CdWlsZGVyKSB7XHJcbiAgICB0aGlzLmZpbHRlciA9IGZvcm1CdWlsZGVyLmNvbnRyb2wobnVsbCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFwcGx5RmVhdHVyZUZpbHRlcihuYW1lPzogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xyXG4gICAgdGhpcy5maWx0ZXJlZEZlYXR1cmVzID0gdGhpcy5fZmVhdHVyZXMuZmlsdGVyKChmZWF0dXJlKSA9PiB7XHJcbiAgICAgIHJldHVybiAhbmFtZSB8fCBmZWF0dXJlLm5hbWUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhuYW1lLnRvTG93ZXJDYXNlKCkpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICB0aGlzLl9zdWIgPSB0aGlzLmZpbHRlci52YWx1ZUNoYW5nZXNcclxuICAgICAgLnBpcGUoZGlzdGluY3RVbnRpbENoYW5nZWQoKSwgZGVib3VuY2VUaW1lKDMwMCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgdGhpcy5hcHBseUZlYXR1cmVGaWx0ZXIodmFsdWUpO1xyXG4gICAgICB9KTtcclxuICAgIHRoaXMuYXBwbHlGZWF0dXJlRmlsdGVyKCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLl9zdWI/LnVuc3Vic2NyaWJlKCk7XHJcbiAgfVxyXG59XHJcbiIsIjxkaXY+XHJcbiAgPCEtLSBmaWx0ZXIgLS0+XHJcbiAgPGRpdj5cclxuICAgIEBpZiAoZmlsdGVyVGhyZXNob2xkID09PSAwIHx8IGZlYXR1cmVzLmxlbmd0aCA+IGZpbHRlclRocmVzaG9sZCkge1xyXG4gICAgPGRpdiBjbGFzcz1cImZvcm0tcm93XCI+XHJcbiAgICAgIDxtYXQtZm9ybS1maWVsZCBpZD1cImZpbHRlclwiPlxyXG4gICAgICAgIDxtYXQtbGFiZWw+ZmlsdGVyPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgPGlucHV0IG1hdElucHV0IHBsYWNlaG9sZGVyPVwiZmlsdGVyXCIgW2Zvcm1Db250cm9sXT1cImZpbHRlclwiIC8+XHJcbiAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgIG1hdFN1ZmZpeFxyXG4gICAgICAgICAgKGNsaWNrKT1cImZpbHRlci5yZXNldCgpXCJcclxuICAgICAgICAgIFtkaXNhYmxlZF09XCIhZmlsdGVyLnZhbHVlXCJcclxuICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ1Jlc2V0IGZpbHRlcidcIlxyXG4gICAgICAgID5cclxuICAgICAgICAgIDxtYXQtaWNvbiBjb2xvcj1cIndhcm5cIiAgY2xhc3M9XCJtYXQtd2FyblwiPmNhbmNlbDwvbWF0LWljb24+XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcblxyXG4gICAgICA8c3Bhbj57eyBmaWx0ZXJlZEZlYXR1cmVzLmxlbmd0aCB9fTwvc3Bhbj5cclxuICAgIDwvZGl2PlxyXG4gICAgfVxyXG5cclxuICAgIDwhLS0gbGlzdCAtLT5cclxuICAgIEBpZiAoZmlsdGVyZWRGZWF0dXJlcy5sZW5ndGgpIHtcclxuICAgIDx0YWJsZT5cclxuICAgICAgPHRib2R5PlxyXG4gICAgICAgIEBmb3IgKGZlYXR1cmUgb2YgZmlsdGVyZWRGZWF0dXJlczsgdHJhY2sgJGluZGV4KSB7XHJcbiAgICAgICAgPHRyPlxyXG4gICAgICAgICAgPHRoPlxyXG4gICAgICAgICAgICBAaWYgKGZlYXROYW1lcz8ubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIDxzcGFuPnt7XHJcbiAgICAgICAgICAgICAgZmVhdHVyZS5uYW1lIHwgZmxhdExvb2t1cCA6IGZlYXROYW1lcyA6IFwiaWRcIiA6IFwibGFiZWxcIlxyXG4gICAgICAgICAgICB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgfSBAZWxzZSB7XHJcbiAgICAgICAgICAgIDxzcGFuPnt7IGZlYXR1cmUubmFtZSB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgPC90aD5cclxuICAgICAgICAgIDx0ZD5cclxuICAgICAgICAgICAgQGlmIChmZWF0VmFsdWVzKSB7XHJcbiAgICAgICAgICAgIDxzcGFuPnt7XHJcbiAgICAgICAgICAgICAgZmVhdHVyZS52YWx1ZSB8IGZsYXRMb29rdXAgOiBmZWF0VmFsdWVzW2ZlYXR1cmUubmFtZV1cclxuICAgICAgICAgICAgfX08L3NwYW4+XHJcbiAgICAgICAgICAgIH0gQGVsc2Uge1xyXG4gICAgICAgICAgICA8c3Bhbj57eyBmZWF0dXJlLnZhbHVlIH19PC9zcGFuPlxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICA8L3RkPlxyXG4gICAgICAgIDwvdHI+XHJcbiAgICAgICAgfVxyXG4gICAgICA8L3Rib2R5PlxyXG4gICAgPC90YWJsZT5cclxuICAgIH1cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcbiJdfQ==
@@ -1,126 +0,0 @@
1
- import { CommonModule } from '@angular/common';
2
- import { Component, EventEmitter, Input, Output, } from '@angular/core';
3
- import { ReactiveFormsModule } from '@angular/forms';
4
- import { debounceTime, distinctUntilChanged } from 'rxjs';
5
- import { MatButtonModule } from '@angular/material/button';
6
- import { MatFormFieldModule } from '@angular/material/form-field';
7
- import { MatIconModule } from '@angular/material/icon';
8
- import { MatInputModule } from '@angular/material/input';
9
- import { MatSelectModule } from '@angular/material/select';
10
- import { MatTooltipModule } from '@angular/material/tooltip';
11
- import * as i0 from "@angular/core";
12
- import * as i1 from "@angular/forms";
13
- import * as i2 from "@angular/common";
14
- import * as i3 from "@angular/material/button";
15
- import * as i4 from "@angular/material/form-field";
16
- import * as i5 from "@angular/material/icon";
17
- import * as i6 from "@angular/material/input";
18
- import * as i7 from "@angular/material/select";
19
- import * as i8 from "@angular/material/core";
20
- import * as i9 from "@angular/material/tooltip";
21
- /**
22
- * 🔑 `gve-ln-heights-editor`
23
- *
24
- * A component to edit line heights.
25
- * Used by the `gve-snapshot-editor` component.
26
- *
27
- * - ▶️ `lineCount` (`number`): the number of lines.
28
- * - ▶️ `heights` (`Record<number, number>`): the line heights.
29
- * - 🔥 `heightsChange` (`EventEmitter<Record<number, number>>`): the event
30
- * emitted when the heights change.
31
- */
32
- export class LnHeightsEditorComponent {
33
- /**
34
- * The total number of lines in the text.
35
- */
36
- get lineCount() {
37
- return this._lineCount;
38
- }
39
- set lineCount(value) {
40
- if (this._lineCount === value)
41
- return;
42
- this._lineCount = value;
43
- this.lineNumbers = Array.from({ length: value }, (_, i) => i + 1);
44
- }
45
- /**
46
- * The heights map of the lines. Each key is a line number and the value is
47
- * the height of the line.
48
- */
49
- get heights() {
50
- return this._heights;
51
- }
52
- set heights(value) {
53
- if (this._heights === value)
54
- return;
55
- this._heights = value || undefined;
56
- }
57
- constructor(formBuilder) {
58
- this._lineCount = 0;
59
- /**
60
- * The event emitted when the heights change.
61
- */
62
- this.heightsChange = new EventEmitter();
63
- this.lineNumbers = [];
64
- this.lineNumber = formBuilder.control(0, { nonNullable: true });
65
- this.height = formBuilder.control(0, { nonNullable: true });
66
- }
67
- pruneHeights() {
68
- // remove all the heigths with value=0
69
- this._heights = Object.fromEntries(Object.entries(this._heights || {}).filter(([_, v]) => v !== 0));
70
- // if heights are now empty, set to undefined
71
- if (Object.keys(this._heights).length === 0) {
72
- this._heights = undefined;
73
- }
74
- }
75
- ngOnInit() {
76
- this._subs = [];
77
- // update heights[ln] when height changes and emit heightsChange
78
- this._subs.push(this.height.valueChanges
79
- .pipe(distinctUntilChanged(), debounceTime(200))
80
- .subscribe((value) => {
81
- if (!this._heights) {
82
- this._heights = {};
83
- }
84
- this._heights[this.lineNumber.value] = value;
85
- this.pruneHeights();
86
- this.heightsChange.emit(this._heights);
87
- }));
88
- // update height when line number changes
89
- this._subs.push(this.lineNumber.valueChanges
90
- .pipe(distinctUntilChanged(), debounceTime(200))
91
- .subscribe((value) => {
92
- if (!this._heights)
93
- return;
94
- this.height.setValue(this._heights[value] || 0);
95
- }));
96
- }
97
- ngOnDestroy() {
98
- this._subs?.forEach((sub) => sub.unsubscribe());
99
- }
100
- reset() {
101
- this._heights = undefined;
102
- this.heightsChange.emit(undefined);
103
- }
104
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: LnHeightsEditorComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
105
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", type: LnHeightsEditorComponent, isStandalone: true, selector: "gve-ln-heights-editor", inputs: { lineCount: "lineCount", heights: "heights" }, outputs: { heightsChange: "heightsChange" }, ngImport: i0, template: "@if (lineNumbers.length) {\r\n<div class=\"form-row\">\r\n <!-- line number -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>line</mat-label>\r\n <mat-select [formControl]=\"lineNumber\">\r\n <mat-option *ngFor=\"let n of lineNumbers\" [value]=\"n\">\r\n {{ n }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n @if (lineNumber.value) {\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input matInput type=\"number\" [formControl]=\"height\" min=\"0\" />\r\n </mat-form-field>\r\n }\r\n\r\n <!-- reset button -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n (click)=\"reset()\"\r\n matTooltip=\"Remove all the heights\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n</div>\r\n}\r\n", styles: [".input-nr{width:5em}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.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: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i8.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); }
106
- }
107
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: LnHeightsEditorComponent, decorators: [{
108
- type: Component,
109
- args: [{ selector: 'gve-ln-heights-editor', standalone: true, imports: [
110
- CommonModule,
111
- ReactiveFormsModule,
112
- MatButtonModule,
113
- MatFormFieldModule,
114
- MatIconModule,
115
- MatInputModule,
116
- MatSelectModule,
117
- MatTooltipModule,
118
- ], template: "@if (lineNumbers.length) {\r\n<div class=\"form-row\">\r\n <!-- line number -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>line</mat-label>\r\n <mat-select [formControl]=\"lineNumber\">\r\n <mat-option *ngFor=\"let n of lineNumbers\" [value]=\"n\">\r\n {{ n }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n @if (lineNumber.value) {\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input matInput type=\"number\" [formControl]=\"height\" min=\"0\" />\r\n </mat-form-field>\r\n }\r\n\r\n <!-- reset button -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n (click)=\"reset()\"\r\n matTooltip=\"Remove all the heights\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n</div>\r\n}\r\n", styles: [".input-nr{width:5em}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"] }]
119
- }], ctorParameters: () => [{ type: i1.FormBuilder }], propDecorators: { lineCount: [{
120
- type: Input
121
- }], heights: [{
122
- type: Input
123
- }], heightsChange: [{
124
- type: Output
125
- }] } });
126
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG4taGVpZ2h0cy1lZGl0b3IuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbXlybWlkb24vZ3ZlLWNvcmUvc3JjL2xpYi9jb21wb25lbnRzL2xuLWhlaWdodHMtZWRpdG9yL2xuLWhlaWdodHMtZWRpdG9yLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL215cm1pZG9uL2d2ZS1jb3JlL3NyYy9saWIvY29tcG9uZW50cy9sbi1oZWlnaHRzLWVkaXRvci9sbi1oZWlnaHRzLWVkaXRvci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUNMLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUdMLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQTRCLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDL0UsT0FBTyxFQUFnQixZQUFZLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFeEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDekQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDOzs7Ozs7Ozs7OztBQUU3RDs7Ozs7Ozs7OztHQVVHO0FBaUJILE1BQU0sT0FBTyx3QkFBd0I7SUFRbkM7O09BRUc7SUFDSCxJQUNXLFNBQVM7UUFD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QyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ25CLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUTtnQkFBRSxPQUFPO1lBQzNCLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDbEQsQ0FBQyxDQUFDLENBQ0wsQ0FBQztJQUNKLENBQUM7SUFFTSxXQUFXO1FBQ2hCLElBQUksQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBRU0sS0FBSztRQUNWLElBQUksQ0FBQyxRQUFRLEdBQUcsU0FBUyxDQUFDO1FBQzFCLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7OEdBOUZVLHdCQUF3QjtrR0FBeEIsd0JBQXdCLHNMQzlDckMsKzJCQWdDQSwwS0RFSSxZQUFZLDJKQUNaLG1CQUFtQixzNkJBQ25CLGVBQWUsMklBQ2Ysa0JBQWtCLDBTQUNsQixhQUFhLG1MQUNiLGNBQWMsMFdBQ2QsZUFBZSxtckJBQ2YsZ0JBQWdCOzsyRkFLUCx3QkFBd0I7a0JBaEJwQyxTQUFTOytCQUNFLHVCQUF1QixjQUNyQixJQUFJLFdBQ1A7d0JBQ1AsWUFBWTt3QkFDWixtQkFBbUI7d0JBQ25CLGVBQWU7d0JBQ2Ysa0JBQWtCO3dCQUNsQixhQUFhO3dCQUNiLGNBQWM7d0JBQ2QsZUFBZTt3QkFDZixnQkFBZ0I7cUJBQ2pCO2dGQWdCVSxTQUFTO3NCQURuQixLQUFLO2dCQWVLLE9BQU87c0JBRGpCLEtBQUs7Z0JBYVUsYUFBYTtzQkFENUIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBJbnB1dCxcclxuICBPbkRlc3Ryb3ksXHJcbiAgT25Jbml0LFxyXG4gIE91dHB1dCxcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRm9ybUJ1aWxkZXIsIEZvcm1Db250cm9sLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBTdWJzY3JpcHRpb24sIGRlYm91bmNlVGltZSwgZGlzdGluY3RVbnRpbENoYW5nZWQgfSBmcm9tICdyeGpzJztcclxuXHJcbmltcG9ydCB7IE1hdEJ1dHRvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2J1dHRvbic7XHJcbmltcG9ydCB7IE1hdEZvcm1GaWVsZE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xyXG5pbXBvcnQgeyBNYXRJY29uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XHJcbmltcG9ydCB7IE1hdElucHV0TW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaW5wdXQnO1xyXG5pbXBvcnQgeyBNYXRTZWxlY3RNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zZWxlY3QnO1xyXG5pbXBvcnQgeyBNYXRUb29sdGlwTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCc7XHJcblxyXG4vKipcclxuICog8J+UkSBgZ3ZlLWxuLWhlaWdodHMtZWRpdG9yYFxyXG4gKlxyXG4gKiBBIGNvbXBvbmVudCB0byBlZGl0IGxpbmUgaGVpZ2h0cy5cclxuICogVXNlZCBieSB0aGUgYGd2ZS1zbmFwc2hvdC1lZGl0b3JgIGNvbXBvbmVudC5cclxuICpcclxuICogLSDilrbvuI8gYGxpbmVDb3VudGAgKGBudW1iZXJgKTogdGhlIG51bWJlciBvZiBsaW5lcy5cclxuICogLSDilrbvuI8gYGhlaWdodHNgIChgUmVjb3JkPG51bWJlciwgbnVtYmVyPmApOiB0aGUgbGluZSBoZWlnaHRzLlxyXG4gKiAtIPCflKUgYGhlaWdodHNDaGFuZ2VgIChgRXZlbnRFbWl0dGVyPFJlY29yZDxudW1iZXIsIG51bWJlcj4+YCk6IHRoZSBldmVudFxyXG4gKiBlbWl0dGVkIHdoZW4gdGhlIGhlaWdodHMgY2hhbmdlLlxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdndmUtbG4taGVpZ2h0cy1lZGl0b3InLFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgaW1wb3J0czogW1xyXG4gICAgQ29tbW9uTW9kdWxlLFxyXG4gICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcclxuICAgIE1hdEJ1dHRvbk1vZHVsZSxcclxuICAgIE1hdEZvcm1GaWVsZE1vZHVsZSxcclxuICAgIE1hdEljb25Nb2R1bGUsXHJcbiAgICBNYXRJbnB1dE1vZHVsZSxcclxuICAgIE1hdFNlbGVjdE1vZHVsZSxcclxuICAgIE1hdFRvb2x0aXBNb2R1bGUsXHJcbiAgXSxcclxuICB0ZW1wbGF0ZVVybDogJy4vbG4taGVpZ2h0cy1lZGl0b3IuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsOiAnLi9sbi1oZWlnaHRzLWVkaXRvci5jb21wb25lbnQuY3NzJyxcclxufSlcclxuZXhwb3J0IGNsYXNzIExuSGVpZ2h0c0VkaXRvckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcclxuICBwcml2YXRlIF9zdWJzPzogU3Vic2NyaXB0aW9uW107XHJcbiAgcHJpdmF0ZSBfaGVpZ2h0cz86IFJlY29yZDxudW1iZXIsIG51bWJlcj47XHJcbiAgcHJpdmF0ZSBfbGluZUNvdW50OiBudW1iZXIgPSAwO1xyXG5cclxuICBwdWJsaWMgbGluZU51bWJlcjogRm9ybUNvbnRyb2w8bnVtYmVyPjtcclxuICBwdWJsaWMgaGVpZ2h0OiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG5cclxuICAvKipcclxuICAgKiBUaGUgdG90YWwgbnVtYmVyIG9mIGxpbmVzIGluIHRoZSB0ZXh0LlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGdldCBsaW5lQ291bnQoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLl9saW5lQ291bnQ7XHJcbiAgfVxyXG4gIHB1YmxpYyBzZXQgbGluZUNvdW50KHZhbHVlOiBudW1iZXIpIHtcclxuICAgIGlmICh0aGlzLl9saW5lQ291bnQgPT09IHZhbHVlKSByZXR1cm47XHJcbiAgICB0aGlzLl9saW5lQ291bnQgPSB2YWx1ZTtcclxuICAgIHRoaXMubGluZU51bWJlcnMgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiB2YWx1ZSB9LCAoXywgaSkgPT4gaSArIDEpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGhlIGhlaWdodHMgbWFwIG9mIHRoZSBsaW5lcy4gRWFjaCBrZXkgaXMgYSBsaW5lIG51bWJlciBhbmQgdGhlIHZhbHVlIGlzXHJcbiAgICogdGhlIGhlaWdodCBvZiB0aGUgbGluZS5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBnZXQgaGVpZ2h0cygpOiBSZWNvcmQ8bnVtYmVyLCBudW1iZXI+IHwgdW5kZWZpbmVkIHtcclxuICAgIHJldHVybiB0aGlzLl9oZWlnaHRzO1xyXG4gIH1cclxuICBwdWJsaWMgc2V0IGhlaWdodHModmFsdWU6IFJlY29yZDxudW1iZXIsIG51bWJlcj4gfCB1bmRlZmluZWQgfCBudWxsKSB7XHJcbiAgICBpZiAodGhpcy5faGVpZ2h0cyA9PT0gdmFsdWUpIHJldHVybjtcclxuICAgIHRoaXMuX2hlaWdodHMgPSB2YWx1ZSB8fCB1bmRlZmluZWQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGUgZXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBoZWlnaHRzIGNoYW5nZS5cclxuICAgKi9cclxuICBAT3V0cHV0KClcclxuICBwdWJsaWMgcmVhZG9ubHkgaGVpZ2h0c0NoYW5nZTogRXZlbnRFbWl0dGVyPFxyXG4gICAgUmVjb3JkPG51bWJlciwgbnVtYmVyPiB8IHVuZGVmaW5lZFxyXG4gID4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcblxyXG4gIHB1YmxpYyBsaW5lTnVtYmVyczogbnVtYmVyW10gPSBbXTtcclxuXHJcbiAgY29uc3RydWN0b3IoZm9ybUJ1aWxkZXI6IEZvcm1CdWlsZGVyKSB7XHJcbiAgICB0aGlzLmxpbmVOdW1iZXIgPSBmb3JtQnVpbGRlci5jb250cm9sKDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLmhlaWdodCA9IGZvcm1CdWlsZGVyLmNvbnRyb2woMCwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJ1bmVIZWlnaHRzKCk6IHZvaWQge1xyXG4gICAgLy8gcmVtb3ZlIGFsbCB0aGUgaGVpZ3RocyB3aXRoIHZhbHVlPTBcclxuICAgIHRoaXMuX2hlaWdodHMgPSBPYmplY3QuZnJvbUVudHJpZXMoXHJcbiAgICAgIE9iamVjdC5lbnRyaWVzKHRoaXMuX2hlaWdodHMgfHwge30pLmZpbHRlcigoW18sIHZdKSA9PiB2ICE9PSAwKVxyXG4gICAgKTtcclxuICAgIC8vIGlmIGhlaWdodHMgYXJlIG5vdyBlbXB0eSwgc2V0IHRvIHVuZGVmaW5lZFxyXG4gICAgaWYgKE9iamVjdC5rZXlzKHRoaXMuX2hlaWdodHMpLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICB0aGlzLl9oZWlnaHRzID0gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5fc3VicyA9IFtdO1xyXG4gICAgLy8gdXBkYXRlIGhlaWdodHNbbG5dIHdoZW4gaGVpZ2h0IGNoYW5nZXMgYW5kIGVtaXQgaGVpZ2h0c0NoYW5nZVxyXG4gICAgdGhpcy5fc3Vicy5wdXNoKFxyXG4gICAgICB0aGlzLmhlaWdodC52YWx1ZUNoYW5nZXNcclxuICAgICAgICAucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLCBkZWJvdW5jZVRpbWUoMjAwKSlcclxuICAgICAgICAuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xyXG4gICAgICAgICAgaWYgKCF0aGlzLl9oZWlnaHRzKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2hlaWdodHMgPSB7fTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHRoaXMuX2hlaWdodHNbdGhpcy5saW5lTnVtYmVyLnZhbHVlXSA9IHZhbHVlO1xyXG4gICAgICAgICAgdGhpcy5wcnVuZUhlaWdodHMoKTtcclxuICAgICAgICAgIHRoaXMuaGVpZ2h0c0NoYW5nZS5lbWl0KHRoaXMuX2hlaWdodHMpO1xyXG4gICAgICAgIH0pXHJcbiAgICApO1xyXG5cclxuICAgIC8vIHVwZGF0ZSBoZWlnaHQgd2hlbiBsaW5lIG51bWJlciBjaGFuZ2VzXHJcbiAgICB0aGlzLl9zdWJzLnB1c2goXHJcbiAgICAgIHRoaXMubGluZU51bWJlci52YWx1ZUNoYW5nZXNcclxuICAgICAgICAucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLCBkZWJvdW5jZVRpbWUoMjAwKSlcclxuICAgICAgICAuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xyXG4gICAgICAgICAgaWYgKCF0aGlzLl9oZWlnaHRzKSByZXR1cm47XHJcbiAgICAgICAgICB0aGlzLmhlaWdodC5zZXRWYWx1ZSh0aGlzLl9oZWlnaHRzW3ZhbHVlXSB8fCAwKTtcclxuICAgICAgICB9KVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuX3N1YnM/LmZvckVhY2goKHN1YikgPT4gc3ViLnVuc3Vic2NyaWJlKCkpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHJlc2V0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5faGVpZ2h0cyA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMuaGVpZ2h0c0NoYW5nZS5lbWl0KHVuZGVmaW5lZCk7XHJcbiAgfVxyXG59XHJcbiIsIkBpZiAobGluZU51bWJlcnMubGVuZ3RoKSB7XHJcbjxkaXYgY2xhc3M9XCJmb3JtLXJvd1wiPlxyXG4gIDwhLS0gbGluZSBudW1iZXIgLS0+XHJcbiAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtbnJcIj5cclxuICAgIDxtYXQtbGFiZWw+bGluZTwvbWF0LWxhYmVsPlxyXG4gICAgPG1hdC1zZWxlY3QgW2Zvcm1Db250cm9sXT1cImxpbmVOdW1iZXJcIj5cclxuICAgICAgPG1hdC1vcHRpb24gKm5nRm9yPVwibGV0IG4gb2YgbGluZU51bWJlcnNcIiBbdmFsdWVdPVwiblwiPlxyXG4gICAgICAgIHt7IG4gfX1cclxuICAgICAgPC9tYXQtb3B0aW9uPlxyXG4gICAgPC9tYXQtc2VsZWN0PlxyXG4gIDwvbWF0LWZvcm0tZmllbGQ+XHJcblxyXG4gIDwhLS0gaGVpZ2h0IC0tPlxyXG4gIEBpZiAobGluZU51bWJlci52YWx1ZSkge1xyXG4gIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LW5yXCI+XHJcbiAgICA8bWF0LWxhYmVsPmhlaWdodDwvbWF0LWxhYmVsPlxyXG4gICAgPGlucHV0IG1hdElucHV0IHR5cGU9XCJudW1iZXJcIiBbZm9ybUNvbnRyb2xdPVwiaGVpZ2h0XCIgbWluPVwiMFwiIC8+XHJcbiAgPC9tYXQtZm9ybS1maWVsZD5cclxuICB9XHJcblxyXG4gIDwhLS0gcmVzZXQgYnV0dG9uIC0tPlxyXG4gIDxidXR0b25cclxuICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICBjb2xvcj1cIndhcm5cIlxyXG4gICAgKGNsaWNrKT1cInJlc2V0KClcIlxyXG4gICAgbWF0VG9vbHRpcD1cIlJlbW92ZSBhbGwgdGhlIGhlaWdodHNcIlxyXG4gID5cclxuICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdC13YXJuXCI+Y2xlYXI8L21hdC1pY29uPlxyXG4gIDwvYnV0dG9uPlxyXG48L2Rpdj5cclxufVxyXG4iXX0=