@jax-data-science/sci-image-visualizer 0.14.0 → 0.16.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 (34) hide show
  1. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +39 -3
  2. package/esm2022/lib/channel-histogram/channel-tree.mjs +65 -0
  3. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +1 -1
  4. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  5. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
  6. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +202 -33
  7. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +2 -1
  8. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +5 -8
  9. package/esm2022/lib/spatial/lod.mjs +19 -1
  10. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +47 -10
  11. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +49 -16
  12. package/esm2022/lib/store/visualizer-store.service.mjs +20 -3
  13. package/esm2022/lib/toolbar/toolbar.component.mjs +13 -4
  14. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +7 -7
  15. package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DvFp1jNH.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-CYsPzX3J.mjs} +462 -83
  16. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-CYsPzX3J.mjs.map +1 -0
  17. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-D7lSUAM1.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-DaZVXq1s.mjs} +3 -2
  18. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-D7lSUAM1.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-DaZVXq1s.mjs.map} +1 -1
  19. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +2 -1
  20. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  21. package/lib/channel-histogram/channel-histogram.component.d.ts +14 -0
  22. package/lib/channel-histogram/channel-tree.d.ts +30 -0
  23. package/lib/contracts/channel-histogram-api.contract.d.ts +2 -0
  24. package/lib/contracts/image.contract.d.ts +6 -0
  25. package/lib/implementations/napari-js/napari-scene.d.ts +2 -0
  26. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +80 -9
  27. package/lib/spatial/lod.d.ts +11 -1
  28. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +18 -1
  29. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +18 -0
  30. package/lib/store/visualizer-store.service.d.ts +7 -1
  31. package/lib/toolbar/toolbar.component.d.ts +6 -0
  32. package/lib/toolbar/view-controls/view-controls.component.d.ts +3 -3
  33. package/package.json +2 -2
  34. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DvFp1jNH.mjs.map +0 -1
@@ -20,6 +20,8 @@ import * as i4 from "primeng/overlaypanel";
20
20
  import * as i5 from "primeng/tooltip";
21
21
  /** Rows of the all-genes list drawn at once; the filter narrows the rest. */
22
22
  const ALL_GENES_ROWS = 200;
23
+ /** Names in reading order: case aside, and `G9` before `G10`. */
24
+ const byName = (a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });
23
25
  /**
24
26
  * The selected transcript genes as Xenium Explorer's tree: the gene groups, then the
25
27
  * ungrouped genes, each row with an eye that hides it without deselecting it, its marker
@@ -28,6 +30,11 @@ const ALL_GENES_ROWS = 200;
28
30
  * expands to every gene of the dataset, each with its eye when the dataset lists its genes
29
31
  * in code order (`transcriptTiles.genes`), filtered by name past a few hundred.
30
32
  *
33
+ * Both lists are ordered by name, or by their transcripts in view, most first (the
34
+ * sort switch, offered once the renderer reports counts). The all-genes list is sorted
35
+ * before it is cut to its first rows, so by count those are the genes with the most
36
+ * transcripts in view.
37
+ *
31
38
  * Writes only through `controls.setViewState`.
32
39
  */
33
40
  export class SpatialGeneTreeComponent {
@@ -47,6 +54,10 @@ export class SpatialGeneTreeComponent {
47
54
  /** Swatches in the picker: the categorical palette genes are coloured from by default. */
48
55
  /** The tree, rebuilt when the view changes — never per change-detection pass. */
49
56
  this.geneTree = [];
57
+ /** {@link geneTree} with each node's genes in {@link geneSort} order: what the template draws. */
58
+ this.sortedTree = [];
59
+ /** The rows' order. By count only while the renderer reports counts (see {@link sortShown}). */
60
+ this.geneSort = 'name';
50
61
  /** Per gene: its eye, swatch, glyph and count — rebuilt with the inputs (and when the
51
62
  * cells' group colours arrive), so the template does no per-row lookups per check. */
52
63
  this.rows = new Map();
@@ -108,8 +119,30 @@ export class SpatialGeneTreeComponent {
108
119
  .filter((node) => node.name)
109
120
  .map((node) => [node.name, this.areGenesShown(node.genes)]));
110
121
  this.rootShown = this.view.transcriptAllGenes ? this.anyOfAllGenesShown() : this.areGenesShown(genes);
122
+ this.sortedTree = this.geneTree.map((node) => ({ ...node, genes: this.sorted(node.genes) }));
111
123
  this.rebuildAllRows();
112
124
  }
125
+ /** Whether the rows are ordered by count: chosen, and counts to order by. */
126
+ get byCount() {
127
+ return this.geneSort === 'count' && !!this.geneCounts;
128
+ }
129
+ /** The sort switch is offered once there are counts to sort by. */
130
+ get sortShown() {
131
+ return !!this.geneCounts;
132
+ }
133
+ onGeneSort(sort) {
134
+ if (sort === this.geneSort)
135
+ return;
136
+ this.geneSort = sort;
137
+ this.rebuildRows();
138
+ }
139
+ /** `genes` in the rows' order: by count, most first (ties by name), else by name. */
140
+ sorted(genes) {
141
+ if (!this.byCount)
142
+ return [...genes].sort(byName);
143
+ const counts = this.geneCounts ?? {};
144
+ return [...genes].sort((a, b) => (counts[b] ?? 0) - (counts[a] ?? 0) || byName(a, b));
145
+ }
113
146
  /**
114
147
  * The all-genes list's rows: the genes matching the filter, up to the cap. Built only while
115
148
  * the list is open: the counts in view change with every pan, and the list can be thousands.
@@ -123,24 +156,24 @@ export class SpatialGeneTreeComponent {
123
156
  }
124
157
  const needle = this.allGenesFilter.trim().toLowerCase();
125
158
  const shown = allGeneShownBy(this.view.transcriptAllGenesHidden);
126
- const rows = [];
127
- let matched = 0;
159
+ // Every match, ordered, and only then cut: by count the first rows are the most abundant.
160
+ const codes = new Map();
128
161
  list.forEach((gene, code) => {
129
162
  // An empty name is a code no transcript carries (a control probe).
130
163
  if (!gene || (needle && !gene.toLowerCase().includes(needle)))
131
164
  return;
132
- matched++;
133
- if (rows.length >= ALL_GENES_ROWS)
134
- return;
135
- rows.push({
136
- gene,
137
- shown: shown(gene),
138
- swatch: this.canHideAllGenes ? this.allGeneColorOf(gene, code) : null,
139
- count: this.geneCountOf(gene),
140
- });
165
+ if (!codes.has(gene))
166
+ codes.set(gene, code);
141
167
  });
142
- this.allRows = rows;
143
- this.allGenesMatched = matched;
168
+ this.allRows = this.sorted([...codes.keys()])
169
+ .slice(0, ALL_GENES_ROWS)
170
+ .map((gene) => ({
171
+ gene,
172
+ shown: shown(gene),
173
+ swatch: this.canHideAllGenes ? this.allGeneColorOf(gene, codes.get(gene)) : null,
174
+ count: this.geneCountOf(gene),
175
+ }));
176
+ this.allGenesMatched = codes.size;
144
177
  }
145
178
  /** Whether "All genes" draws anything: not switched off whole, nor every listed gene hidden. */
146
179
  anyOfAllGenesShown() {
@@ -295,7 +328,7 @@ export class SpatialGeneTreeComponent {
295
328
  });
296
329
  }
297
330
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SpatialGeneTreeComponent, deps: [{ token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
298
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: SpatialGeneTreeComponent, isStandalone: true, selector: "spatial-gene-tree", inputs: { controls: "controls", dataset: "dataset", view: "view", geneCounts: "geneCounts", geneTotal: "geneTotal" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"sc-subhead\">Selected genes</div>\n<div class=\"sc-gene-tree\">\n <div class=\"sc-gene-row sc-gene-root\">\n <button\n type=\"button\"\n class=\"sc-eye\"\n (click)=\"\n view.transcriptAllGenes ? onAllGenesShown(!rootShown) : onGenesShown(view.transcriptGenes, !rootShown)\n \"\n >\n <i class=\"pi\" [class.pi-eye]=\"rootShown\" [class.pi-eye-slash]=\"!rootShown\"></i>\n </button>\n <span class=\"sc-group-label\">Genes</span>\n <span class=\"sc-count\"\n >({{ (view.transcriptAllGenes ? geneTotal : view.transcriptGenes.length) | number }}/{{\n geneTotal | number\n }})</span\n >\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n (click)=\"geneTreeOpen = !geneTreeOpen\"\n *ngIf=\"!view.transcriptAllGenes && view.transcriptGenes.length\"\n >\n <i class=\"pi\" [class.pi-chevron-down]=\"geneTreeOpen\" [class.pi-chevron-right]=\"!geneTreeOpen\"></i>\n </button>\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n (click)=\"toggleAllGenesOpen()\"\n *ngIf=\"view.transcriptAllGenes && allGeneList?.length\"\n [attr.aria-label]=\"allGenesOpen ? 'Hide the gene list' : 'Show every gene'\"\n >\n <i class=\"pi\" [class.pi-chevron-down]=\"allGenesOpen\" [class.pi-chevron-right]=\"!allGenesOpen\"></i>\n </button>\n </div>\n <!-- \"All genes\": every gene of the dataset, each with its eye when the dataset says which\n transcripts are whose (its gene list in code order). -->\n <ng-container *ngIf=\"allGenesOpen && view.transcriptAllGenes && allGeneList?.length\">\n <input\n pInputText\n class=\"sc-gene-filter\"\n placeholder=\"Filter genes\u2026\"\n aria-label=\"Filter genes\"\n [value]=\"allGenesFilter\"\n (input)=\"onAllGenesFilter($any($event.target).value)\"\n />\n <small class=\"sc-hint\" *ngIf=\"!canHideAllGenes\">\n This dataset does not say which transcripts are whose, so its genes cannot be hidden one by one.\n </small>\n <small class=\"sc-hint\" *ngIf=\"canHideAllGenes && view.transcriptMode === 'density'\">\n The density map draws every gene as one raster: genes are hidden one by one as circles or icons.\n </small>\n <div class=\"sc-gene-row sc-gene-leaf nested\" *ngFor=\"let row of allRows; trackBy: trackByAllRow\">\n <button\n type=\"button\"\n class=\"sc-eye\"\n [disabled]=\"!canHideAllGenes || view.transcriptMode === 'density'\"\n (click)=\"onAllGeneShown(row.gene, !row.shown)\"\n >\n <i class=\"pi\" [class.pi-eye]=\"row.shown\" [class.pi-eye-slash]=\"!row.shown\"></i>\n </button>\n <span class=\"sc-gene-icon\" *ngIf=\"row.swatch\" [style.color]=\"row.swatch\" aria-hidden=\"true\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\"><circle r=\"0.75\"></circle></svg>\n </span>\n <span class=\"sc-group-label\" [title]=\"row.gene\">{{ row.gene }}</span>\n <span class=\"sc-gene-count\" *ngIf=\"row.count !== null\" title=\"Transcripts in view\">{{\n row.count | number\n }}</span>\n </div>\n <small class=\"sc-hint\" *ngIf=\"allGenesMatched > allRows.length\">\n Showing {{ allRows.length | number }} of {{ allGenesMatched | number }} genes: filter to find the others.\n </small>\n <small class=\"sc-hint\" *ngIf=\"allGenesMatched === 0\">No gene matches.</small>\n </ng-container>\n <ng-container *ngIf=\"geneTreeOpen && !view.transcriptAllGenes\">\n <ng-container *ngFor=\"let node of geneTree; trackBy: trackByNode\">\n <div class=\"sc-gene-row sc-gene-group\" *ngIf=\"node.name\">\n <button type=\"button\" class=\"sc-eye\" (click)=\"onGenesShown(node.genes, !groupShown.get(node.name))\">\n <i\n class=\"pi\"\n [class.pi-eye]=\"groupShown.get(node.name)\"\n [class.pi-eye-slash]=\"!groupShown.get(node.name)\"\n ></i>\n </button>\n <span class=\"sc-group-label\" [title]=\"node.name\">{{ node.name }}</span>\n <span class=\"sc-count\">({{ node.genes.length }})</span>\n <button type=\"button\" class=\"sc-icon-btn\" (click)=\"toggleGeneGroup(node.name)\">\n <i\n class=\"pi\"\n [class.pi-chevron-down]=\"!collapsedGeneGroups.has(node.name)\"\n [class.pi-chevron-right]=\"collapsedGeneGroups.has(node.name)\"\n ></i>\n </button>\n </div>\n <ng-container *ngIf=\"!node.name || !collapsedGeneGroups.has(node.name)\">\n <div\n class=\"sc-gene-row sc-gene-leaf\"\n [class.nested]=\"!!node.name\"\n *ngFor=\"let gene of node.genes; trackBy: trackByLabelString\"\n >\n <button type=\"button\" class=\"sc-eye\" (click)=\"onGenesShown([gene], !rows.get(gene)?.shown)\">\n <i class=\"pi\" [class.pi-eye]=\"rows.get(gene)?.shown\" [class.pi-eye-slash]=\"!rows.get(gene)?.shown\"></i>\n </button>\n <!-- The gene's marker, in its colour: its icon in Icons mode, a dot for circles.\n Clicking it opens the icon and colour picker (as Xenium Explorer does). -->\n <button\n type=\"button\"\n class=\"sc-gene-icon\"\n [style.color]=\"rows.get(gene)?.swatch\"\n [attr.aria-label]=\"'Icon and colour for ' + gene\"\n pTooltip=\"Icon and colour\"\n tooltipPosition=\"top\"\n (click)=\"openGeneStyle($event, gene, genePop)\"\n >\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon\n *ngIf=\"view.transcriptMode === 'glyphs'; else dotIcon\"\n [attr.points]=\"rows.get(gene)?.points\"\n ></polygon>\n <ng-template #dotIcon><circle r=\"0.75\"></circle></ng-template>\n </svg>\n </button>\n <span class=\"sc-group-label\">{{ gene }}</span>\n <span\n class=\"sc-gene-count\"\n *ngIf=\"rows.get(gene)?.count as n; else zeroCount\"\n title=\"Transcripts in view\"\n >{{ n | number }}</span\n >\n <ng-template #zeroCount>\n <span class=\"sc-gene-count\" *ngIf=\"geneCounts\" title=\"Transcripts in view\">0</span>\n </ng-template>\n </div>\n </ng-container>\n </ng-container>\n </ng-container>\n <!-- One picker for every gene row, filled for the gene that opened it. -->\n <p-overlayPanel #genePop styleClass=\"sc-gene-style\" appendTo=\"body\">\n <ng-template pTemplate=\"content\">\n <spatial-gene-style\n *ngIf=\"styleGene as gene\"\n [gene]=\"gene\"\n what=\"Transcript\"\n [color]=\"geneColorOf(gene)\"\n [glyph]=\"styleGlyph ?? 'circle'\"\n [iconHint]=\"\n view.transcriptMode !== 'glyphs' ? 'Icons show when the transcript point style is Icons.' : null\n \"\n (colorChange)=\"onGeneColor(gene, $event)\"\n (glyphChange)=\"onGlyph(gene, $event)\"\n (resetStyle)=\"resetGeneStyle(gene)\"\n ></spatial-gene-style>\n </ng-template>\n </p-overlayPanel>\n <div class=\"sc-gene-footer\">\n {{ (view.transcriptAllGenes ? geneTotal : view.transcriptGenes.length) | number }}/{{ geneTotal | number }}\n genes selected\n </div>\n</div>\n", styles: [".sc-hint{font-size:.75rem;color:var(--text-color-secondary, #6c757d)}.sc-error{color:var(--red-600, #c62828)}.sc-section{display:flex;flex-direction:column;gap:.35rem}.sc-lbl{font-size:.78rem;color:var(--text-color-secondary, #6c757d);white-space:nowrap}.sc-row{display:flex;align-items:center;gap:.6rem}.sc-row p-slider,.sc-row p-dropdown,.sc-row p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row p-slider .p-slider{width:100%}:host ::ng-deep .sc-row p-dropdown .p-dropdown,:host ::ng-deep .sc-row p-treeSelect .p-treeselect{width:100%}.sc-row .sc-lbl{flex:0 0 calc(50% - .6rem);min-width:0;overflow:hidden;text-overflow:ellipsis}.sc-cmap-option{display:inline-flex;align-items:center;gap:.4rem}.sc-cmap-swatch{width:3.5rem;height:.7rem;border-radius:2px;display:block}.sc-val{flex:0 0 4rem;text-align:right;font-size:.78rem;font-variant-numeric:tabular-nums;white-space:nowrap}:host ::ng-deep .sc-full,:host ::ng-deep .sc-full .p-dropdown,:host ::ng-deep .sc-full .p-autocomplete,:host ::ng-deep .sc-full input{width:100%}.sc-colorbar{height:.75rem;border-radius:2px;border:1px solid rgba(0,0,0,.2)}.sc-colorbar-ends{display:flex;justify-content:space-between;font-size:.7rem;color:var(--text-color-secondary, #6c757d);margin-top:.2rem}.sc-panel{border:1px solid var(--surface-border, #dee2e6);border-radius:6px;margin-bottom:.5rem;overflow:hidden}.sc-panel-head{display:flex;align-items:center;gap:.6rem;padding:.5rem .7rem;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--surface-100, #f5f6f7)}.sc-panel-head .sc-panel-title{flex:1;font-weight:600}.sc-panel.open>.sc-panel-head{background:var(--primary-color, #2196f3);color:var(--primary-color-text, #fff)}.sc-panel-body{display:flex;flex-direction:column;gap:.45rem;padding:.6rem .75rem .75rem}.sc-subhead{display:flex;align-items:center;gap:.5rem;margin-top:.4rem;font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-color-secondary, #6c757d)}.sc-subhead:after{content:\"\";flex:1;border-top:1px solid var(--surface-border, #dee2e6)}:host ::ng-deep .sc-buttons .p-button{padding:.35rem .75rem;font-size:.85rem}.sc-row-picker p-dropdown,.sc-row-picker p-multiSelect,.sc-row-picker p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row-picker .sc-variant{width:6.5rem}:host ::ng-deep .sc-row-picker p-multiselect .p-multiselect{width:100%}:host ::ng-deep .sc-row-picker p-dropdown:has(.sc-variant){flex:0 0 6.5rem}:host ::ng-deep .sc-row-picker p-treeselect:has(.sc-palette){flex:0 0 3rem}:host ::ng-deep .sc-palette .p-treeselect-label{width:0;padding:0}.sc-icon-btn{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:.25rem .35rem;font:inherit;font-size:1.05rem;color:var(--text-color, #333);border-radius:4px}.sc-icon-btn:hover{background:var(--surface-200, #e9ecef)}.sc-icon-btn.active{color:var(--primary-color, #2196f3);font-weight:700}.sc-icon-btn:disabled{opacity:.5;cursor:default}.sc-small-btn{margin-left:auto;border:1px solid var(--surface-border, #ced4da);background:var(--surface-0, #fff);border-radius:4px;padding:.2rem .6rem;font:inherit;font-size:.8rem;cursor:pointer}:host ::ng-deep .sc-group-heading{font-size:.7rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;opacity:.7}.sc-group-list,.sc-gene-tree{max-height:16rem;overflow-y:auto;border:1px solid var(--surface-border, #dee2e6);border-radius:4px;padding:.25rem .4rem}.sc-group-row,.sc-gene-row{display:flex;align-items:center;gap:.45rem;padding:.15rem 0;font-size:.88rem}.sc-group-row .sc-group-label,.sc-gene-row .sc-group-label{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sc-group-all,.sc-gene-root,.sc-gene-group{font-weight:600}.sc-group-all .sc-icon-btn,.sc-gene-root .sc-icon-btn,.sc-gene-group .sc-icon-btn{margin-left:auto;font-size:.85rem}.sc-count{flex:0 0 auto;font-size:.78rem;color:var(--text-color-secondary, #6c757d)}.sc-glyph-option{display:inline-flex;align-items:center;gap:.4rem}.sc-glyph-svg{width:1rem;height:1rem;fill:currentColor}:host ::ng-deep .sc-glyph-pick .p-dropdown-label{padding:.2rem .4rem}.sc-color-input{width:2.5rem;height:1.8rem;border:1px solid var(--surface-border, #ced4da);border-radius:4px;padding:0;background:none}.sc-row-number p-slider,.sc-row-range p-slider{flex:1 1 0;min-width:0}:host ::ng-deep .sc-num{width:4.5rem;padding:.3rem .4rem;text-align:center}:host ::ng-deep .sc-row-number p-inputnumber,:host ::ng-deep .sc-row-range p-inputnumber{flex:0 0 auto}.sc-gene-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:1.4rem;height:1.4rem;padding:0;border:1px solid transparent;border-radius:4px;background:transparent;cursor:pointer}.sc-gene-icon:hover,.sc-gene-icon:focus-visible{border-color:var(--surface-border, rgba(0, 0, 0, .2))}:host{display:contents}.sc-gene-group,.sc-gene-leaf{padding-left:1rem}.sc-gene-leaf.nested{padding-left:2rem}.sc-eye{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:0;color:var(--text-color-secondary, #6c757d)}.sc-eye .pi-eye{color:var(--text-color, #333)}.sc-eye:disabled{cursor:default;opacity:.5}.sc-gene-filter{width:calc(100% - 1rem);margin:.2rem 0 .2rem 1rem;font-size:.8rem;padding:.2rem .4rem}.sc-gene-footer{text-align:right;font-size:.78rem;padding:.2rem 0;color:var(--text-color-secondary, #6c757d)}.sc-gene-count{margin-left:auto;font-variant-numeric:tabular-nums;opacity:.8;padding-left:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }, { kind: "ngmodule", type: SharedModule }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["variant"] }, { kind: "ngmodule", type: OverlayPanelModule }, { kind: "component", type: i4.OverlayPanel, selector: "p-overlayPanel", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "showCloseIcon", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: SpatialGeneStyleComponent, selector: "spatial-gene-style", inputs: ["gene", "what", "color", "glyph", "iconHint"], outputs: ["colorChange", "glyphChange", "resetStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
331
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: SpatialGeneTreeComponent, isStandalone: true, selector: "spatial-gene-tree", inputs: { controls: "controls", dataset: "dataset", view: "view", geneCounts: "geneCounts", geneTotal: "geneTotal" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"sc-subhead\">Selected genes</div>\n<div class=\"sc-gene-sort\" *ngIf=\"sortShown\" role=\"group\" aria-label=\"Sort genes\">\n <span class=\"sc-lbl\">Sort by</span>\n <button\n type=\"button\"\n class=\"sc-sort-btn\"\n [class.active]=\"!byCount\"\n [attr.aria-pressed]=\"!byCount\"\n (click)=\"onGeneSort('name')\"\n >\n Name\n </button>\n <button\n type=\"button\"\n class=\"sc-sort-btn\"\n [class.active]=\"byCount\"\n [attr.aria-pressed]=\"byCount\"\n title=\"Transcripts in view, most first\"\n (click)=\"onGeneSort('count')\"\n >\n Count\n </button>\n</div>\n<div class=\"sc-gene-tree\">\n <div class=\"sc-gene-row sc-gene-root\">\n <button\n type=\"button\"\n class=\"sc-eye\"\n (click)=\"\n view.transcriptAllGenes ? onAllGenesShown(!rootShown) : onGenesShown(view.transcriptGenes, !rootShown)\n \"\n >\n <i class=\"pi\" [class.pi-eye]=\"rootShown\" [class.pi-eye-slash]=\"!rootShown\"></i>\n </button>\n <span class=\"sc-group-label\">Genes</span>\n <span class=\"sc-count\"\n >({{ (view.transcriptAllGenes ? geneTotal : view.transcriptGenes.length) | number }}/{{\n geneTotal | number\n }})</span\n >\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n (click)=\"geneTreeOpen = !geneTreeOpen\"\n *ngIf=\"!view.transcriptAllGenes && view.transcriptGenes.length\"\n >\n <i class=\"pi\" [class.pi-chevron-down]=\"geneTreeOpen\" [class.pi-chevron-right]=\"!geneTreeOpen\"></i>\n </button>\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n (click)=\"toggleAllGenesOpen()\"\n *ngIf=\"view.transcriptAllGenes && allGeneList?.length\"\n [attr.aria-label]=\"allGenesOpen ? 'Hide the gene list' : 'Show every gene'\"\n >\n <i class=\"pi\" [class.pi-chevron-down]=\"allGenesOpen\" [class.pi-chevron-right]=\"!allGenesOpen\"></i>\n </button>\n </div>\n <!-- \"All genes\": every gene of the dataset, each with its eye when the dataset says which\n transcripts are whose (its gene list in code order). -->\n <ng-container *ngIf=\"allGenesOpen && view.transcriptAllGenes && allGeneList?.length\">\n <input\n pInputText\n class=\"sc-gene-filter\"\n placeholder=\"Filter genes\u2026\"\n aria-label=\"Filter genes\"\n [value]=\"allGenesFilter\"\n (input)=\"onAllGenesFilter($any($event.target).value)\"\n />\n <small class=\"sc-hint\" *ngIf=\"!canHideAllGenes\">\n This dataset does not say which transcripts are whose, so its genes cannot be hidden one by one.\n </small>\n <small class=\"sc-hint\" *ngIf=\"canHideAllGenes && view.transcriptMode === 'density'\">\n The density map draws every gene as one raster: genes are hidden one by one as circles or icons.\n </small>\n <div class=\"sc-gene-row sc-gene-leaf nested\" *ngFor=\"let row of allRows; trackBy: trackByAllRow\">\n <button\n type=\"button\"\n class=\"sc-eye\"\n [disabled]=\"!canHideAllGenes || view.transcriptMode === 'density'\"\n (click)=\"onAllGeneShown(row.gene, !row.shown)\"\n >\n <i class=\"pi\" [class.pi-eye]=\"row.shown\" [class.pi-eye-slash]=\"!row.shown\"></i>\n </button>\n <span class=\"sc-gene-icon\" *ngIf=\"row.swatch\" [style.color]=\"row.swatch\" aria-hidden=\"true\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\"><circle r=\"0.75\"></circle></svg>\n </span>\n <span class=\"sc-group-label\" [title]=\"row.gene\">{{ row.gene }}</span>\n <span class=\"sc-gene-count\" *ngIf=\"row.count !== null\" title=\"Transcripts in view\">{{\n row.count | number\n }}</span>\n </div>\n <small class=\"sc-hint\" *ngIf=\"allGenesMatched > allRows.length\">\n Showing {{ allRows.length | number }} of {{ allGenesMatched | number }} genes: filter to find the others.\n </small>\n <small class=\"sc-hint\" *ngIf=\"allGenesMatched === 0\">No gene matches.</small>\n </ng-container>\n <ng-container *ngIf=\"geneTreeOpen && !view.transcriptAllGenes\">\n <ng-container *ngFor=\"let node of sortedTree; trackBy: trackByNode\">\n <div class=\"sc-gene-row sc-gene-group\" *ngIf=\"node.name\">\n <button type=\"button\" class=\"sc-eye\" (click)=\"onGenesShown(node.genes, !groupShown.get(node.name))\">\n <i\n class=\"pi\"\n [class.pi-eye]=\"groupShown.get(node.name)\"\n [class.pi-eye-slash]=\"!groupShown.get(node.name)\"\n ></i>\n </button>\n <span class=\"sc-group-label\" [title]=\"node.name\">{{ node.name }}</span>\n <span class=\"sc-count\">({{ node.genes.length }})</span>\n <button type=\"button\" class=\"sc-icon-btn\" (click)=\"toggleGeneGroup(node.name)\">\n <i\n class=\"pi\"\n [class.pi-chevron-down]=\"!collapsedGeneGroups.has(node.name)\"\n [class.pi-chevron-right]=\"collapsedGeneGroups.has(node.name)\"\n ></i>\n </button>\n </div>\n <ng-container *ngIf=\"!node.name || !collapsedGeneGroups.has(node.name)\">\n <div\n class=\"sc-gene-row sc-gene-leaf\"\n [class.nested]=\"!!node.name\"\n *ngFor=\"let gene of node.genes; trackBy: trackByLabelString\"\n >\n <button type=\"button\" class=\"sc-eye\" (click)=\"onGenesShown([gene], !rows.get(gene)?.shown)\">\n <i class=\"pi\" [class.pi-eye]=\"rows.get(gene)?.shown\" [class.pi-eye-slash]=\"!rows.get(gene)?.shown\"></i>\n </button>\n <!-- The gene's marker, in its colour: its icon in Icons mode, a dot for circles.\n Clicking it opens the icon and colour picker (as Xenium Explorer does). -->\n <button\n type=\"button\"\n class=\"sc-gene-icon\"\n [style.color]=\"rows.get(gene)?.swatch\"\n [attr.aria-label]=\"'Icon and colour for ' + gene\"\n pTooltip=\"Icon and colour\"\n tooltipPosition=\"top\"\n (click)=\"openGeneStyle($event, gene, genePop)\"\n >\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon\n *ngIf=\"view.transcriptMode === 'glyphs'; else dotIcon\"\n [attr.points]=\"rows.get(gene)?.points\"\n ></polygon>\n <ng-template #dotIcon><circle r=\"0.75\"></circle></ng-template>\n </svg>\n </button>\n <span class=\"sc-group-label\">{{ gene }}</span>\n <span\n class=\"sc-gene-count\"\n *ngIf=\"rows.get(gene)?.count as n; else zeroCount\"\n title=\"Transcripts in view\"\n >{{ n | number }}</span\n >\n <ng-template #zeroCount>\n <span class=\"sc-gene-count\" *ngIf=\"geneCounts\" title=\"Transcripts in view\">0</span>\n </ng-template>\n </div>\n </ng-container>\n </ng-container>\n </ng-container>\n <!-- One picker for every gene row, filled for the gene that opened it. -->\n <p-overlayPanel #genePop styleClass=\"sc-gene-style\" appendTo=\"body\">\n <ng-template pTemplate=\"content\">\n <spatial-gene-style\n *ngIf=\"styleGene as gene\"\n [gene]=\"gene\"\n what=\"Transcript\"\n [color]=\"geneColorOf(gene)\"\n [glyph]=\"styleGlyph ?? 'circle'\"\n [iconHint]=\"\n view.transcriptMode !== 'glyphs' ? 'Icons show when the transcript point style is Icons.' : null\n \"\n (colorChange)=\"onGeneColor(gene, $event)\"\n (glyphChange)=\"onGlyph(gene, $event)\"\n (resetStyle)=\"resetGeneStyle(gene)\"\n ></spatial-gene-style>\n </ng-template>\n </p-overlayPanel>\n <div class=\"sc-gene-footer\">\n {{ (view.transcriptAllGenes ? geneTotal : view.transcriptGenes.length) | number }}/{{ geneTotal | number }}\n genes selected\n </div>\n</div>\n", styles: [".sc-hint{font-size:.75rem;color:var(--text-color-secondary, #6c757d)}.sc-error{color:var(--red-600, #c62828)}.sc-section{display:flex;flex-direction:column;gap:.35rem}.sc-lbl{font-size:.78rem;color:var(--text-color-secondary, #6c757d);white-space:nowrap}.sc-row{display:flex;align-items:center;gap:.6rem}.sc-row p-slider,.sc-row p-dropdown,.sc-row p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row p-slider .p-slider{width:100%}:host ::ng-deep .sc-row p-dropdown .p-dropdown,:host ::ng-deep .sc-row p-treeSelect .p-treeselect{width:100%}.sc-row .sc-lbl{flex:0 0 calc(50% - .6rem);min-width:0;overflow:hidden;text-overflow:ellipsis}.sc-cmap-option{display:inline-flex;align-items:center;gap:.4rem}.sc-cmap-swatch{width:3.5rem;height:.7rem;border-radius:2px;display:block}.sc-val{flex:0 0 4rem;text-align:right;font-size:.78rem;font-variant-numeric:tabular-nums;white-space:nowrap}:host ::ng-deep .sc-full,:host ::ng-deep .sc-full .p-dropdown,:host ::ng-deep .sc-full .p-autocomplete,:host ::ng-deep .sc-full input{width:100%}.sc-colorbar{height:.75rem;border-radius:2px;border:1px solid rgba(0,0,0,.2)}.sc-colorbar-ends{display:flex;justify-content:space-between;font-size:.7rem;color:var(--text-color-secondary, #6c757d);margin-top:.2rem}.sc-panel{border:1px solid var(--surface-border, #dee2e6);border-radius:6px;margin-bottom:.5rem;overflow:hidden}.sc-panel-head{display:flex;align-items:center;gap:.6rem;padding:.5rem .7rem;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--surface-100, #f5f6f7)}.sc-panel-head .sc-panel-title{flex:1;font-weight:600}.sc-panel.open>.sc-panel-head{background:var(--primary-color, #2196f3);color:var(--primary-color-text, #fff)}.sc-panel-body{display:flex;flex-direction:column;gap:.45rem;padding:.6rem .75rem .75rem}.sc-subhead{display:flex;align-items:center;gap:.5rem;margin-top:.4rem;font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-color-secondary, #6c757d)}.sc-subhead:after{content:\"\";flex:1;border-top:1px solid var(--surface-border, #dee2e6)}:host ::ng-deep .sc-buttons .p-button{padding:.35rem .75rem;font-size:.85rem}.sc-row-picker p-dropdown,.sc-row-picker p-multiSelect,.sc-row-picker p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row-picker .sc-variant{width:6.5rem}:host ::ng-deep .sc-row-picker p-multiselect .p-multiselect{width:100%}:host ::ng-deep .sc-row-picker p-dropdown:has(.sc-variant){flex:0 0 6.5rem}:host ::ng-deep .sc-row-picker p-treeselect:has(.sc-palette){flex:0 0 3rem}:host ::ng-deep .sc-palette .p-treeselect-label{width:0;padding:0}.sc-icon-btn{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:.25rem .35rem;font:inherit;font-size:1.05rem;color:var(--text-color, #333);border-radius:4px}.sc-icon-btn:hover{background:var(--surface-200, #e9ecef)}.sc-icon-btn.active{color:var(--primary-color, #2196f3);font-weight:700}.sc-icon-btn:disabled{opacity:.5;cursor:default}.sc-small-btn{margin-left:auto;border:1px solid var(--surface-border, #ced4da);background:var(--surface-0, #fff);border-radius:4px;padding:.2rem .6rem;font:inherit;font-size:.8rem;cursor:pointer}:host ::ng-deep .sc-group-heading{font-size:.7rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;opacity:.7}.sc-group-list,.sc-gene-tree{max-height:16rem;overflow-y:auto;border:1px solid var(--surface-border, #dee2e6);border-radius:4px;padding:.25rem .4rem}.sc-group-row,.sc-gene-row{display:flex;align-items:center;gap:.45rem;padding:.15rem 0;font-size:.88rem}.sc-group-row .sc-group-label,.sc-gene-row .sc-group-label{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sc-group-all,.sc-gene-root,.sc-gene-group{font-weight:600}.sc-group-all .sc-icon-btn,.sc-gene-root .sc-icon-btn,.sc-gene-group .sc-icon-btn{margin-left:auto;font-size:.85rem}.sc-count{flex:0 0 auto;font-size:.78rem;color:var(--text-color-secondary, #6c757d)}.sc-glyph-option{display:inline-flex;align-items:center;gap:.4rem}.sc-glyph-svg{width:1rem;height:1rem;fill:currentColor}:host ::ng-deep .sc-glyph-pick .p-dropdown-label{padding:.2rem .4rem}.sc-color-input{width:2.5rem;height:1.8rem;border:1px solid var(--surface-border, #ced4da);border-radius:4px;padding:0;background:none}.sc-row-number p-slider,.sc-row-range p-slider{flex:1 1 0;min-width:0}:host ::ng-deep .sc-num{width:4.5rem;padding:.3rem .4rem;text-align:center}:host ::ng-deep .sc-row-number p-inputnumber,:host ::ng-deep .sc-row-range p-inputnumber{flex:0 0 auto}.sc-gene-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:1.4rem;height:1.4rem;padding:0;border:1px solid transparent;border-radius:4px;background:transparent;cursor:pointer}.sc-gene-icon:hover,.sc-gene-icon:focus-visible{border-color:var(--surface-border, rgba(0, 0, 0, .2))}:host{display:contents}.sc-gene-group,.sc-gene-leaf{padding-left:1rem}.sc-gene-leaf.nested{padding-left:2rem}.sc-eye{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:0;color:var(--text-color-secondary, #6c757d)}.sc-eye .pi-eye{color:var(--text-color, #333)}.sc-eye:disabled{cursor:default;opacity:.5}.sc-gene-sort{display:flex;align-items:center;gap:.25rem;font-size:.8rem}.sc-gene-sort .sc-lbl{margin-right:auto}.sc-sort-btn{border:1px solid var(--surface-border, #ced4da);background:var(--surface-0, #fff);color:var(--text-color, #333);border-radius:4px;padding:.1rem .5rem;font:inherit;cursor:pointer}.sc-sort-btn.active{border-color:var(--primary-color, #2196f3);color:var(--primary-color, #2196f3);font-weight:600}.sc-gene-filter{width:calc(100% - 1rem);margin:.2rem 0 .2rem 1rem;font-size:.8rem;padding:.2rem .4rem}.sc-gene-footer{text-align:right;font-size:.78rem;padding:.2rem 0;color:var(--text-color-secondary, #6c757d)}.sc-gene-count{margin-left:auto;font-variant-numeric:tabular-nums;opacity:.8;padding-left:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }, { kind: "ngmodule", type: SharedModule }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["variant"] }, { kind: "ngmodule", type: OverlayPanelModule }, { kind: "component", type: i4.OverlayPanel, selector: "p-overlayPanel", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "showCloseIcon", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: SpatialGeneStyleComponent, selector: "spatial-gene-style", inputs: ["gene", "what", "color", "glyph", "iconHint"], outputs: ["colorChange", "glyphChange", "resetStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
299
332
  }
300
333
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SpatialGeneTreeComponent, decorators: [{
301
334
  type: Component,
@@ -306,7 +339,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
306
339
  OverlayPanelModule,
307
340
  TooltipModule,
308
341
  SpatialGeneStyleComponent,
309
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sc-subhead\">Selected genes</div>\n<div class=\"sc-gene-tree\">\n <div class=\"sc-gene-row sc-gene-root\">\n <button\n type=\"button\"\n class=\"sc-eye\"\n (click)=\"\n view.transcriptAllGenes ? onAllGenesShown(!rootShown) : onGenesShown(view.transcriptGenes, !rootShown)\n \"\n >\n <i class=\"pi\" [class.pi-eye]=\"rootShown\" [class.pi-eye-slash]=\"!rootShown\"></i>\n </button>\n <span class=\"sc-group-label\">Genes</span>\n <span class=\"sc-count\"\n >({{ (view.transcriptAllGenes ? geneTotal : view.transcriptGenes.length) | number }}/{{\n geneTotal | number\n }})</span\n >\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n (click)=\"geneTreeOpen = !geneTreeOpen\"\n *ngIf=\"!view.transcriptAllGenes && view.transcriptGenes.length\"\n >\n <i class=\"pi\" [class.pi-chevron-down]=\"geneTreeOpen\" [class.pi-chevron-right]=\"!geneTreeOpen\"></i>\n </button>\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n (click)=\"toggleAllGenesOpen()\"\n *ngIf=\"view.transcriptAllGenes && allGeneList?.length\"\n [attr.aria-label]=\"allGenesOpen ? 'Hide the gene list' : 'Show every gene'\"\n >\n <i class=\"pi\" [class.pi-chevron-down]=\"allGenesOpen\" [class.pi-chevron-right]=\"!allGenesOpen\"></i>\n </button>\n </div>\n <!-- \"All genes\": every gene of the dataset, each with its eye when the dataset says which\n transcripts are whose (its gene list in code order). -->\n <ng-container *ngIf=\"allGenesOpen && view.transcriptAllGenes && allGeneList?.length\">\n <input\n pInputText\n class=\"sc-gene-filter\"\n placeholder=\"Filter genes\u2026\"\n aria-label=\"Filter genes\"\n [value]=\"allGenesFilter\"\n (input)=\"onAllGenesFilter($any($event.target).value)\"\n />\n <small class=\"sc-hint\" *ngIf=\"!canHideAllGenes\">\n This dataset does not say which transcripts are whose, so its genes cannot be hidden one by one.\n </small>\n <small class=\"sc-hint\" *ngIf=\"canHideAllGenes && view.transcriptMode === 'density'\">\n The density map draws every gene as one raster: genes are hidden one by one as circles or icons.\n </small>\n <div class=\"sc-gene-row sc-gene-leaf nested\" *ngFor=\"let row of allRows; trackBy: trackByAllRow\">\n <button\n type=\"button\"\n class=\"sc-eye\"\n [disabled]=\"!canHideAllGenes || view.transcriptMode === 'density'\"\n (click)=\"onAllGeneShown(row.gene, !row.shown)\"\n >\n <i class=\"pi\" [class.pi-eye]=\"row.shown\" [class.pi-eye-slash]=\"!row.shown\"></i>\n </button>\n <span class=\"sc-gene-icon\" *ngIf=\"row.swatch\" [style.color]=\"row.swatch\" aria-hidden=\"true\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\"><circle r=\"0.75\"></circle></svg>\n </span>\n <span class=\"sc-group-label\" [title]=\"row.gene\">{{ row.gene }}</span>\n <span class=\"sc-gene-count\" *ngIf=\"row.count !== null\" title=\"Transcripts in view\">{{\n row.count | number\n }}</span>\n </div>\n <small class=\"sc-hint\" *ngIf=\"allGenesMatched > allRows.length\">\n Showing {{ allRows.length | number }} of {{ allGenesMatched | number }} genes: filter to find the others.\n </small>\n <small class=\"sc-hint\" *ngIf=\"allGenesMatched === 0\">No gene matches.</small>\n </ng-container>\n <ng-container *ngIf=\"geneTreeOpen && !view.transcriptAllGenes\">\n <ng-container *ngFor=\"let node of geneTree; trackBy: trackByNode\">\n <div class=\"sc-gene-row sc-gene-group\" *ngIf=\"node.name\">\n <button type=\"button\" class=\"sc-eye\" (click)=\"onGenesShown(node.genes, !groupShown.get(node.name))\">\n <i\n class=\"pi\"\n [class.pi-eye]=\"groupShown.get(node.name)\"\n [class.pi-eye-slash]=\"!groupShown.get(node.name)\"\n ></i>\n </button>\n <span class=\"sc-group-label\" [title]=\"node.name\">{{ node.name }}</span>\n <span class=\"sc-count\">({{ node.genes.length }})</span>\n <button type=\"button\" class=\"sc-icon-btn\" (click)=\"toggleGeneGroup(node.name)\">\n <i\n class=\"pi\"\n [class.pi-chevron-down]=\"!collapsedGeneGroups.has(node.name)\"\n [class.pi-chevron-right]=\"collapsedGeneGroups.has(node.name)\"\n ></i>\n </button>\n </div>\n <ng-container *ngIf=\"!node.name || !collapsedGeneGroups.has(node.name)\">\n <div\n class=\"sc-gene-row sc-gene-leaf\"\n [class.nested]=\"!!node.name\"\n *ngFor=\"let gene of node.genes; trackBy: trackByLabelString\"\n >\n <button type=\"button\" class=\"sc-eye\" (click)=\"onGenesShown([gene], !rows.get(gene)?.shown)\">\n <i class=\"pi\" [class.pi-eye]=\"rows.get(gene)?.shown\" [class.pi-eye-slash]=\"!rows.get(gene)?.shown\"></i>\n </button>\n <!-- The gene's marker, in its colour: its icon in Icons mode, a dot for circles.\n Clicking it opens the icon and colour picker (as Xenium Explorer does). -->\n <button\n type=\"button\"\n class=\"sc-gene-icon\"\n [style.color]=\"rows.get(gene)?.swatch\"\n [attr.aria-label]=\"'Icon and colour for ' + gene\"\n pTooltip=\"Icon and colour\"\n tooltipPosition=\"top\"\n (click)=\"openGeneStyle($event, gene, genePop)\"\n >\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon\n *ngIf=\"view.transcriptMode === 'glyphs'; else dotIcon\"\n [attr.points]=\"rows.get(gene)?.points\"\n ></polygon>\n <ng-template #dotIcon><circle r=\"0.75\"></circle></ng-template>\n </svg>\n </button>\n <span class=\"sc-group-label\">{{ gene }}</span>\n <span\n class=\"sc-gene-count\"\n *ngIf=\"rows.get(gene)?.count as n; else zeroCount\"\n title=\"Transcripts in view\"\n >{{ n | number }}</span\n >\n <ng-template #zeroCount>\n <span class=\"sc-gene-count\" *ngIf=\"geneCounts\" title=\"Transcripts in view\">0</span>\n </ng-template>\n </div>\n </ng-container>\n </ng-container>\n </ng-container>\n <!-- One picker for every gene row, filled for the gene that opened it. -->\n <p-overlayPanel #genePop styleClass=\"sc-gene-style\" appendTo=\"body\">\n <ng-template pTemplate=\"content\">\n <spatial-gene-style\n *ngIf=\"styleGene as gene\"\n [gene]=\"gene\"\n what=\"Transcript\"\n [color]=\"geneColorOf(gene)\"\n [glyph]=\"styleGlyph ?? 'circle'\"\n [iconHint]=\"\n view.transcriptMode !== 'glyphs' ? 'Icons show when the transcript point style is Icons.' : null\n \"\n (colorChange)=\"onGeneColor(gene, $event)\"\n (glyphChange)=\"onGlyph(gene, $event)\"\n (resetStyle)=\"resetGeneStyle(gene)\"\n ></spatial-gene-style>\n </ng-template>\n </p-overlayPanel>\n <div class=\"sc-gene-footer\">\n {{ (view.transcriptAllGenes ? geneTotal : view.transcriptGenes.length) | number }}/{{ geneTotal | number }}\n genes selected\n </div>\n</div>\n", styles: [".sc-hint{font-size:.75rem;color:var(--text-color-secondary, #6c757d)}.sc-error{color:var(--red-600, #c62828)}.sc-section{display:flex;flex-direction:column;gap:.35rem}.sc-lbl{font-size:.78rem;color:var(--text-color-secondary, #6c757d);white-space:nowrap}.sc-row{display:flex;align-items:center;gap:.6rem}.sc-row p-slider,.sc-row p-dropdown,.sc-row p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row p-slider .p-slider{width:100%}:host ::ng-deep .sc-row p-dropdown .p-dropdown,:host ::ng-deep .sc-row p-treeSelect .p-treeselect{width:100%}.sc-row .sc-lbl{flex:0 0 calc(50% - .6rem);min-width:0;overflow:hidden;text-overflow:ellipsis}.sc-cmap-option{display:inline-flex;align-items:center;gap:.4rem}.sc-cmap-swatch{width:3.5rem;height:.7rem;border-radius:2px;display:block}.sc-val{flex:0 0 4rem;text-align:right;font-size:.78rem;font-variant-numeric:tabular-nums;white-space:nowrap}:host ::ng-deep .sc-full,:host ::ng-deep .sc-full .p-dropdown,:host ::ng-deep .sc-full .p-autocomplete,:host ::ng-deep .sc-full input{width:100%}.sc-colorbar{height:.75rem;border-radius:2px;border:1px solid rgba(0,0,0,.2)}.sc-colorbar-ends{display:flex;justify-content:space-between;font-size:.7rem;color:var(--text-color-secondary, #6c757d);margin-top:.2rem}.sc-panel{border:1px solid var(--surface-border, #dee2e6);border-radius:6px;margin-bottom:.5rem;overflow:hidden}.sc-panel-head{display:flex;align-items:center;gap:.6rem;padding:.5rem .7rem;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--surface-100, #f5f6f7)}.sc-panel-head .sc-panel-title{flex:1;font-weight:600}.sc-panel.open>.sc-panel-head{background:var(--primary-color, #2196f3);color:var(--primary-color-text, #fff)}.sc-panel-body{display:flex;flex-direction:column;gap:.45rem;padding:.6rem .75rem .75rem}.sc-subhead{display:flex;align-items:center;gap:.5rem;margin-top:.4rem;font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-color-secondary, #6c757d)}.sc-subhead:after{content:\"\";flex:1;border-top:1px solid var(--surface-border, #dee2e6)}:host ::ng-deep .sc-buttons .p-button{padding:.35rem .75rem;font-size:.85rem}.sc-row-picker p-dropdown,.sc-row-picker p-multiSelect,.sc-row-picker p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row-picker .sc-variant{width:6.5rem}:host ::ng-deep .sc-row-picker p-multiselect .p-multiselect{width:100%}:host ::ng-deep .sc-row-picker p-dropdown:has(.sc-variant){flex:0 0 6.5rem}:host ::ng-deep .sc-row-picker p-treeselect:has(.sc-palette){flex:0 0 3rem}:host ::ng-deep .sc-palette .p-treeselect-label{width:0;padding:0}.sc-icon-btn{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:.25rem .35rem;font:inherit;font-size:1.05rem;color:var(--text-color, #333);border-radius:4px}.sc-icon-btn:hover{background:var(--surface-200, #e9ecef)}.sc-icon-btn.active{color:var(--primary-color, #2196f3);font-weight:700}.sc-icon-btn:disabled{opacity:.5;cursor:default}.sc-small-btn{margin-left:auto;border:1px solid var(--surface-border, #ced4da);background:var(--surface-0, #fff);border-radius:4px;padding:.2rem .6rem;font:inherit;font-size:.8rem;cursor:pointer}:host ::ng-deep .sc-group-heading{font-size:.7rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;opacity:.7}.sc-group-list,.sc-gene-tree{max-height:16rem;overflow-y:auto;border:1px solid var(--surface-border, #dee2e6);border-radius:4px;padding:.25rem .4rem}.sc-group-row,.sc-gene-row{display:flex;align-items:center;gap:.45rem;padding:.15rem 0;font-size:.88rem}.sc-group-row .sc-group-label,.sc-gene-row .sc-group-label{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sc-group-all,.sc-gene-root,.sc-gene-group{font-weight:600}.sc-group-all .sc-icon-btn,.sc-gene-root .sc-icon-btn,.sc-gene-group .sc-icon-btn{margin-left:auto;font-size:.85rem}.sc-count{flex:0 0 auto;font-size:.78rem;color:var(--text-color-secondary, #6c757d)}.sc-glyph-option{display:inline-flex;align-items:center;gap:.4rem}.sc-glyph-svg{width:1rem;height:1rem;fill:currentColor}:host ::ng-deep .sc-glyph-pick .p-dropdown-label{padding:.2rem .4rem}.sc-color-input{width:2.5rem;height:1.8rem;border:1px solid var(--surface-border, #ced4da);border-radius:4px;padding:0;background:none}.sc-row-number p-slider,.sc-row-range p-slider{flex:1 1 0;min-width:0}:host ::ng-deep .sc-num{width:4.5rem;padding:.3rem .4rem;text-align:center}:host ::ng-deep .sc-row-number p-inputnumber,:host ::ng-deep .sc-row-range p-inputnumber{flex:0 0 auto}.sc-gene-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:1.4rem;height:1.4rem;padding:0;border:1px solid transparent;border-radius:4px;background:transparent;cursor:pointer}.sc-gene-icon:hover,.sc-gene-icon:focus-visible{border-color:var(--surface-border, rgba(0, 0, 0, .2))}:host{display:contents}.sc-gene-group,.sc-gene-leaf{padding-left:1rem}.sc-gene-leaf.nested{padding-left:2rem}.sc-eye{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:0;color:var(--text-color-secondary, #6c757d)}.sc-eye .pi-eye{color:var(--text-color, #333)}.sc-eye:disabled{cursor:default;opacity:.5}.sc-gene-filter{width:calc(100% - 1rem);margin:.2rem 0 .2rem 1rem;font-size:.8rem;padding:.2rem .4rem}.sc-gene-footer{text-align:right;font-size:.78rem;padding:.2rem 0;color:var(--text-color-secondary, #6c757d)}.sc-gene-count{margin-left:auto;font-variant-numeric:tabular-nums;opacity:.8;padding-left:.5rem}\n"] }]
342
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sc-subhead\">Selected genes</div>\n<div class=\"sc-gene-sort\" *ngIf=\"sortShown\" role=\"group\" aria-label=\"Sort genes\">\n <span class=\"sc-lbl\">Sort by</span>\n <button\n type=\"button\"\n class=\"sc-sort-btn\"\n [class.active]=\"!byCount\"\n [attr.aria-pressed]=\"!byCount\"\n (click)=\"onGeneSort('name')\"\n >\n Name\n </button>\n <button\n type=\"button\"\n class=\"sc-sort-btn\"\n [class.active]=\"byCount\"\n [attr.aria-pressed]=\"byCount\"\n title=\"Transcripts in view, most first\"\n (click)=\"onGeneSort('count')\"\n >\n Count\n </button>\n</div>\n<div class=\"sc-gene-tree\">\n <div class=\"sc-gene-row sc-gene-root\">\n <button\n type=\"button\"\n class=\"sc-eye\"\n (click)=\"\n view.transcriptAllGenes ? onAllGenesShown(!rootShown) : onGenesShown(view.transcriptGenes, !rootShown)\n \"\n >\n <i class=\"pi\" [class.pi-eye]=\"rootShown\" [class.pi-eye-slash]=\"!rootShown\"></i>\n </button>\n <span class=\"sc-group-label\">Genes</span>\n <span class=\"sc-count\"\n >({{ (view.transcriptAllGenes ? geneTotal : view.transcriptGenes.length) | number }}/{{\n geneTotal | number\n }})</span\n >\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n (click)=\"geneTreeOpen = !geneTreeOpen\"\n *ngIf=\"!view.transcriptAllGenes && view.transcriptGenes.length\"\n >\n <i class=\"pi\" [class.pi-chevron-down]=\"geneTreeOpen\" [class.pi-chevron-right]=\"!geneTreeOpen\"></i>\n </button>\n <button\n type=\"button\"\n class=\"sc-icon-btn\"\n (click)=\"toggleAllGenesOpen()\"\n *ngIf=\"view.transcriptAllGenes && allGeneList?.length\"\n [attr.aria-label]=\"allGenesOpen ? 'Hide the gene list' : 'Show every gene'\"\n >\n <i class=\"pi\" [class.pi-chevron-down]=\"allGenesOpen\" [class.pi-chevron-right]=\"!allGenesOpen\"></i>\n </button>\n </div>\n <!-- \"All genes\": every gene of the dataset, each with its eye when the dataset says which\n transcripts are whose (its gene list in code order). -->\n <ng-container *ngIf=\"allGenesOpen && view.transcriptAllGenes && allGeneList?.length\">\n <input\n pInputText\n class=\"sc-gene-filter\"\n placeholder=\"Filter genes\u2026\"\n aria-label=\"Filter genes\"\n [value]=\"allGenesFilter\"\n (input)=\"onAllGenesFilter($any($event.target).value)\"\n />\n <small class=\"sc-hint\" *ngIf=\"!canHideAllGenes\">\n This dataset does not say which transcripts are whose, so its genes cannot be hidden one by one.\n </small>\n <small class=\"sc-hint\" *ngIf=\"canHideAllGenes && view.transcriptMode === 'density'\">\n The density map draws every gene as one raster: genes are hidden one by one as circles or icons.\n </small>\n <div class=\"sc-gene-row sc-gene-leaf nested\" *ngFor=\"let row of allRows; trackBy: trackByAllRow\">\n <button\n type=\"button\"\n class=\"sc-eye\"\n [disabled]=\"!canHideAllGenes || view.transcriptMode === 'density'\"\n (click)=\"onAllGeneShown(row.gene, !row.shown)\"\n >\n <i class=\"pi\" [class.pi-eye]=\"row.shown\" [class.pi-eye-slash]=\"!row.shown\"></i>\n </button>\n <span class=\"sc-gene-icon\" *ngIf=\"row.swatch\" [style.color]=\"row.swatch\" aria-hidden=\"true\">\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\"><circle r=\"0.75\"></circle></svg>\n </span>\n <span class=\"sc-group-label\" [title]=\"row.gene\">{{ row.gene }}</span>\n <span class=\"sc-gene-count\" *ngIf=\"row.count !== null\" title=\"Transcripts in view\">{{\n row.count | number\n }}</span>\n </div>\n <small class=\"sc-hint\" *ngIf=\"allGenesMatched > allRows.length\">\n Showing {{ allRows.length | number }} of {{ allGenesMatched | number }} genes: filter to find the others.\n </small>\n <small class=\"sc-hint\" *ngIf=\"allGenesMatched === 0\">No gene matches.</small>\n </ng-container>\n <ng-container *ngIf=\"geneTreeOpen && !view.transcriptAllGenes\">\n <ng-container *ngFor=\"let node of sortedTree; trackBy: trackByNode\">\n <div class=\"sc-gene-row sc-gene-group\" *ngIf=\"node.name\">\n <button type=\"button\" class=\"sc-eye\" (click)=\"onGenesShown(node.genes, !groupShown.get(node.name))\">\n <i\n class=\"pi\"\n [class.pi-eye]=\"groupShown.get(node.name)\"\n [class.pi-eye-slash]=\"!groupShown.get(node.name)\"\n ></i>\n </button>\n <span class=\"sc-group-label\" [title]=\"node.name\">{{ node.name }}</span>\n <span class=\"sc-count\">({{ node.genes.length }})</span>\n <button type=\"button\" class=\"sc-icon-btn\" (click)=\"toggleGeneGroup(node.name)\">\n <i\n class=\"pi\"\n [class.pi-chevron-down]=\"!collapsedGeneGroups.has(node.name)\"\n [class.pi-chevron-right]=\"collapsedGeneGroups.has(node.name)\"\n ></i>\n </button>\n </div>\n <ng-container *ngIf=\"!node.name || !collapsedGeneGroups.has(node.name)\">\n <div\n class=\"sc-gene-row sc-gene-leaf\"\n [class.nested]=\"!!node.name\"\n *ngFor=\"let gene of node.genes; trackBy: trackByLabelString\"\n >\n <button type=\"button\" class=\"sc-eye\" (click)=\"onGenesShown([gene], !rows.get(gene)?.shown)\">\n <i class=\"pi\" [class.pi-eye]=\"rows.get(gene)?.shown\" [class.pi-eye-slash]=\"!rows.get(gene)?.shown\"></i>\n </button>\n <!-- The gene's marker, in its colour: its icon in Icons mode, a dot for circles.\n Clicking it opens the icon and colour picker (as Xenium Explorer does). -->\n <button\n type=\"button\"\n class=\"sc-gene-icon\"\n [style.color]=\"rows.get(gene)?.swatch\"\n [attr.aria-label]=\"'Icon and colour for ' + gene\"\n pTooltip=\"Icon and colour\"\n tooltipPosition=\"top\"\n (click)=\"openGeneStyle($event, gene, genePop)\"\n >\n <svg viewBox=\"-1.2 -1.2 2.4 2.4\" class=\"sc-glyph-svg\">\n <polygon\n *ngIf=\"view.transcriptMode === 'glyphs'; else dotIcon\"\n [attr.points]=\"rows.get(gene)?.points\"\n ></polygon>\n <ng-template #dotIcon><circle r=\"0.75\"></circle></ng-template>\n </svg>\n </button>\n <span class=\"sc-group-label\">{{ gene }}</span>\n <span\n class=\"sc-gene-count\"\n *ngIf=\"rows.get(gene)?.count as n; else zeroCount\"\n title=\"Transcripts in view\"\n >{{ n | number }}</span\n >\n <ng-template #zeroCount>\n <span class=\"sc-gene-count\" *ngIf=\"geneCounts\" title=\"Transcripts in view\">0</span>\n </ng-template>\n </div>\n </ng-container>\n </ng-container>\n </ng-container>\n <!-- One picker for every gene row, filled for the gene that opened it. -->\n <p-overlayPanel #genePop styleClass=\"sc-gene-style\" appendTo=\"body\">\n <ng-template pTemplate=\"content\">\n <spatial-gene-style\n *ngIf=\"styleGene as gene\"\n [gene]=\"gene\"\n what=\"Transcript\"\n [color]=\"geneColorOf(gene)\"\n [glyph]=\"styleGlyph ?? 'circle'\"\n [iconHint]=\"\n view.transcriptMode !== 'glyphs' ? 'Icons show when the transcript point style is Icons.' : null\n \"\n (colorChange)=\"onGeneColor(gene, $event)\"\n (glyphChange)=\"onGlyph(gene, $event)\"\n (resetStyle)=\"resetGeneStyle(gene)\"\n ></spatial-gene-style>\n </ng-template>\n </p-overlayPanel>\n <div class=\"sc-gene-footer\">\n {{ (view.transcriptAllGenes ? geneTotal : view.transcriptGenes.length) | number }}/{{ geneTotal | number }}\n genes selected\n </div>\n</div>\n", styles: [".sc-hint{font-size:.75rem;color:var(--text-color-secondary, #6c757d)}.sc-error{color:var(--red-600, #c62828)}.sc-section{display:flex;flex-direction:column;gap:.35rem}.sc-lbl{font-size:.78rem;color:var(--text-color-secondary, #6c757d);white-space:nowrap}.sc-row{display:flex;align-items:center;gap:.6rem}.sc-row p-slider,.sc-row p-dropdown,.sc-row p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row p-slider .p-slider{width:100%}:host ::ng-deep .sc-row p-dropdown .p-dropdown,:host ::ng-deep .sc-row p-treeSelect .p-treeselect{width:100%}.sc-row .sc-lbl{flex:0 0 calc(50% - .6rem);min-width:0;overflow:hidden;text-overflow:ellipsis}.sc-cmap-option{display:inline-flex;align-items:center;gap:.4rem}.sc-cmap-swatch{width:3.5rem;height:.7rem;border-radius:2px;display:block}.sc-val{flex:0 0 4rem;text-align:right;font-size:.78rem;font-variant-numeric:tabular-nums;white-space:nowrap}:host ::ng-deep .sc-full,:host ::ng-deep .sc-full .p-dropdown,:host ::ng-deep .sc-full .p-autocomplete,:host ::ng-deep .sc-full input{width:100%}.sc-colorbar{height:.75rem;border-radius:2px;border:1px solid rgba(0,0,0,.2)}.sc-colorbar-ends{display:flex;justify-content:space-between;font-size:.7rem;color:var(--text-color-secondary, #6c757d);margin-top:.2rem}.sc-panel{border:1px solid var(--surface-border, #dee2e6);border-radius:6px;margin-bottom:.5rem;overflow:hidden}.sc-panel-head{display:flex;align-items:center;gap:.6rem;padding:.5rem .7rem;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--surface-100, #f5f6f7)}.sc-panel-head .sc-panel-title{flex:1;font-weight:600}.sc-panel.open>.sc-panel-head{background:var(--primary-color, #2196f3);color:var(--primary-color-text, #fff)}.sc-panel-body{display:flex;flex-direction:column;gap:.45rem;padding:.6rem .75rem .75rem}.sc-subhead{display:flex;align-items:center;gap:.5rem;margin-top:.4rem;font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-color-secondary, #6c757d)}.sc-subhead:after{content:\"\";flex:1;border-top:1px solid var(--surface-border, #dee2e6)}:host ::ng-deep .sc-buttons .p-button{padding:.35rem .75rem;font-size:.85rem}.sc-row-picker p-dropdown,.sc-row-picker p-multiSelect,.sc-row-picker p-treeSelect{flex:1 1 0;min-width:0}:host ::ng-deep .sc-row-picker .sc-variant{width:6.5rem}:host ::ng-deep .sc-row-picker p-multiselect .p-multiselect{width:100%}:host ::ng-deep .sc-row-picker p-dropdown:has(.sc-variant){flex:0 0 6.5rem}:host ::ng-deep .sc-row-picker p-treeselect:has(.sc-palette){flex:0 0 3rem}:host ::ng-deep .sc-palette .p-treeselect-label{width:0;padding:0}.sc-icon-btn{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:.25rem .35rem;font:inherit;font-size:1.05rem;color:var(--text-color, #333);border-radius:4px}.sc-icon-btn:hover{background:var(--surface-200, #e9ecef)}.sc-icon-btn.active{color:var(--primary-color, #2196f3);font-weight:700}.sc-icon-btn:disabled{opacity:.5;cursor:default}.sc-small-btn{margin-left:auto;border:1px solid var(--surface-border, #ced4da);background:var(--surface-0, #fff);border-radius:4px;padding:.2rem .6rem;font:inherit;font-size:.8rem;cursor:pointer}:host ::ng-deep .sc-group-heading{font-size:.7rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;opacity:.7}.sc-group-list,.sc-gene-tree{max-height:16rem;overflow-y:auto;border:1px solid var(--surface-border, #dee2e6);border-radius:4px;padding:.25rem .4rem}.sc-group-row,.sc-gene-row{display:flex;align-items:center;gap:.45rem;padding:.15rem 0;font-size:.88rem}.sc-group-row .sc-group-label,.sc-gene-row .sc-group-label{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sc-group-all,.sc-gene-root,.sc-gene-group{font-weight:600}.sc-group-all .sc-icon-btn,.sc-gene-root .sc-icon-btn,.sc-gene-group .sc-icon-btn{margin-left:auto;font-size:.85rem}.sc-count{flex:0 0 auto;font-size:.78rem;color:var(--text-color-secondary, #6c757d)}.sc-glyph-option{display:inline-flex;align-items:center;gap:.4rem}.sc-glyph-svg{width:1rem;height:1rem;fill:currentColor}:host ::ng-deep .sc-glyph-pick .p-dropdown-label{padding:.2rem .4rem}.sc-color-input{width:2.5rem;height:1.8rem;border:1px solid var(--surface-border, #ced4da);border-radius:4px;padding:0;background:none}.sc-row-number p-slider,.sc-row-range p-slider{flex:1 1 0;min-width:0}:host ::ng-deep .sc-num{width:4.5rem;padding:.3rem .4rem;text-align:center}:host ::ng-deep .sc-row-number p-inputnumber,:host ::ng-deep .sc-row-range p-inputnumber{flex:0 0 auto}.sc-gene-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:1.4rem;height:1.4rem;padding:0;border:1px solid transparent;border-radius:4px;background:transparent;cursor:pointer}.sc-gene-icon:hover,.sc-gene-icon:focus-visible{border-color:var(--surface-border, rgba(0, 0, 0, .2))}:host{display:contents}.sc-gene-group,.sc-gene-leaf{padding-left:1rem}.sc-gene-leaf.nested{padding-left:2rem}.sc-eye{flex:0 0 auto;border:0;background:transparent;cursor:pointer;padding:0;color:var(--text-color-secondary, #6c757d)}.sc-eye .pi-eye{color:var(--text-color, #333)}.sc-eye:disabled{cursor:default;opacity:.5}.sc-gene-sort{display:flex;align-items:center;gap:.25rem;font-size:.8rem}.sc-gene-sort .sc-lbl{margin-right:auto}.sc-sort-btn{border:1px solid var(--surface-border, #ced4da);background:var(--surface-0, #fff);color:var(--text-color, #333);border-radius:4px;padding:.1rem .5rem;font:inherit;cursor:pointer}.sc-sort-btn.active{border-color:var(--primary-color, #2196f3);color:var(--primary-color, #2196f3);font-weight:600}.sc-gene-filter{width:calc(100% - 1rem);margin:.2rem 0 .2rem 1rem;font-size:.8rem;padding:.2rem .4rem}.sc-gene-footer{text-align:right;font-size:.78rem;padding:.2rem 0;color:var(--text-color-secondary, #6c757d)}.sc-gene-count{margin-left:auto;font-variant-numeric:tabular-nums;opacity:.8;padding-left:.5rem}\n"] }]
310
343
  }], ctorParameters: () => [{ type: i0.NgZone }, { type: i0.ChangeDetectorRef }], propDecorators: { controls: [{
311
344
  type: Input
312
345
  }], dataset: [{
@@ -318,4 +351,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
318
351
  }], geneTotal: [{
319
352
  type: Input
320
353
  }] } });
321
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC1nZW5lLXRyZWUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zcGF0aWFsLWNvbnRyb2xzL3NwYXRpYWwtZ2VuZS10cmVlL3NwYXRpYWwtZ2VuZS10cmVlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc3BhdGlhbC1jb250cm9scy9zcGF0aWFsLWdlbmUtdHJlZS9zcGF0aWFsLWdlbmUtdHJlZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsS0FBSyxFQUNMLE1BQU0sR0FHUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMzQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDcEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBSWhELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUNwRSxPQUFPLEVBQUUsb0JBQW9CLEVBQXlDLE1BQU0sK0JBQStCLENBQUM7QUFDNUcsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDN0UsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsZUFBZSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDakgsT0FBTyxFQUFnQixhQUFhLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQzNHLE9BQU8sRUFBRSxjQUFjLEVBQUUsY0FBYyxFQUFFLG1C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WixZQUFZO3dCQUNaLGVBQWU7d0JBQ2Ysa0JBQWtCO3dCQUNsQixhQUFhO3dCQUNiLHlCQUF5QjtxQkFDMUIsbUJBR2dCLHVCQUF1QixDQUFDLE1BQU07MkdBSXRDLFFBQVE7c0JBQWhCLEtBQUs7Z0JBRUcsT0FBTztzQkFBZixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLFNBQVM7c0JBQWpCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIE5nWm9uZSxcbiAgT25DaGFuZ2VzLFxuICBTaW1wbGVDaGFuZ2VzLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBTaGFyZWRNb2R1bGUgfSBmcm9tICdwcmltZW5nL2FwaSc7XG5pbXBvcnQgeyBJbnB1dFRleHRNb2R1bGUgfSBmcm9tICdwcmltZW5nL2lucHV0dGV4dCc7XG5pbXBvcnQgeyBPdmVybGF5UGFuZWxNb2R1bGUgfSBmcm9tICdwcmltZW5nL292ZXJsYXlwYW5lbCc7XG5pbXBvcnQgeyBUb29sdGlwTW9kdWxlIH0gZnJvbSAncHJpbWVuZy90b29sdGlwJztcblxuaW1wb3J0IHR5cGUgeyBJU3BhdGlhbENvbnRyb2xzIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3Zpc3VhbGl6ZXIuY29udHJhY3QnO1xuaW1wb3J0IHR5cGUgeyBTcGF0aWFsRGF0YXNldCB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9zcGF0aWFsLWRhdGFzZXQuY29udHJhY3QnO1xuaW1wb3J0IHsgQUxMX0dFTkVTIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3BvcnRzL3NwYXRpYWwtZGF0YS5wb3J0JztcbmltcG9ydCB7IERFRkFVTFRfU1BBVElBTF9WSUVXLCBTcGF0aWFsVmlld1N0YXRlLCBUcmFuc2NyaXB0R2x5cGhOYW1lIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL2Rpc3BsYXktdHlwZXMnO1xuaW1wb3J0IHsgREVGQVVMVF9DQVRFR09SSUNBTF9QQUxFVFRFIH0gZnJvbSAnLi4vLi4vc3BhdGlhbC9zcGF0aWFsLWVuY29kaW5nJztcbmltcG9ydCB7IGNlbGxUeXBlQ29sdW1uRm9yLCBjbHVzdGVyQ29sb3JNYXAsIGNsdXN0ZXJPZkdlbmUsIGRlZmF1bHRHbHlwaEZvciB9IGZyb20gJy4uLy4uL3NwYXRpYWwvc3BhdGlhbC10aWxlcyc7XG5pbXBvcnQgeyBHZW5lVHJlZU5vZGUsIGJ1aWxkR2VuZVRyZWUsIGdseXBoUG9pbnRzLCB0b2dnbGVIaWRkZW4gfSBmcm9tICcuLi8uLi9zcGF0aWFsL3NwYXRpYWwtcGFuZWwtbW9kZWwnO1xuaW1wb3J0IHsgYWxsR2VuZVNob3duQnksIGFsbEdlbmVzSGlkZGVuLCB0b2dnbGVBbGxHZW5lSGlkZGVuIH0gZnJvbSAnLi4vLi4vc3BhdGlhbC9zcGF0aWFsLXRpbGUtbWVyZ2UnO1xuaW1wb3J0IHsgU3VwZXJzZWRlIH0gZnJvbSAnLi4vLi4vdXRpbC9zdXBlcnNlZGUnO1xuaW1wb3J0IHsgU3BhdGlhbEdlbmVTdHlsZUNvbXBvbmVudCB9IGZyb20gJy4uL3NwYXRpYWwtZ2VuZS1zdHlsZS9zcGF0aWFsLWdlbmUtc3R5bGUuY29tcG9uZW50JztcblxuLyoqIFJvd3Mgb2YgdGhlIGFsbC1nZW5lcyBsaXN0IGRyYXduIGF0IG9uY2U7IHRoZSBmaWx0ZXIgbmFycm93cyB0aGUgcmVzdC4gKi9cbmNvbnN0IEFMTF9HRU5FU19ST1dTID0gMjAwO1xuXG4vKiogT25lIGdlbmUgcm93IGFzIHRoZSB0ZW1wbGF0ZSBkcmF3cyBpdCwgZGVyaXZlZCBvbmNlIHBlciBpbnB1dCBjaGFuZ2UuICovXG5pbnRlcmZhY2UgR2VuZVJvd1ZpZXcge1xuICBzaG93bjogYm9vbGVhbjtcbiAgc3dhdGNoOiBzdHJpbmc7XG4gIC8qKiBUaGUgcm93J3MgZ2x5cGggb3V0bGluZSAoZHJhd24gaW4gSWNvbnMgbW9kZSkuICovXG4gIHBvaW50czogc3RyaW5nO1xuICAvKiogVHJhbnNjcmlwdHMgaW4gdmlldywgb3IgbnVsbCBiZWZvcmUgdGhlIHJlbmRlcmVyIHJlcG9ydHMgYW55LiAqL1xuICBjb3VudDogbnVtYmVyIHwgbnVsbDtcbn1cblxuLyoqIE9uZSByb3cgb2YgdGhlIGFsbC1nZW5lcyBsaXN0LiAqL1xuaW50ZXJmYWNlIEFsbEdlbmVSb3dWaWV3IHtcbiAgZ2VuZTogc3RyaW5nO1xuICBzaG93bjogYm9vbGVhbjtcbiAgLyoqIEl0cyBjb2xvdXIgd2hlbiBjb2xvdXJlZCBieSBnZW5lLCBvciBudWxsIHdoZW4gdGhlIGRhdGFzZXQncyBjb2RlIG9yZGVyIGlzIHVua25vd24uICovXG4gIHN3YXRjaDogc3RyaW5nIHwgbnVsbDtcbiAgY291bnQ6IG51bWJlciB8IG51bGw7XG59XG5cbi8qKlxuICogVGhlIHNlbGVjdGVkIHRyYW5zY3JpcHQgZ2VuZXMgYXMgWGVuaXVtIEV4cGxvcmVyJ3MgdHJlZTogdGhlIGdlbmUgZ3JvdXBzLCB0aGVuIHRoZVxuICogdW5ncm91cGVkIGdlbmVzLCBlYWNoIHJvdyB3aXRoIGFuIGV5ZSB0aGF0IGhpZGVzIGl0IHdpdGhvdXQgZGVzZWxlY3RpbmcgaXQsIGl0cyBtYXJrZXJcbiAqIGluIGl0cyBjb2xvdXIgKG9wZW5pbmcgb25lIGljb24tYW5kLWNvbG91ciBwaWNrZXIgcGVyIGdlbmUpLCBhbmQgaXRzIHRyYW5zY3JpcHQgY291bnQgaW5cbiAqIHZpZXcuIFdpdGggXCJBbGwgZ2VuZXNcIiBvbiwgdGhlIHJvb3QgZXllIGhpZGVzIG9yIHNob3dzIGV2ZXJ5IHRyYW5zY3JpcHQgYW5kIHRoZSByb290XG4gKiBleHBhbmRzIHRvIGV2ZXJ5IGdlbmUgb2YgdGhlIGRhdGFzZXQsIGVhY2ggd2l0aCBpdHMgZXllIHdoZW4gdGhlIGRhdGFzZXQgbGlzdHMgaXRzIGdlbmVzXG4gKiBpbiBjb2RlIG9yZGVyIChgdHJhbnNjcmlwdFRpbGVzLmdlbmVzYCksIGZpbHRlcmVkIGJ5IG5hbWUgcGFzdCBhIGZldyBodW5kcmVkLlxuICpcbiAqIFdyaXRlcyBvbmx5IHRocm91Z2ggYGNvbnRyb2xzLnNldFZpZXdTdGF0ZWAuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3NwYXRpYWwtZ2VuZS10cmVlJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBTaGFyZWRNb2R1bGUsXG4gICAgSW5wdXRUZXh0TW9kdWxlLFxuICAgIE92ZXJsYXlQYW5lbE1vZHVsZSxcbiAgICBUb29sdGlwTW9kdWxlLFxuICAgIFNwYXRpYWxHZW5lU3R5bGVDb21wb25lbnQsXG4gIF0sXG4gIHRlbXBsYXRlVXJsOiAnLi9zcGF0aWFsLWdlbmUtdHJlZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3NwYXRpYWwtZ2VuZS10cmVlLmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBTcGF0aWFsR2VuZVRyZWVDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICAvKiogVGhlIHNwYXRpYWwgY29udHJvbHMgdGhpcyBwYW5lbCByZWFkcyBhbmQgd3JpdGVzIHRocm91Z2g7IG51bGwgd2l0aG91dCBhIGBTUEFUSUFMX0RBVEFfUE9SVGAuICovXG4gIEBJbnB1dCgpIGNvbnRyb2xzOiBJU3BhdGlhbENvbnRyb2xzIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBUaGUgZGF0YXNldCBvbiBvZmZlciwgb3IgbnVsbC4gKi9cbiAgQElucHV0KCkgZGF0YXNldDogU3BhdGlhbERhdGFzZXQgfCBudWxsID0gbnVsbDtcbiAgLyoqIFRoZSBjdXJyZW50IHNwYXRpYWwgdmlldyBzdGF0ZTogd2hhdCBpcyBkcmF3biwgYW5kIGhvdy4gKi9cbiAgQElucHV0KCkgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSA9IERFRkFVTFRfU1BBVElBTF9WSUVXO1xuICAvKiogVHJhbnNjcmlwdHMgb2YgZWFjaCBzZWxlY3RlZCBnZW5lIGluIHRoZSBjdXJyZW50IHZpZXcsIGZyb20gdGhlIHJlbmRlcmVyLiAqL1xuICBASW5wdXQoKSBnZW5lQ291bnRzOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+IHwgbnVsbCA9IG51bGw7XG4gIC8qKiBSZWFsIGdlbmVzIGluIHRoZSBwYW5lbCDigJQgdGhlIHRyZWUncyBkZW5vbWluYXRvci4gKi9cbiAgQElucHV0KCkgZ2VuZVRvdGFsID0gMDtcblxuICAvKiogU3dhdGNoZXMgaW4gdGhlIHBpY2tlcjogdGhlIGNhdGVnb3JpY2FsIHBhbGV0dGUgZ2VuZXMgYXJlIGNvbG91cmVkIGZyb20gYnkgZGVmYXVsdC4gKi9cblxuICAvKiogVGhlIHRyZWUsIHJlYnVpbHQgd2hlbiB0aGUgdmlldyBjaGFuZ2VzIOKAlCBuZXZlciBwZXIgY2hhbmdlLWRldGVjdGlvbiBwYXNzLiAqL1xuICBwcm90ZWN0ZWQgZ2VuZVRyZWU6IEdlbmVUcmVlTm9kZVtdID0gW107XG4gIC8qKiBQZXIgZ2VuZTogaXRzIGV5ZSwgc3dhdGNoLCBnbHlwaCBhbmQgY291bnQg4oCUIHJlYnVpbHQgd2l0aCB0aGUgaW5wdXRzIChhbmQgd2hlbiB0aGVcbiAgICogIGNlbGxzJyBncm91cCBjb2xvdXJzIGFycml2ZSksIHNvIHRoZSB0ZW1wbGF0ZSBkb2VzIG5vIHBlci1yb3cgbG9va3VwcyBwZXIgY2hlY2suICovXG4gIHByb3RlY3RlZCByb3dzID0gbmV3IE1hcDxzdHJpbmcsIEdlbmVSb3dWaWV3PigpO1xuICAvKiogUGVyIG5hbWVkIGdyb3VwLCBhbmQgZm9yIHRoZSByb290OiB3aGV0aGVyIGFueSBvZiBpdHMgZ2VuZXMgaXMgc2hvd24uICovXG4gIHByb3RlY3RlZCBncm91cFNob3duID0gbmV3IE1hcDxzdHJpbmcsIGJvb2xlYW4+KCk7XG4gIHByb3RlY3RlZCByb290U2hvd24gPSBmYWxzZTtcbiAgcHJvdGVjdGVkIGNvbGxhcHNlZEdlbmVHcm91cHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgcHJvdGVjdGVkIGdlbmVUcmVlT3BlbiA9IHRydWU7XG4gIC8qKiBUaGUgYWxsLWdlbmVzIGxpc3Qgc3RhcnRzIGNsb3NlZDogaXQgY2FuIHJ1biB0byB0aG91c2FuZHMgb2YgZ2VuZXMuICovXG4gIHByb3RlY3RlZCBhbGxHZW5lc09wZW4gPSBmYWxzZTtcbiAgLyoqIFRoZSBnZW5lcyBcIkFsbCBnZW5lc1wiIGxpc3RzLCBvciBudWxsIHdoZW4gdGhlIGRhdGFzZXQgbmFtZXMgbm9uZS4gKi9cbiAgcHJvdGVjdGVkIGFsbEdlbmVMaXN0OiByZWFkb25seSBzdHJpbmdbXSB8IG51bGwgPSBudWxsO1xuICAvKiogV2hldGhlciBhIGdlbmUgb2YgXCJBbGwgZ2VuZXNcIiBjYW4gYmUgaGlkZGVuOiB0aGUgZGF0YXNldCBsaXN0cyBpdHMgZ2VuZXMgaW4gY29kZSBvcmRlci4gKi9cbiAgcHJvdGVjdGVkIGNhbkhpZGVBbGxHZW5lcyA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgYWxsR2VuZXNGaWx0ZXIgPSAnJztcbiAgLyoqIFRoZSBsaXN0J3Mgcm93cyBtYXRjaGluZyB0aGUgZmlsdGVyLCBhdCBtb3N0IHtAbGluayBBTExfR0VORVNfUk9XU30uICovXG4gIHByb3RlY3RlZCBhbGxSb3dzOiBBbGxHZW5lUm93Vmlld1tdID0gW107XG4gIC8qKiBIb3cgbWFueSBnZW5lcyBtYXRjaCB0aGUgZmlsdGVyLCBmb3IgdGhlIFwic2hvd2luZyBuIG9mIG1cIiBsaW5lLiAqL1xuICBwcm90ZWN0ZWQgYWxsR2VuZXNNYXRjaGVkID0gMDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGFsbEdlbmVzUm93Q2FwID0gQUxMX0dFTkVTX1JPV1M7XG4gIC8qKiBUaGUgZ2VuZSB0aGUgb3BlbiBwaWNrZXIgZWRpdHMuICovXG4gIHByb3RlY3RlZCBzdHlsZUdlbmU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBDb2xvdXJzIG9mIHRoZSBjZWxscycgZ3JvdXBzLCBieSBuYW1lIOKAlCB3aGF0IGEgY2x1c3RlciBvZiB0aGUgc2FtZSBuYW1lIGlzIGRyYXduIGluLiAqL1xuICBwcml2YXRlIGNlbGxHcm91cENvbG9ycyA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gIC8qKiBUaGUgZ3JvdXBpbmcge0BsaW5rIGNlbGxHcm91cENvbG9yc30gYmVsb25ncyB0byDigJQgYSByZXBlYXQgcmVxdWVzdCBmb3IgaXQgaXMgYSBuby1vcC4gKi9cbiAgcHJpdmF0ZSBjZWxsR3JvdXBDb2xvcnNGb3I6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gIC8qKiBMYXRlc3Qgd2lucyBhbW9uZyBjb2xvdXIgbG9hZHMgZm9yIHtAbGluayBjZWxsR3JvdXBDb2xvcnN9LiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGNlbGxHcm91cENvbG9yc0xvYWQgPSBuZXcgU3VwZXJzZWRlKCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSB6b25lOiBOZ1pvbmUsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxuICApIHt9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzWyd2aWV3J10pIHRoaXMuZ2VuZVRyZWUgPSBidWlsZEdlbmVUcmVlKHRoaXMudmlldy50cmFuc2NyaXB0R2VuZXMsIHRoaXMudmlldy50cmFuc2NyaXB0R2VuZUdyb3Vwcyk7XG4gICAgLy8gQSBzYW1lLW5hbWVkIGdyb3VwaW5nIG9mIGEgbmV3IGRhdGFzZXQgaXMgbm90IHRoZSBvbGQgb25lLlxuICAgIGlmIChjaGFuZ2VzWydkYXRhc2V0J10pIHtcbiAgICAgIHRoaXMuY2VsbEdyb3VwQ29sb3JzRm9yID0gdW5kZWZpbmVkO1xuICAgICAgY29uc3QgY29kZWQgPSB0aGlzLmRhdGFzZXQ/LnRyYW5zY3JpcHRUaWxlcz8uZ2VuZXM7XG4gICAgICB0aGlzLmNhbkhpZGVBbGxHZW5lcyA9ICEhY29kZWQ/Lmxlbmd0aDtcbiAgICAgIHRoaXMuYWxsR2VuZUxpc3QgPSBjb2RlZD8ubGVuZ3RoID8gY29kZWQgOiAodGhpcy5kYXRhc2V0Py5mZWF0dXJlcz8ubmFtZXMgPz8gbnVsbCk7XG4gICAgfVxuICAgIHRoaXMucmVidWlsZFJvd3MoKTtcbiAgICB2b2lkIHRoaXMucmVmcmVzaENlbGxHcm91cENvbG9ycygpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWJ1aWxkUm93cygpOiB2b2lkIHtcbiAgICBjb25zdCBnZW5lcyA9IHRoaXMudmlldy50cmFuc2NyaXB0R2VuZXM7XG4gICAgdGhpcy5yb3dzID0gbmV3IE1hcChcbiAgICAgIGdlbmVzLm1hcCgoZ2VuZSwgc2xvdCkgPT4gW1xuICAgICAgICBnZW5lLFxuICAgICAgICB7XG4gICAgICAgICAgc2hvd246IHRoaXMuaXNHZW5lU2hvd24oZ2VuZSksXG4gICAgICAgICAgc3dhdGNoOiB0aGlzLmdlbmVTd2F0Y2hPZihnZW5lKSxcbiAgICAgICAgICBwb2ludHM6IGdseXBoUG9pbnRzKHRoaXMuZ2x5cGhPZihnZW5lLCBzbG90KSksXG4gICAgICAgICAgY291bnQ6IHRoaXMuZ2VuZUNvdW50T2YoZ2VuZSksXG4gICAgICAgIH0sXG4gICAgICBdKSxcbiAgICApO1xuICAgIHRoaXMuZ3JvdXBTaG93biA9IG5ldyBNYXAoXG4gICAgICB0aGlzLmdlbmVUcmVlXG4gICAgICAgIC5maWx0ZXIoKG5vZGUpID0+IG5vZGUubmFtZSlcbiAgICAgICAgLm1hcCgobm9kZSkgPT4gW25vZGUubmFtZSBhcyBzdHJpbmcsIHRoaXMuYXJlR2VuZXNTaG93bihub2RlLmdlbmVzKV0pLFxuICAgICk7XG4gICAgdGhpcy5yb290U2hvd24gPSB0aGlzLnZpZXcudHJhbnNjcmlwdEFsbEdlbmVzID8gdGhpcy5hbnlPZkFsbEdlbmVzU2hvd24oKSA6IHRoaXMuYXJlR2VuZXNTaG93bihnZW5lcyk7XG4gICAgdGhpcy5yZWJ1aWxkQWxsUm93cygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBhbGwtZ2VuZXMgbGlzdCdzIHJvd3M6IHRoZSBnZW5lcyBtYXRjaGluZyB0aGUgZmlsdGVyLCB1cCB0byB0aGUgY2FwLiBCdWlsdCBvbmx5IHdoaWxlXG4gICAqIHRoZSBsaXN0IGlzIG9wZW46IHRoZSBjb3VudHMgaW4gdmlldyBjaGFuZ2Ugd2l0aCBldmVyeSBwYW4sIGFuZCB0aGUgbGlzdCBjYW4gYmUgdGhvdXNhbmRzLlxuICAgKi9cbiAgcHJpdmF0ZSByZWJ1aWxkQWxsUm93cygpOiB2b2lkIHtcbiAgICBjb25zdCBsaXN0ID0gdGhpcy52aWV3LnRyYW5zY3JpcHRBbGxHZW5lcyAmJiB0aGlzLmFsbEdlbmVzT3BlbiA/IHRoaXMuYWxsR2VuZUxpc3QgOiBudWxsO1xuICAgIGlmICghbGlzdCkge1xuICAgICAgdGhpcy5hbGxSb3dzID0gW107XG4gICAgICB0aGlzLmFsbEdlbmVzTWF0Y2hlZCA9IDA7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IG5lZWRsZSA9IHRoaXMuYWxsR2VuZXNGaWx0ZXIudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gICAgY29uc3Qgc2hvd24gPSBhbGxHZW5lU2hvd25CeSh0aGlzLnZpZXcudHJhbnNjcmlwdEFsbEdlbmVzSGlkZGVuKTtcbiAgICBjb25zdCByb3dzOiBBbGxHZW5lUm93Vmlld1tdID0gW107XG4gICAgbGV0IG1hdGNoZWQgPSAwO1xuICAgIGxpc3QuZm9yRWFjaCgoZ2VuZSwgY29kZSkgPT4ge1xuICAgICAgLy8gQW4gZW1wdHkgbmFtZSBpcyBhIGNvZGUgbm8gdHJhbnNjcmlwdCBjYXJyaWVzIChhIGNvbnRyb2wgcHJvYmUpLlxuICAgICAgaWYgKCFnZW5lIHx8IChuZWVkbGUgJiYgIWdlbmUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhuZWVkbGUpKSkgcmV0dXJuO1xuICAgICAgbWF0Y2hlZCsrO1xuICAgICAgaWYgKHJvd3MubGVuZ3RoID49IEFMTF9HRU5FU19ST1dTKSByZXR1cm47XG4gICAgICByb3dzLnB1c2goe1xuICAgICAgICBnZW5lLFxuICAgICAgICBzaG93bjogc2hvd24oZ2VuZSksXG4gICAgICAgIHN3YXRjaDogdGhpcy5jYW5IaWRlQWxsR2VuZXMgPyB0aGlzLmFsbEdlbmVDb2xvck9mKGdlbmUsIGNvZGUpIDogbnVsbCxcbiAgICAgICAgY291bnQ6IHRoaXMuZ2VuZUNvdW50T2YoZ2VuZSksXG4gICAgICB9KTtcbiAgICB9KTtcbiAgICB0aGlzLmFsbFJvd3MgPSByb3dzO1xuICAgIHRoaXMuYWxsR2VuZXNNYXRjaGVkID0gbWF0Y2hlZDtcbiAgfVxuXG4gIC8qKiBXaGV0aGVyIFwiQWxsIGdlbmVzXCIgZHJhd3MgYW55dGhpbmc6IG5vdCBzd2l0Y2hlZCBvZmYgd2hvbGUsIG5vciBldmVyeSBsaXN0ZWQgZ2VuZSBoaWRkZW4uICovXG4gIHByaXZhdGUgYW55T2ZBbGxHZW5lc1Nob3duKCk6IGJvb2xlYW4ge1xuICAgIGlmIChhbGxHZW5lc0hpZGRlbih0aGlzLnZpZXcpKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKCF0aGlzLmNhbkhpZGVBbGxHZW5lcyB8fCAhdGhpcy5hbGxHZW5lTGlzdCkgcmV0dXJuIHRydWU7XG4gICAgY29uc3Qgc2hvd24gPSBhbGxHZW5lU2hvd25CeSh0aGlzLnZpZXcudHJhbnNjcmlwdEFsbEdlbmVzSGlkZGVuKTtcbiAgICByZXR1cm4gdGhpcy5hbGxHZW5lTGlzdC5zb21lKChnKSA9PiBnICYmIHNob3duKGcpKTtcbiAgfVxuXG4gIC8qKiBBIGdlbmUgb2YgXCJBbGwgZ2VuZXNcIiBpbiBpdHMgY29sb3VyIGJ5IGdlbmU6IGl0cyBjaG9zZW4gb25lLCBlbHNlIHRoZSBwYWxldHRlJ3MgYnkgY29kZS4gKi9cbiAgcHJpdmF0ZSBhbGxHZW5lQ29sb3JPZihnZW5lOiBzdHJpbmcsIGNvZGU6IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMudmlldy50cmFuc2NyaXB0R2VuZUNvbG9yc1tnZW5lXSB8fFxuICAgICAgREVGQVVMVF9DQVRFR09SSUNBTF9QQUxFVFRFW2NvZGUgJSBERUZBVUxUX0NBVEVHT1JJQ0FMX1BBTEVUVEUubGVuZ3RoXVxuICAgICk7XG4gIH1cblxuICBwcm90ZWN0ZWQgdG9nZ2xlQWxsR2VuZXNPcGVuKCk6IHZvaWQge1xuICAgIHRoaXMuYWxsR2VuZXNPcGVuID0gIXRoaXMuYWxsR2VuZXNPcGVuO1xuICAgIHRoaXMucmVidWlsZEFsbFJvd3MoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvbkFsbEdlbmVzRmlsdGVyKHRleHQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuYWxsR2VuZXNGaWx0ZXIgPSB0ZXh0O1xuICAgIHRoaXMucmVidWlsZEFsbFJvd3MoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCB0b2dnbGVHZW5lR3JvdXAobmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgbmV4dCA9IG5ldyBTZXQodGhpcy5jb2xsYXBzZWRHZW5lR3JvdXBzKTtcbiAgICBpZiAobmV4dC5oYXMobmFtZSkpIG5leHQuZGVsZXRlKG5hbWUpO1xuICAgIGVsc2UgbmV4dC5hZGQobmFtZSk7XG4gICAgdGhpcy5jb2xsYXBzZWRHZW5lR3JvdXBzID0gbmV4dDtcbiAgfVxuXG4gIHByb3RlY3RlZCBpc0dlbmVTaG93bihnZW5lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gIXRoaXMudmlldy50cmFuc2NyaXB0SGlkZGVuR2VuZXMuaW5jbHVkZXMoZ2VuZSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXJlR2VuZXNTaG93bihnZW5lczogc3RyaW5nW10pOiBib29sZWFuIHtcbiAgICByZXR1cm4gZ2VuZXMuc29tZSgoZykgPT4gdGhpcy5pc0dlbmVTaG93bihnKSk7XG4gIH1cblxuICAvKiogVGhlIGV5ZSB0b2dnbGU6IGhpZGUgb3Igc2hvdyBnZW5lcyB3aXRob3V0IHJlbW92aW5nIHRoZW0gZnJvbSB0aGUgc2VsZWN0aW9uLiAqL1xuICBwcm90ZWN0ZWQgb25HZW5lc1Nob3duKGdlbmVzOiBzdHJpbmdbXSwgb246IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoe1xuICAgICAgdHJhbnNjcmlwdEhpZGRlbkdlbmVzOiB0b2dnbGVIaWRkZW4odGhpcy52aWV3LnRyYW5zY3JpcHRIaWRkZW5HZW5lcywgZ2VuZXMsIG9uKSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBUaGUgcm9vdCBleWUgd2hpbGUgZXZlcnkgZ2VuZSBpcyBkcmF3bjogaGlkZSBvciBzaG93IHRoZW0gYWxsICh0aGUgJ8KxJyBsZWF2ZXMgXCJBbGwgZ2VuZXNcIikuICovXG4gIHByb3RlY3RlZCBvbkFsbEdlbmVzU2hvd24ob246IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0QWxsR2VuZXNIaWRkZW46IG9uID8gW10gOiBbQUxMX0dFTkVTXSB9KTtcbiAgfVxuXG4gIC8qKiBPbmUgZ2VuZSdzIGV5ZSBpbiB0aGUgYWxsLWdlbmVzIGxpc3QuIFNob3dpbmcgb25lIHdoaWxlIGFsbCBhcmUgb2ZmIHNob3dzIGl0IGFsb25lLiAqL1xuICBwcm90ZWN0ZWQgb25BbGxHZW5lU2hvd24oZ2VuZTogc3RyaW5nLCBvbjogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICghdGhpcy5jYW5IaWRlQWxsR2VuZXMpIHJldHVybjtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoe1xuICAgICAgdHJhbnNjcmlwdEFsbEdlbmVzSGlkZGVuOiB0b2dnbGVBbGxHZW5lSGlkZGVuKHRoaXMudmlldy50cmFuc2NyaXB0QWxsR2VuZXNIaWRkZW4sIGdlbmUsIG9uKSxcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvbkdlbmVDb2xvcihnZW5lOiBzdHJpbmcsIGhleDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgdHJhbnNjcmlwdEdlbmVDb2xvcnM6IHsgLi4udGhpcy52aWV3LnRyYW5zY3JpcHRHZW5lQ29sb3JzLCBbZ2VuZV06IGhleCB9IH0pO1xuICB9XG5cbiAgLy8g4pSA4pSAIHBlci1nZW5lIGljb24gYW5kIGNvbG91ciBwaWNrZXIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJvdGVjdGVkIG9wZW5HZW5lU3R5bGUoZXZlbnQ6IEV2ZW50LCBnZW5lOiBzdHJpbmcsIHBhbmVsOiB7IHRvZ2dsZShlOiBFdmVudCk6IHZvaWQ7IGhpZGUoKTogdm9pZCB9KTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc3R5bGVHZW5lID09PSBnZW5lKSB7XG4gICAgICBwYW5lbC50b2dnbGUoZXZlbnQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnN0eWxlR2VuZSA9IGdlbmU7XG4gICAgcGFuZWwuaGlkZSgpO1xuICAgIC8vIFJlLW9wZW4gYW5jaG9yZWQgb24gdGhlIHJvdyB0aGF0IHdhcyBjbGlja2VkLCBvbmNlIHRoZSBwYW5lbCBoYXMgY2xvc2VkLlxuICAgIHNldFRpbWVvdXQoKCkgPT4gcGFuZWwudG9nZ2xlKGV2ZW50KSk7XG4gIH1cblxuICAvKiogVGhlIGljb24gdGhlIG9wZW4gcGlja2VyIHNob3dzIGFzIGNob3Nlbi4gKi9cbiAgcHJvdGVjdGVkIGdldCBzdHlsZUdseXBoKCk6IFRyYW5zY3JpcHRHbHlwaE5hbWUgfCBudWxsIHtcbiAgICBjb25zdCBnZW5lID0gdGhpcy5zdHlsZUdlbmU7XG4gICAgcmV0dXJuIGdlbmUgPyB0aGlzLmdseXBoT2YoZ2VuZSwgTWF0aC5tYXgoMCwgdGhpcy52aWV3LnRyYW5zY3JpcHRHZW5lcy5pbmRleE9mKGdlbmUpKSkgOiBudWxsO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdseXBoUG9pbnRzKGdseXBoOiBUcmFuc2NyaXB0R2x5cGhOYW1lKTogc3RyaW5nIHtcbiAgICByZXR1cm4gZ2x5cGhQb2ludHMoZ2x5cGgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdseXBoT2YoZ2VuZTogc3RyaW5nLCBzbG90OiBudW1iZXIpOiBUcmFuc2NyaXB0R2x5cGhOYW1lIHtcbiAgICByZXR1cm4gdGhpcy52aWV3LnRyYW5zY3JpcHRHbHlwaHNbZ2VuZV0gPz8gZGVmYXVsdEdseXBoRm9yKHNsb3QpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uR2x5cGgoZ2VuZTogc3RyaW5nLCBnbHlwaDogVHJhbnNjcmlwdEdseXBoTmFtZSk6IHZvaWQge1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7IHRyYW5zY3JpcHRHbHlwaHM6IHsgLi4udGhpcy52aWV3LnRyYW5zY3JpcHRHbHlwaHMsIFtnZW5lXTogZ2x5cGggfSB9KTtcbiAgfVxuXG4gIC8qKiBCYWNrIHRvIHRoZSBnZW5lJ3MgZGVmYXVsdCBpY29uIGFuZCBjb2xvdXIgKGJ5IGl0cyBwb3NpdGlvbiBpbiB0aGUgbGlzdCkuICovXG4gIHByb3RlY3RlZCByZXNldEdlbmVTdHlsZShnZW5lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBjb2xvcnMgPSB7IC4uLnRoaXMudmlldy50cmFuc2NyaXB0R2VuZUNvbG9ycyB9O1xuICAgIGNvbnN0IGdseXBocyA9IHsgLi4udGhpcy52aWV3LnRyYW5zY3JpcHRHbHlwaHMgfTtcbiAgICBkZWxldGUgY29sb3JzW2dlbmVdO1xuICAgIGRlbGV0ZSBnbHlwaHNbZ2VuZV07XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgdHJhbnNjcmlwdEdlbmVDb2xvcnM6IGNvbG9ycywgdHJhbnNjcmlwdEdseXBoczogZ2x5cGhzIH0pO1xuICB9XG5cbiAgLy8g4pSA4pSAIGNvbG91cnMgYW5kIGNvdW50cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogVGhlIGNvbG91ciBnZW5lIGBzbG90YCBpcyBkcmF3biBpbiB3aGVuIHRyYW5zY3JpcHRzIGFyZSBjb2xvdXJlZCBieSBnZW5lLiAqL1xuICBnZW5lQ29sb3Ioc2xvdDogbnVtYmVyKTogc3RyaW5nIHtcbiAgICBjb25zdCBnZW5lID0gdGhpcy52aWV3Py50cmFuc2NyaXB0R2VuZXNbc2xvdF07XG4gICAgcmV0dXJuIChcbiAgICAgIChnZW5lICYmIHRoaXMudmlldy50cmFuc2NyaXB0R2VuZUNvbG9yc1tnZW5lXSkgfHxcbiAgICAgIERFRkFVTFRfQ0FURUdPUklDQUxfUEFMRVRURVtzbG90ICUgREVGQVVMVF9DQVRFR09SSUNBTF9QQUxFVFRFLmxlbmd0aF1cbiAgICApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdlbmVDb2xvck9mKGdlbmU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZ2VuZUNvbG9yKE1hdGgubWF4KDAsIHRoaXMudmlldy50cmFuc2NyaXB0R2VuZXMuaW5kZXhPZihnZW5lKSkpO1xuICB9XG5cbiAgLyoqIEluIENsdXN0ZXIgY29sb3VyaW5nLCBhIGdlbmUncyBzd2F0Y2ggaXMgaXRzIGNsdXN0ZXIncyBjb2xvdXIsIGFzIGl0cyBtYXJrZXJzIGFyZS4gKi9cbiAgcHJvdGVjdGVkIGdlbmVTd2F0Y2hPZihnZW5lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLnZpZXcudHJhbnNjcmlwdENvbG9yQnkgIT09ICdjbHVzdGVyJykgcmV0dXJuIHRoaXMuZ2VuZUNvbG9yT2YoZ2VuZSk7XG4gICAgcmV0dXJuIHRoaXMuY2x1c3RlckNvbG9ycygpLmdldChjbHVzdGVyT2ZHZW5lKGdlbmUsIHRoaXMudmlldy50cmFuc2NyaXB0R2VuZUdyb3VwcykpID8/IHRoaXMuZ2VuZUNvbG9yT2YoZ2VuZSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2VuZUNvdW50T2YoZ2VuZTogc3RyaW5nKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuZ2VuZUNvdW50cyA/ICh0aGlzLmdlbmVDb3VudHNbZ2VuZV0gPz8gMCkgOiBudWxsO1xuICB9XG5cbiAgcHJvdGVjdGVkIHRyYWNrQnlOb2RlID0gKF9pOiBudW1iZXIsIG5vZGU6IHsgbmFtZTogc3RyaW5nIHwgbnVsbCB9KSA9PiBub2RlLm5hbWUgPz8gJyc7XG4gIHByb3RlY3RlZCB0cmFja0J5TGFiZWxTdHJpbmcgPSAoX2k6IG51bWJlciwgczogc3RyaW5nKSA9PiBzO1xuICBwcm90ZWN0ZWQgdHJhY2tCeUFsbFJvdyA9IChfaTogbnVtYmVyLCByb3c6IEFsbEdlbmVSb3dWaWV3KSA9PiByb3cuZ2VuZTtcblxuICAvKipcbiAgICogVGhlIGNsdXN0ZXIgY29sb3VycywgcmVidWlsdCBvbmx5IHdoZW4gd2hhdCB0aGV5IGNvbWUgZnJvbSBjaGFuZ2VzLiBUaGUgdGVtcGxhdGUgYXNrc1xuICAgKiBvbmNlIHBlciBnZW5lIHJvdyBwZXIgY2hhbmdlLWRldGVjdGlvbiBwYXNzLCBhbmQgcmVidWlsZGluZyBwZXIgY2FsbCBtYWRlIHRoYXQgTyhHwrIpLlxuICAgKi9cbiAgcHJpdmF0ZSBjbHVzdGVyQ29sb3JzKCk6IE1hcDxzdHJpbmcsIHN0cmluZz4ge1xuICAgIGNvbnN0IHsgdHJhbnNjcmlwdEdlbmVzOiBnZW5lcywgdHJhbnNjcmlwdEdlbmVHcm91cHM6IGdyb3VwcyB9ID0gdGhpcy52aWV3O1xuICAgIGNvbnN0IGhpdCA9IHRoaXMuY2x1c3RlckNvbG9yTWVtbztcbiAgICBpZiAoaGl0ICYmIGhpdC5nZW5lcyA9PT0gZ2VuZXMgJiYgaGl0Lmdyb3VwcyA9PT0gZ3JvdXBzICYmIGhpdC5jZWxsQ29sb3JzID09PSB0aGlzLmNlbGxHcm91cENvbG9ycykge1xuICAgICAgcmV0dXJuIGhpdC5jb2xvcnM7XG4gICAgfVxuICAgIGNvbnN0IGNvbG9ycyA9IGNsdXN0ZXJDb2xvck1hcChnZW5lcywgZ3JvdXBzLCB0aGlzLmNlbGxHcm91cENvbG9ycywgREVGQVVMVF9DQVRFR09SSUNBTF9QQUxFVFRFKTtcbiAgICB0aGlzLmNsdXN0ZXJDb2xvck1lbW8gPSB7IGdlbmVzLCBncm91cHMsIGNlbGxDb2xvcnM6IHRoaXMuY2VsbEdyb3VwQ29sb3JzLCBjb2xvcnMgfTtcbiAgICByZXR1cm4gY29sb3JzO1xuICB9XG4gIHByaXZhdGUgY2x1c3RlckNvbG9yTWVtbzoge1xuICAgIGdlbmVzOiBTcGF0aWFsVmlld1N0YXRlWyd0cmFuc2NyaXB0R2VuZXMnXTtcbiAgICBncm91cHM6IFNwYXRpYWxWaWV3U3RhdGVbJ3RyYW5zY3JpcHRHZW5lR3JvdXBzJ107XG4gICAgY2VsbENvbG9yczogTWFwPHN0cmluZywgc3RyaW5nPjtcbiAgICBjb2xvcnM6IE1hcDxzdHJpbmcsIHN0cmluZz47XG4gIH0gfCBudWxsID0gbnVsbDtcblxuICBwcml2YXRlIGFzeW5jIHJlZnJlc2hDZWxsR3JvdXBDb2xvcnMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY29sdW1uID0gdGhpcy5kYXRhc2V0ID8gY2VsbFR5cGVDb2x1bW5Gb3IodGhpcy5kYXRhc2V0LCB0aGlzLnZpZXcpIDogbnVsbDtcbiAgICBpZiAoY29sdW1uID09PSB0aGlzLmNlbGxHcm91cENvbG9yc0ZvcikgcmV0dXJuO1xuICAgIHRoaXMuY2VsbEdyb3VwQ29sb3JzRm9yID0gY29sdW1uO1xuICAgIGNvbnN0IHRhc2sgPSB0aGlzLmNlbGxHcm91cENvbG9yc0xvYWQubmV4dCgpO1xuICAgIGNvbnN0IG1hcCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gICAgY29uc3QgbWV0YSA9IGNvbHVtbiA/IHRoaXMuZGF0YXNldD8uY29sdW1ucy5maW5kKChjKSA9PiBjLm5hbWUgPT09IGNvbHVtbikgOiBudWxsO1xuICAgIGlmIChtZXRhICYmIG1ldGEua2luZCA9PT0gJ2NhdGVnb3JpY2FsJyAmJiB0aGlzLmNvbnRyb2xzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjb2xvcnMgPSBhd2FpdCB0aGlzLmNvbnRyb2xzLmNhdGVnb3J5Q29sb3JzKGNvbHVtbiEpO1xuICAgICAgICBtZXRhLmNhdGVnb3JpZXMuZm9yRWFjaCgoYywgaykgPT4ge1xuICAgICAgICAgIGlmIChjb2xvcnNba10pIG1hcC5zZXQoYywgY29sb3JzW2tdKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gTm8gY29sb3VyczogcGFsZXR0ZSBjb2xvdXJzLCBhcyB0aGUgbWFya2VycyBmYWxsIGJhY2sgdG8uXG4gICAgICB9XG4gICAgfVxuICAgIC8vIFRoZSBjZWxscycgZ3JvdXBpbmcgY2hhbmdlZCB3aGlsZSB0aGUgY29sb3VycyBsb2FkZWQ6IHRoZSBuZXdlciByZXF1ZXN0IGFwcGxpZXMgaXRzIG93bi5cbiAgICBpZiAoIXRhc2suaXNDdXJyZW50KCkpIHJldHVybjtcbiAgICB0aGlzLnpvbmUucnVuKCgpID0+IHtcbiAgICAgIHRoaXMuY2VsbEdyb3VwQ29sb3JzID0gbWFwO1xuICAgICAgdGhpcy5yZWJ1aWxkUm93cygpO1xuICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgfSk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJzYy1zdWJoZWFkXCI+U2VsZWN0ZWQgZ2VuZXM8L2Rpdj5cbjxkaXYgY2xhc3M9XCJzYy1nZW5lLXRyZWVcIj5cbiAgPGRpdiBjbGFzcz1cInNjLWdlbmUtcm93IHNjLWdlbmUtcm9vdFwiPlxuICAgIDxidXR0b25cbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgY2xhc3M9XCJzYy1leWVcIlxuICAgICAgKGNsaWNrKT1cIlxuICAgICAgICB2aWV3LnRyYW5zY3JpcHRBbGxHZW5lcyA/IG9uQWxsR2VuZXNTaG93bighcm9vdFNob3duKSA6IG9uR2VuZXNTaG93bih2aWV3LnRyYW5zY3JpcHRHZW5lcywgIXJvb3RTaG93bilcbiAgICAgIFwiXG4gICAgPlxuICAgICAgPGkgY2xhc3M9XCJwaVwiIFtjbGFzcy5waS1leWVdPVwicm9vdFNob3duXCIgW2NsYXNzLnBpLWV5ZS1zbGFzaF09XCIhcm9vdFNob3duXCI+PC9pPlxuICAgIDwvYnV0dG9uPlxuICAgIDxzcGFuIGNsYXNzPVwic2MtZ3JvdXAtbGFiZWxcIj5HZW5lczwvc3Bhbj5cbiAgICA8c3BhbiBjbGFzcz1cInNjLWNvdW50XCJcbiAgICAgID4oe3sgKHZpZXcudHJhbnNjcmlwdEFsbEdlbmVzID8gZ2VuZVRvdGFsIDogdmlldy50cmFuc2NyaXB0R2VuZXMubGVuZ3RoKSB8IG51bWJlciB9fS97e1xuICAgICAgICBnZW5lVG90YWwgfCBudW1iZXJcbiAgICAgIH19KTwvc3BhblxuICAgID5cbiAgICA8YnV0dG9uXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgIGNsYXNzPVwic2MtaWNvbi1idG5cIlxuICAgICAgKGNsaWNrKT1cImdlbmVUcmVlT3BlbiA9ICFnZW5lVHJlZU9wZW5cIlxuICAgICAgKm5nSWY9XCIhdmlldy50cmFuc2NyaXB0QWxsR2VuZXMgJiYgdmlldy50cmFuc2NyaXB0R2VuZXMubGVuZ3RoXCJcbiAgICA+XG4gICAgICA8aSBjbGFzcz1cInBpXCIgW2NsYXNzLnBpLWNoZXZyb24tZG93bl09XCJnZW5lVHJlZU9wZW5cIiBbY2xhc3MucGktY2hldnJvbi1yaWdodF09XCIhZ2VuZVRyZWVPcGVuXCI+PC9pPlxuICAgIDwvYnV0dG9uPlxuICAgIDxidXR0b25cbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgY2xhc3M9XCJzYy1pY29uLWJ0blwiXG4gICAgICAoY2xpY2spPVwidG9nZ2xlQWxsR2VuZXNPcGVuKClcIlxuICAgICAgKm5nSWY9XCJ2aWV3LnRyYW5zY3JpcHRBbGxHZW5lcyAmJiBhbGxHZW5lTGlzdD8ubGVuZ3RoXCJcbiAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYWxsR2VuZXNPcGVuID8gJ0hpZGUgdGhlIGdlbmUgbGlzdCcgOiAnU2hvdyBldmVyeSBnZW5lJ1wiXG4gICAgPlxuICAgICAgPGkgY2xhc3M9XCJwaVwiIFtjbGFzcy5waS1jaGV2cm9uLWRvd25dPVwiYWxsR2VuZXNPcGVuXCIgW2NsYXNzLnBpLWNoZXZyb24tcmlnaHRdPVwiIWFsbEdlbmVzT3BlblwiPjwvaT5cbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG4gIDwhLS0gXCJBbGwgZ2VuZXNcIjogZXZlcnkgZ2VuZSBvZiB0aGUgZGF0YXNldCwgZWFjaCB3aXRoIGl0cyBleWUgd2hlbiB0aGUgZGF0YXNldCBzYXlzIHdoaWNoXG4gICAgICAgdHJhbnNjcmlwdHMgYXJlIHdob3NlIChpdHMgZ2VuZSBsaXN0IGluIGNvZGUgb3JkZXIpLiAtLT5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImFsbEdlbmVzT3BlbiAmJiB2aWV3LnRyYW5zY3JpcHRBbGxHZW5lcyAmJiBhbGxHZW5lTGlzdD8ubGVuZ3RoXCI+XG4gICAgPGlucHV0XG4gICAgICBwSW5wdXRUZXh0XG4gICAgICBjbGFzcz1cInNjLWdlbmUtZmlsdGVyXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiRmlsdGVyIGdlbmVz4oCmXCJcbiAgICAgIGFyaWEtbGFiZWw9XCJGaWx0ZXIgZ2VuZXNcIlxuICAgICAgW3ZhbHVlXT1cImFsbEdlbmVzRmlsdGVyXCJcbiAgICAgIChpbnB1dCk9XCJvbkFsbEdlbmVzRmlsdGVyKCRhbnkoJGV2ZW50LnRhcmdldCkudmFsdWUpXCJcbiAgICAvPlxuICAgIDxzbWFsbCBjbGFzcz1cInNjLWhpbnRcIiAqbmdJZj1cIiFjYW5IaWRlQWxsR2VuZXNcIj5cbiAgICAgIFRoaXMgZGF0YXNldCBkb2VzIG5vdCBzYXkgd2hpY2ggdHJhbnNjcmlwdHMgYXJlIHdob3NlLCBzbyBpdHMgZ2VuZXMgY2Fubm90IGJlIGhpZGRlbiBvbmUgYnkgb25lLlxuICAgIDwvc21hbGw+XG4gICAgPHNtYWxsIGNsYXNzPVwic2MtaGludFwiICpuZ0lmPVwiY2FuSGlkZUFsbEdlbmVzICYmIHZpZXcudHJhbnNjcmlwdE1vZGUgPT09ICdkZW5zaXR5J1wiPlxuICAgICAgVGhlIGRlbnNpdHkgbWFwIGRyYXdzIGV2ZXJ5IGdlbmUgYXMgb25lIHJhc3RlcjogZ2VuZXMgYXJlIGhpZGRlbiBvbmUgYnkgb25lIGFzIGNpcmNsZXMgb3IgaWNvbnMuXG4gICAgPC9zbWFsbD5cbiAgICA8ZGl2IGNsYXNzPVwic2MtZ2VuZS1yb3cgc2MtZ2VuZS1sZWFmIG5lc3RlZFwiICpuZ0Zvcj1cImxldCByb3cgb2YgYWxsUm93czsgdHJhY2tCeTogdHJhY2tCeUFsbFJvd1wiPlxuICAgICAgPGJ1dHRvblxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgY2xhc3M9XCJzYy1leWVcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiIWNhbkhpZGVBbGxHZW5lcyB8fCB2aWV3LnRyYW5zY3JpcHRNb2RlID09PSAnZGVuc2l0eSdcIlxuICAgICAgICAoY2xpY2spPVwib25BbGxHZW5lU2hvd24ocm93LmdlbmUsICFyb3cuc2hvd24pXCJcbiAgICAgID5cbiAgICAgICAgPGkgY2xhc3M9XCJwaVwiIFtjbGFzcy5waS1leWVdPVwicm93LnNob3duXCIgW2NsYXNzLnBpLWV5ZS1zbGFzaF09XCIhcm93LnNob3duXCI+PC9pPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8c3BhbiBjbGFzcz1cInNjLWdlbmUtaWNvblwiICpuZ0lmPVwicm93LnN3YXRjaFwiIFtzdHlsZS5jb2xvcl09XCJyb3cuc3dhdGNoXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+XG4gICAgICAgIDxzdmcgdmlld0JveD1cIi0xLjIgLTEuMiAyLjQgMi40XCIgY2xhc3M9XCJzYy1nbHlwaC1zdmdcIj48Y2lyY2xlIHI9XCIwLjc1XCI+PC9jaXJjbGU+PC9zdmc+XG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiBjbGFzcz1cInNjLWdyb3VwLWxhYmVsXCIgW3RpdGxlXT1cInJvdy5nZW5lXCI+e3sgcm93LmdlbmUgfX08L3NwYW4+XG4gICAgICA8c3BhbiBjbGFzcz1cInNjLWdlbmUtY291bnRcIiAqbmdJZj1cInJvdy5jb3VudCAhPT0gbnVsbFwiIHRpdGxlPVwiVHJhbnNjcmlwdHMgaW4gdmlld1wiPnt7XG4gICAgICAgIHJvdy5jb3VudCB8IG51bWJlclxuICAgICAgfX08L3NwYW4+XG4gICAgPC9kaXY+XG4gICAgPHNtYWxsIGNsYXNzPVwic2MtaGludFwiICpuZ0lmPVwiYWxsR2VuZXNNYXRjaGVkID4gYWxsUm93cy5sZW5ndGhcIj5cbiAgICAgIFNob3dpbmcge3sgYWxsUm93cy5sZW5ndGggfCBudW1iZXIgfX0gb2Yge3sgYWxsR2VuZXNNYXRjaGVkIHwgbnVtYmVyIH19IGdlbmVzOiBmaWx0ZXIgdG8gZmluZCB0aGUgb3RoZXJzLlxuICAgIDwvc21hbGw+XG4gICAgPHNtYWxsIGNsYXNzPVwic2MtaGludFwiICpuZ0lmPVwiYWxsR2VuZXNNYXRjaGVkID09PSAwXCI+Tm8gZ2VuZSBtYXRjaGVzLjwvc21hbGw+XG4gIDwvbmctY29udGFpbmVyPlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiZ2VuZVRyZWVPcGVuICYmICF2aWV3LnRyYW5zY3JpcHRBbGxHZW5lc1wiPlxuICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IG5vZGUgb2YgZ2VuZVRyZWU7IHRyYWNrQnk6IHRyYWNrQnlOb2RlXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwic2MtZ2VuZS1yb3cgc2MtZ2VuZS1ncm91cFwiICpuZ0lmPVwibm9kZS5uYW1lXCI+XG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwic2MtZXllXCIgKGNsaWNrKT1cIm9uR2VuZXNTaG93bihub2RlLmdlbmVzLCAhZ3JvdXBTaG93bi5nZXQobm9kZS5uYW1lKSlcIj5cbiAgICAgICAgICA8aVxuICAgICAgICAgICAgY2xhc3M9XCJwaVwiXG4gICAgICAgICAgICBbY2xhc3MucGktZXllXT1cImdyb3VwU2hvd24uZ2V0KG5vZGUubmFtZSlcIlxuICAgICAgICAgICAgW2NsYXNzLnBpLWV5ZS1zbGFzaF09XCIhZ3JvdXBTaG93bi5nZXQobm9kZS5uYW1lKVwiXG4gICAgICAgICAgPjwvaT5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwic2MtZ3JvdXAtbGFiZWxcIiBbdGl0bGVdPVwibm9kZS5uYW1lXCI+e3sgbm9kZS5uYW1lIH19PC9zcGFuPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInNjLWNvdW50XCI+KHt7IG5vZGUuZ2VuZXMubGVuZ3RoIH19KTwvc3Bhbj5cbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJzYy1pY29uLWJ0blwiIChjbGljayk9XCJ0b2dnbGVHZW5lR3JvdXAobm9kZS5uYW1lKVwiPlxuICAgICAgICAgIDxpXG4gICAgICAgICAgICBjbGFzcz1cInBpXCJcbiAgICAgICAgICAgIFtjbGFzcy5waS1jaGV2cm9uLWRvd25dPVwiIWNvbGxhcHNlZEdlbmVHcm91cHMuaGFzKG5vZGUubmFtZSlcIlxuICAgICAgICAgICAgW2NsYXNzLnBpLWNoZXZyb24tcmlnaHRdPVwiY29sbGFwc2VkR2VuZUdyb3Vwcy5oYXMobm9kZS5uYW1lKVwiXG4gICAgICAgICAgPjwvaT5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhbm9kZS5uYW1lIHx8ICFjb2xsYXBzZWRHZW5lR3JvdXBzLmhhcyhub2RlLm5hbWUpXCI+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICBjbGFzcz1cInNjLWdlbmUtcm93IHNjLWdlbmUtbGVhZlwiXG4gICAgICAgICAgW2NsYXNzLm5lc3RlZF09XCIhIW5vZGUubmFtZVwiXG4gICAgICAgICAgKm5nRm9yPVwibGV0IGdlbmUgb2Ygbm9kZS5nZW5lczsgdHJhY2tCeTogdHJhY2tCeUxhYmVsU3RyaW5nXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwic2MtZXllXCIgKGNsaWNrKT1cIm9uR2VuZXNTaG93bihbZ2VuZV0sICFyb3dzLmdldChnZW5lKT8uc2hvd24pXCI+XG4gICAgICAgICAgICA8aSBjbGFzcz1cInBpXCIgW2NsYXNzLnBpLWV5ZV09XCJyb3dzLmdldChnZW5lKT8uc2hvd25cIiBbY2xhc3MucGktZXllLXNsYXNoXT1cIiFyb3dzLmdldChnZW5lKT8uc2hvd25cIj48L2k+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPCEtLSBUaGUgZ2VuZSdzIG1hcmtlciwgaW4gaXRzIGNvbG91cjogaXRzIGljb24gaW4gSWNvbnMgbW9kZSwgYSBkb3QgZm9yIGNpcmNsZXMuXG4gICAgICAgICAgICAgICBDbGlja2luZyBpdCBvcGVucyB0aGUgaWNvbiBhbmQgY29sb3VyIHBpY2tlciAoYXMgWGVuaXVtIEV4cGxvcmVyIGRvZXMpLiAtLT5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNsYXNzPVwic2MtZ2VuZS1pY29uXCJcbiAgICAgICAgICAgIFtzdHlsZS5jb2xvcl09XCJyb3dzLmdldChnZW5lKT8uc3dhdGNoXCJcbiAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ0ljb24gYW5kIGNvbG91ciBmb3IgJyArIGdlbmVcIlxuICAgICAgICAgICAgcFRvb2x0aXA9XCJJY29uIGFuZCBjb2xvdXJcIlxuICAgICAgICAgICAgdG9vbHRpcFBvc2l0aW9uPVwidG9wXCJcbiAgICAgICAgICAgIChjbGljayk9XCJvcGVuR2VuZVN0eWxlKCRldmVudCwgZ2VuZSwgZ2VuZVBvcClcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxzdmcgdmlld0JveD1cIi0xLjIgLTEuMiAyLjQgMi40XCIgY2xhc3M9XCJzYy1nbHlwaC1zdmdcIj5cbiAgICAgICAgICAgICAgPHBvbHlnb25cbiAgICAgICAgICAgICAgICAqbmdJZj1cInZpZXcudHJhbnNjcmlwdE1vZGUgPT09ICdnbHlwaHMnOyBlbHNlIGRvdEljb25cIlxuICAgICAgICAgICAgICAgIFthdHRyLnBvaW50c109XCJyb3dzLmdldChnZW5lKT8ucG9pbnRzXCJcbiAgICAgICAgICAgICAgPjwvcG9seWdvbj5cbiAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNkb3RJY29uPjxjaXJjbGUgcj1cIjAuNzVcIj48L2NpcmNsZT48L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJzYy1ncm91cC1sYWJlbFwiPnt7IGdlbmUgfX08L3NwYW4+XG4gICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgIGNsYXNzPVwic2MtZ2VuZS1jb3VudFwiXG4gICAgICAgICAgICAqbmdJZj1cInJvd3MuZ2V0KGdlbmUpPy5jb3VudCBhcyBuOyBlbHNlIHplcm9Db3VudFwiXG4gICAgICAgICAgICB0aXRsZT1cIlRyYW5zY3JpcHRzIGluIHZpZXdcIlxuICAgICAgICAgICAgPnt7IG4gfCBudW1iZXIgfX08L3NwYW5cbiAgICAgICAgICA+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICN6ZXJvQ291bnQ+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInNjLWdlbmUtY291bnRcIiAqbmdJZj1cImdlbmVDb3VudHNcIiB0aXRsZT1cIlRyYW5zY3JpcHRzIGluIHZpZXdcIj4wPC9zcGFuPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIDwvbmctY29udGFpbmVyPlxuICA8IS0tIE9uZSBwaWNrZXIgZm9yIGV2ZXJ5IGdlbmUgcm93LCBmaWxsZWQgZm9yIHRoZSBnZW5lIHRoYXQgb3BlbmVkIGl0LiAtLT5cbiAgPHAtb3ZlcmxheVBhbmVsICNnZW5lUG9wIHN0eWxlQ2xhc3M9XCJzYy1nZW5lLXN0eWxlXCIgYXBwZW5kVG89XCJib2R5XCI+XG4gICAgPG5nLXRlbXBsYXRlIHBUZW1wbGF0ZT1cImNvbnRlbnRcIj5cbiAgICAgIDxzcGF0aWFsLWdlbmUtc3R5bGVcbiAgICAgICAgKm5nSWY9XCJzdHlsZUdlbmUgYXMgZ2VuZVwiXG4gICAgICAgIFtnZW5lXT1cImdlbmVcIlxuICAgICAgICB3aGF0PVwiVHJhbnNjcmlwdFwiXG4gICAgICAgIFtjb2xvcl09XCJnZW5lQ29sb3JPZihnZW5lKVwiXG4gICAgICAgIFtnbHlwaF09XCJzdHlsZUdseXBoID8/ICdjaXJjbGUnXCJcbiAgICAgICAgW2ljb25IaW50XT1cIlxuICAgICAgICAgIHZpZXcudHJhbnNjcmlwdE1vZGUgIT09ICdnbHlwaHMnID8gJ0ljb25zIHNob3cgd2hlbiB0aGUgdHJhbnNjcmlwdCBwb2ludCBzdHlsZSBpcyBJY29ucy4nIDogbnVsbFxuICAgICAgICBcIlxuICAgICAgICAoY29sb3JDaGFuZ2UpPVwib25HZW5lQ29sb3IoZ2VuZSwgJGV2ZW50KVwiXG4gICAgICAgIChnbHlwaENoYW5nZSk9XCJvbkdseXBoKGdlbmUsICRldmVudClcIlxuICAgICAgICAocmVzZXRTdHlsZSk9XCJyZXNldEdlbmVTdHlsZShnZW5lKVwiXG4gICAgICA+PC9zcGF0aWFsLWdlbmUtc3R5bGU+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbiAgPC9wLW92ZXJsYXlQYW5lbD5cbiAgPGRpdiBjbGFzcz1cInNjLWdlbmUtZm9vdGVyXCI+XG4gICAge3sgKHZpZXcudHJhbnNjcmlwdEFsbEdlbmVzID8gZ2VuZVRvdGFsIDogdmlldy50cmFuc2NyaXB0R2VuZXMubGVuZ3RoKSB8IG51bWJlciB9fS97eyBnZW5lVG90YWwgfCBudW1iZXIgfX1cbiAgICBnZW5lcyBzZWxlY3RlZFxuICA8L2Rpdj5cbjwvZGl2PlxuIl19
354
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC1nZW5lLXRyZWUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zcGF0aWFsLWNvbnRyb2xzL3NwYXRpYWwtZ2VuZS10cmVlL3NwYXRpYWwtZ2VuZS10cmVlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc3BhdGlhbC1jb250cm9scy9zcGF0aWFsLWdlbmUtdHJlZS9zcGF0aWFsLWdlbmUtdHJlZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsS0FBSyxFQUNMLE1BQU0sR0FHUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMzQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDcEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBSWhELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUNwRSxPQUFPLEVBQUUsb0JBQW9CLEVBQXlDLE1BQU0sK0JBQStCLENBQUM7QUFDNUcsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDN0UsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsZUFBZSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDakgsT0FBTyxFQUFnQixhQUFhLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQzNHLE9BQU8sRUFBRSxjQUFjLEVBQUUsY0FBYyxFQUFFLG1C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RjtRQUMzRixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUFFLE9BQU87UUFDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFO1lBQ2pCLElBQUksQ0FBQyxlQUFlLEdBQUcsR0FBRyxDQUFDO1lBQzNCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNuQixJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQzFCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs4R0FwVVUsd0JBQXdCO2tHQUF4Qix3QkFBd0Isd05DckZyQyw0eFBBc0xBLHd4TEQ1R0ksWUFBWSx1VEFDWixZQUFZLHFJQUNaLGVBQWUsd0hBQ2Ysa0JBQWtCLGtXQUNsQixhQUFhLHNYQUNiLHlCQUF5Qjs7MkZBTWhCLHdCQUF3QjtrQkFmcEMsU0FBUzsrQkFDRSxtQkFBbUIsY0FDakIsSUFBSSxXQUNQO3dCQUNQLFlBQVk7d0JBQ1osWUFBWTt3QkFDWixlQUFlO3dCQUNmLGtCQUFrQjt3QkFDbEIsYUFBYTt3QkFDYix5QkFBeUI7cUJBQzFCLG1CQUdnQix1QkFBdUIsQ0FBQyxNQUFNOzJHQUl0QyxRQUFRO3NCQUFoQixLQUFLO2dCQUVHLE9BQU87c0JBQWYsS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIElucHV0LFxuICBOZ1pvbmUsXG4gIE9uQ2hhbmdlcyxcbiAgU2ltcGxlQ2hhbmdlcyxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgU2hhcmVkTW9kdWxlIH0gZnJvbSAncHJpbWVuZy9hcGknO1xuaW1wb3J0IHsgSW5wdXRUZXh0TW9kdWxlIH0gZnJvbSAncHJpbWVuZy9pbnB1dHRleHQnO1xuaW1wb3J0IHsgT3ZlcmxheVBhbmVsTW9kdWxlIH0gZnJvbSAncHJpbWVuZy9vdmVybGF5cGFuZWwnO1xuaW1wb3J0IHsgVG9vbHRpcE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvdG9vbHRpcCc7XG5cbmltcG9ydCB0eXBlIHsgSVNwYXRpYWxDb250cm9scyB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy92aXN1YWxpemVyLmNvbnRyYWN0JztcbmltcG9ydCB0eXBlIHsgU3BhdGlhbERhdGFzZXQgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvc3BhdGlhbC1kYXRhc2V0LmNvbnRyYWN0JztcbmltcG9ydCB7IEFMTF9HRU5FUyB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9wb3J0cy9zcGF0aWFsLWRhdGEucG9ydCc7XG5pbXBvcnQgeyBERUZBVUxUX1NQQVRJQUxfVklFVywgU3BhdGlhbFZpZXdTdGF0ZSwgVHJhbnNjcmlwdEdseXBoTmFtZSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9kaXNwbGF5LXR5cGVzJztcbmltcG9ydCB7IERFRkFVTFRfQ0FURUdPUklDQUxfUEFMRVRURSB9IGZyb20gJy4uLy4uL3NwYXRpYWwvc3BhdGlhbC1lbmNvZGluZyc7XG5pbXBvcnQgeyBjZWxsVHlwZUNvbHVtbkZvciwgY2x1c3RlckNvbG9yTWFwLCBjbHVzdGVyT2ZHZW5lLCBkZWZhdWx0R2x5cGhGb3IgfSBmcm9tICcuLi8uLi9zcGF0aWFsL3NwYXRpYWwtdGlsZXMnO1xuaW1wb3J0IHsgR2VuZVRyZWVOb2RlLCBidWlsZEdlbmVUcmVlLCBnbHlwaFBvaW50cywgdG9nZ2xlSGlkZGVuIH0gZnJvbSAnLi4vLi4vc3BhdGlhbC9zcGF0aWFsLXBhbmVsLW1vZGVsJztcbmltcG9ydCB7IGFsbEdlbmVTaG93bkJ5LCBhbGxHZW5lc0hpZGRlbiwgdG9nZ2xlQWxsR2VuZUhpZGRlbiB9IGZyb20gJy4uLy4uL3NwYXRpYWwvc3BhdGlhbC10aWxlLW1lcmdlJztcbmltcG9ydCB7IFN1cGVyc2VkZSB9IGZyb20gJy4uLy4uL3V0aWwvc3VwZXJzZWRlJztcbmltcG9ydCB7IFNwYXRpYWxHZW5lU3R5bGVDb21wb25lbnQgfSBmcm9tICcuLi9zcGF0aWFsLWdlbmUtc3R5bGUvc3BhdGlhbC1nZW5lLXN0eWxlLmNvbXBvbmVudCc7XG5cbi8qKiBSb3dzIG9mIHRoZSBhbGwtZ2VuZXMgbGlzdCBkcmF3biBhdCBvbmNlOyB0aGUgZmlsdGVyIG5hcnJvd3MgdGhlIHJlc3QuICovXG5jb25zdCBBTExfR0VORVNfUk9XUyA9IDIwMDtcblxuLyoqIEhvdyB0aGUgZ2VuZSByb3dzIGFyZSBvcmRlcmVkOiBieSBuYW1lLCBvciBieSB0aGVpciB0cmFuc2NyaXB0cyBpbiB2aWV3LCBtb3N0IGZpcnN0LiAqL1xuZXhwb3J0IHR5cGUgR2VuZVNvcnQgPSAnbmFtZScgfCAnY291bnQnO1xuXG4vKiogTmFtZXMgaW4gcmVhZGluZyBvcmRlcjogY2FzZSBhc2lkZSwgYW5kIGBHOWAgYmVmb3JlIGBHMTBgLiAqL1xuY29uc3QgYnlOYW1lID0gKGE6IHN0cmluZywgYjogc3RyaW5nKTogbnVtYmVyID0+XG4gIGEubG9jYWxlQ29tcGFyZShiLCB1bmRlZmluZWQsIHsgbnVtZXJpYzogdHJ1ZSwgc2Vuc2l0aXZpdHk6ICdiYXNlJyB9KTtcblxuLyoqIE9uZSBnZW5lIHJvdyBhcyB0aGUgdGVtcGxhdGUgZHJhd3MgaXQsIGRlcml2ZWQgb25jZSBwZXIgaW5wdXQgY2hhbmdlLiAqL1xuaW50ZXJmYWNlIEdlbmVSb3dWaWV3IHtcbiAgc2hvd246IGJvb2xlYW47XG4gIHN3YXRjaDogc3RyaW5nO1xuICAvKiogVGhlIHJvdydzIGdseXBoIG91dGxpbmUgKGRyYXduIGluIEljb25zIG1vZGUpLiAqL1xuICBwb2ludHM6IHN0cmluZztcbiAgLyoqIFRyYW5zY3JpcHRzIGluIHZpZXcsIG9yIG51bGwgYmVmb3JlIHRoZSByZW5kZXJlciByZXBvcnRzIGFueS4gKi9cbiAgY291bnQ6IG51bWJlciB8IG51bGw7XG59XG5cbi8qKiBPbmUgcm93IG9mIHRoZSBhbGwtZ2VuZXMgbGlzdC4gKi9cbmludGVyZmFjZSBBbGxHZW5lUm93VmlldyB7XG4gIGdlbmU6IHN0cmluZztcbiAgc2hvd246IGJvb2xlYW47XG4gIC8qKiBJdHMgY29sb3VyIHdoZW4gY29sb3VyZWQgYnkgZ2VuZSwgb3IgbnVsbCB3aGVuIHRoZSBkYXRhc2V0J3MgY29kZSBvcmRlciBpcyB1bmtub3duLiAqL1xuICBzd2F0Y2g6IHN0cmluZyB8IG51bGw7XG4gIGNvdW50OiBudW1iZXIgfCBudWxsO1xufVxuXG4vKipcbiAqIFRoZSBzZWxlY3RlZCB0cmFuc2NyaXB0IGdlbmVzIGFzIFhlbml1bSBFeHBsb3JlcidzIHRyZWU6IHRoZSBnZW5lIGdyb3VwcywgdGhlbiB0aGVcbiAqIHVuZ3JvdXBlZCBnZW5lcywgZWFjaCByb3cgd2l0aCBhbiBleWUgdGhhdCBoaWRlcyBpdCB3aXRob3V0IGRlc2VsZWN0aW5nIGl0LCBpdHMgbWFya2VyXG4gKiBpbiBpdHMgY29sb3VyIChvcGVuaW5nIG9uZSBpY29uLWFuZC1jb2xvdXIgcGlja2VyIHBlciBnZW5lKSwgYW5kIGl0cyB0cmFuc2NyaXB0IGNvdW50IGluXG4gKiB2aWV3LiBXaXRoIFwiQWxsIGdlbmVzXCIgb24sIHRoZSByb290IGV5ZSBoaWRlcyBvciBzaG93cyBldmVyeSB0cmFuc2NyaXB0IGFuZCB0aGUgcm9vdFxuICogZXhwYW5kcyB0byBldmVyeSBnZW5lIG9mIHRoZSBkYXRhc2V0LCBlYWNoIHdpdGggaXRzIGV5ZSB3aGVuIHRoZSBkYXRhc2V0IGxpc3RzIGl0cyBnZW5lc1xuICogaW4gY29kZSBvcmRlciAoYHRyYW5zY3JpcHRUaWxlcy5nZW5lc2ApLCBmaWx0ZXJlZCBieSBuYW1lIHBhc3QgYSBmZXcgaHVuZHJlZC5cbiAqXG4gKiBCb3RoIGxpc3RzIGFyZSBvcmRlcmVkIGJ5IG5hbWUsIG9yIGJ5IHRoZWlyIHRyYW5zY3JpcHRzIGluIHZpZXcsIG1vc3QgZmlyc3QgKHRoZVxuICogc29ydCBzd2l0Y2gsIG9mZmVyZWQgb25jZSB0aGUgcmVuZGVyZXIgcmVwb3J0cyBjb3VudHMpLiBUaGUgYWxsLWdlbmVzIGxpc3QgaXMgc29ydGVkXG4gKiBiZWZvcmUgaXQgaXMgY3V0IHRvIGl0cyBmaXJzdCByb3dzLCBzbyBieSBjb3VudCB0aG9zZSBhcmUgdGhlIGdlbmVzIHdpdGggdGhlIG1vc3RcbiAqIHRyYW5zY3JpcHRzIGluIHZpZXcuXG4gKlxuICogV3JpdGVzIG9ubHkgdGhyb3VnaCBgY29udHJvbHMuc2V0Vmlld1N0YXRlYC5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc3BhdGlhbC1nZW5lLXRyZWUnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIFNoYXJlZE1vZHVsZSxcbiAgICBJbnB1dFRleHRNb2R1bGUsXG4gICAgT3ZlcmxheVBhbmVsTW9kdWxlLFxuICAgIFRvb2x0aXBNb2R1bGUsXG4gICAgU3BhdGlhbEdlbmVTdHlsZUNvbXBvbmVudCxcbiAgXSxcbiAgdGVtcGxhdGVVcmw6ICcuL3NwYXRpYWwtZ2VuZS10cmVlLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vc3BhdGlhbC1nZW5lLXRyZWUuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFNwYXRpYWxHZW5lVHJlZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG4gIC8qKiBUaGUgc3BhdGlhbCBjb250cm9scyB0aGlzIHBhbmVsIHJlYWRzIGFuZCB3cml0ZXMgdGhyb3VnaDsgbnVsbCB3aXRob3V0IGEgYFNQQVRJQUxfREFUQV9QT1JUYC4gKi9cbiAgQElucHV0KCkgY29udHJvbHM6IElTcGF0aWFsQ29udHJvbHMgfCBudWxsID0gbnVsbDtcbiAgLyoqIFRoZSBkYXRhc2V0IG9uIG9mZmVyLCBvciBudWxsLiAqL1xuICBASW5wdXQoKSBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCB8IG51bGwgPSBudWxsO1xuICAvKiogVGhlIGN1cnJlbnQgc3BhdGlhbCB2aWV3IHN0YXRlOiB3aGF0IGlzIGRyYXduLCBhbmQgaG93LiAqL1xuICBASW5wdXQoKSB2aWV3OiBTcGF0aWFsVmlld1N0YXRlID0gREVGQVVMVF9TUEFUSUFMX1ZJRVc7XG4gIC8qKiBUcmFuc2NyaXB0cyBvZiBlYWNoIHNlbGVjdGVkIGdlbmUgaW4gdGhlIGN1cnJlbnQgdmlldywgZnJvbSB0aGUgcmVuZGVyZXIuICovXG4gIEBJbnB1dCgpIGdlbmVDb3VudHM6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4gfCBudWxsID0gbnVsbDtcbiAgLyoqIFJlYWwgZ2VuZXMgaW4gdGhlIHBhbmVsIOKAlCB0aGUgdHJlZSdzIGRlbm9taW5hdG9yLiAqL1xuICBASW5wdXQoKSBnZW5lVG90YWwgPSAwO1xuXG4gIC8qKiBTd2F0Y2hlcyBpbiB0aGUgcGlja2VyOiB0aGUgY2F0ZWdvcmljYWwgcGFsZXR0ZSBnZW5lcyBhcmUgY29sb3VyZWQgZnJvbSBieSBkZWZhdWx0LiAqL1xuXG4gIC8qKiBUaGUgdHJlZSwgcmVidWlsdCB3aGVuIHRoZSB2aWV3IGNoYW5nZXMg4oCUIG5ldmVyIHBlciBjaGFuZ2UtZGV0ZWN0aW9uIHBhc3MuICovXG4gIHByb3RlY3RlZCBnZW5lVHJlZTogR2VuZVRyZWVOb2RlW10gPSBbXTtcbiAgLyoqIHtAbGluayBnZW5lVHJlZX0gd2l0aCBlYWNoIG5vZGUncyBnZW5lcyBpbiB7QGxpbmsgZ2VuZVNvcnR9IG9yZGVyOiB3aGF0IHRoZSB0ZW1wbGF0ZSBkcmF3cy4gKi9cbiAgcHJvdGVjdGVkIHNvcnRlZFRyZWU6IEdlbmVUcmVlTm9kZVtdID0gW107XG4gIC8qKiBUaGUgcm93cycgb3JkZXIuIEJ5IGNvdW50IG9ubHkgd2hpbGUgdGhlIHJlbmRlcmVyIHJlcG9ydHMgY291bnRzIChzZWUge0BsaW5rIHNvcnRTaG93bn0pLiAqL1xuICBwcm90ZWN0ZWQgZ2VuZVNvcnQ6IEdlbmVTb3J0ID0gJ25hbWUnO1xuICAvKiogUGVyIGdlbmU6IGl0cyBleWUsIHN3YXRjaCwgZ2x5cGggYW5kIGNvdW50IOKAlCByZWJ1aWx0IHdpdGggdGhlIGlucHV0cyAoYW5kIHdoZW4gdGhlXG4gICAqICBjZWxscycgZ3JvdXAgY29sb3VycyBhcnJpdmUpLCBzbyB0aGUgdGVtcGxhdGUgZG9lcyBubyBwZXItcm93IGxvb2t1cHMgcGVyIGNoZWNrLiAqL1xuICBwcm90ZWN0ZWQgcm93cyA9IG5ldyBNYXA8c3RyaW5nLCBHZW5lUm93Vmlldz4oKTtcbiAgLyoqIFBlciBuYW1lZCBncm91cCwgYW5kIGZvciB0aGUgcm9vdDogd2hldGhlciBhbnkgb2YgaXRzIGdlbmVzIGlzIHNob3duLiAqL1xuICBwcm90ZWN0ZWQgZ3JvdXBTaG93biA9IG5ldyBNYXA8c3RyaW5nLCBib29sZWFuPigpO1xuICBwcm90ZWN0ZWQgcm9vdFNob3duID0gZmFsc2U7XG4gIHByb3RlY3RlZCBjb2xsYXBzZWRHZW5lR3JvdXBzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIHByb3RlY3RlZCBnZW5lVHJlZU9wZW4gPSB0cnVlO1xuICAvKiogVGhlIGFsbC1nZW5lcyBsaXN0IHN0YXJ0cyBjbG9zZWQ6IGl0IGNhbiBydW4gdG8gdGhvdXNhbmRzIG9mIGdlbmVzLiAqL1xuICBwcm90ZWN0ZWQgYWxsR2VuZXNPcGVuID0gZmFsc2U7XG4gIC8qKiBUaGUgZ2VuZXMgXCJBbGwgZ2VuZXNcIiBsaXN0cywgb3IgbnVsbCB3aGVuIHRoZSBkYXRhc2V0IG5hbWVzIG5vbmUuICovXG4gIHByb3RlY3RlZCBhbGxHZW5lTGlzdDogcmVhZG9ubHkgc3RyaW5nW10gfCBudWxsID0gbnVsbDtcbiAgLyoqIFdoZXRoZXIgYSBnZW5lIG9mIFwiQWxsIGdlbmVzXCIgY2FuIGJlIGhpZGRlbjogdGhlIGRhdGFzZXQgbGlzdHMgaXRzIGdlbmVzIGluIGNvZGUgb3JkZXIuICovXG4gIHByb3RlY3RlZCBjYW5IaWRlQWxsR2VuZXMgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIGFsbEdlbmVzRmlsdGVyID0gJyc7XG4gIC8qKiBUaGUgbGlzdCdzIHJvd3MgbWF0Y2hpbmcgdGhlIGZpbHRlciwgYXQgbW9zdCB7QGxpbmsgQUxMX0dFTkVTX1JPV1N9LiAqL1xuICBwcm90ZWN0ZWQgYWxsUm93czogQWxsR2VuZVJvd1ZpZXdbXSA9IFtdO1xuICAvKiogSG93IG1hbnkgZ2VuZXMgbWF0Y2ggdGhlIGZpbHRlciwgZm9yIHRoZSBcInNob3dpbmcgbiBvZiBtXCIgbGluZS4gKi9cbiAgcHJvdGVjdGVkIGFsbEdlbmVzTWF0Y2hlZCA9IDA7XG4gIHByb3RlY3RlZCByZWFkb25seSBhbGxHZW5lc1Jvd0NhcCA9IEFMTF9HRU5FU19ST1dTO1xuICAvKiogVGhlIGdlbmUgdGhlIG9wZW4gcGlja2VyIGVkaXRzLiAqL1xuICBwcm90ZWN0ZWQgc3R5bGVHZW5lOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAvKiogQ29sb3VycyBvZiB0aGUgY2VsbHMnIGdyb3VwcywgYnkgbmFtZSDigJQgd2hhdCBhIGNsdXN0ZXIgb2YgdGhlIHNhbWUgbmFtZSBpcyBkcmF3biBpbi4gKi9cbiAgcHJpdmF0ZSBjZWxsR3JvdXBDb2xvcnMgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAvKiogVGhlIGdyb3VwaW5nIHtAbGluayBjZWxsR3JvdXBDb2xvcnN9IGJlbG9uZ3MgdG8g4oCUIGEgcmVwZWF0IHJlcXVlc3QgZm9yIGl0IGlzIGEgbm8tb3AuICovXG4gIHByaXZhdGUgY2VsbEdyb3VwQ29sb3JzRm9yOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAvKiogTGF0ZXN0IHdpbnMgYW1vbmcgY29sb3VyIGxvYWRzIGZvciB7QGxpbmsgY2VsbEdyb3VwQ29sb3JzfS4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBjZWxsR3JvdXBDb2xvcnNMb2FkID0gbmV3IFN1cGVyc2VkZSgpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgem9uZTogTmdab25lLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgKSB7fVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBpZiAoY2hhbmdlc1sndmlldyddKSB0aGlzLmdlbmVUcmVlID0gYnVpbGRHZW5lVHJlZSh0aGlzLnZpZXcudHJhbnNjcmlwdEdlbmVzLCB0aGlzLnZpZXcudHJhbnNjcmlwdEdlbmVHcm91cHMpO1xuICAgIC8vIEEgc2FtZS1uYW1lZCBncm91cGluZyBvZiBhIG5ldyBkYXRhc2V0IGlzIG5vdCB0aGUgb2xkIG9uZS5cbiAgICBpZiAoY2hhbmdlc1snZGF0YXNldCddKSB7XG4gICAgICB0aGlzLmNlbGxHcm91cENvbG9yc0ZvciA9IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IGNvZGVkID0gdGhpcy5kYXRhc2V0Py50cmFuc2NyaXB0VGlsZXM/LmdlbmVzO1xuICAgICAgdGhpcy5jYW5IaWRlQWxsR2VuZXMgPSAhIWNvZGVkPy5sZW5ndGg7XG4gICAgICB0aGlzLmFsbEdlbmVMaXN0ID0gY29kZWQ/Lmxlbmd0aCA/IGNvZGVkIDogKHRoaXMuZGF0YXNldD8uZmVhdHVyZXM/Lm5hbWVzID8/IG51bGwpO1xuICAgIH1cbiAgICB0aGlzLnJlYnVpbGRSb3dzKCk7XG4gICAgdm9pZCB0aGlzLnJlZnJlc2hDZWxsR3JvdXBDb2xvcnMoKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVidWlsZFJvd3MoKTogdm9pZCB7XG4gICAgY29uc3QgZ2VuZXMgPSB0aGlzLnZpZXcudHJhbnNjcmlwdEdlbmVzO1xuICAgIHRoaXMucm93cyA9IG5ldyBNYXAoXG4gICAgICBnZW5lcy5tYXAoKGdlbmUsIHNsb3QpID0+IFtcbiAgICAgICAgZ2VuZSxcbiAgICAgICAge1xuICAgICAgICAgIHNob3duOiB0aGlzLmlzR2VuZVNob3duKGdlbmUpLFxuICAgICAgICAgIHN3YXRjaDogdGhpcy5nZW5lU3dhdGNoT2YoZ2VuZSksXG4gICAgICAgICAgcG9pbnRzOiBnbHlwaFBvaW50cyh0aGlzLmdseXBoT2YoZ2VuZSwgc2xvdCkpLFxuICAgICAgICAgIGNvdW50OiB0aGlzLmdlbmVDb3VudE9mKGdlbmUpLFxuICAgICAgICB9LFxuICAgICAgXSksXG4gICAgKTtcbiAgICB0aGlzLmdyb3VwU2hvd24gPSBuZXcgTWFwKFxuICAgICAgdGhpcy5nZW5lVHJlZVxuICAgICAgICAuZmlsdGVyKChub2RlKSA9PiBub2RlLm5hbWUpXG4gICAgICAgIC5tYXAoKG5vZGUpID0+IFtub2RlLm5hbWUgYXMgc3RyaW5nLCB0aGlzLmFyZUdlbmVzU2hvd24obm9kZS5nZW5lcyldKSxcbiAgICApO1xuICAgIHRoaXMucm9vdFNob3duID0gdGhpcy52aWV3LnRyYW5zY3JpcHRBbGxHZW5lcyA/IHRoaXMuYW55T2ZBbGxHZW5lc1Nob3duKCkgOiB0aGlzLmFyZUdlbmVzU2hvd24oZ2VuZXMpO1xuICAgIHRoaXMuc29ydGVkVHJlZSA9IHRoaXMuZ2VuZVRyZWUubWFwKChub2RlKSA9PiAoeyAuLi5ub2RlLCBnZW5lczogdGhpcy5zb3J0ZWQobm9kZS5nZW5lcykgfSkpO1xuICAgIHRoaXMucmVidWlsZEFsbFJvd3MoKTtcbiAgfVxuXG4gIC8qKiBXaGV0aGVyIHRoZSByb3dzIGFyZSBvcmRlcmVkIGJ5IGNvdW50OiBjaG9zZW4sIGFuZCBjb3VudHMgdG8gb3JkZXIgYnkuICovXG4gIHByb3RlY3RlZCBnZXQgYnlDb3VudCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5nZW5lU29ydCA9PT0gJ2NvdW50JyAmJiAhIXRoaXMuZ2VuZUNvdW50cztcbiAgfVxuXG4gIC8qKiBUaGUgc29ydCBzd2l0Y2ggaXMgb2ZmZXJlZCBvbmNlIHRoZXJlIGFyZSBjb3VudHMgdG8gc29ydCBieS4gKi9cbiAgcHJvdGVjdGVkIGdldCBzb3J0U2hvd24oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5nZW5lQ291bnRzO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uR2VuZVNvcnQoc29ydDogR2VuZVNvcnQpOiB2b2lkIHtcbiAgICBpZiAoc29ydCA9PT0gdGhpcy5nZW5lU29ydCkgcmV0dXJuO1xuICAgIHRoaXMuZ2VuZVNvcnQgPSBzb3J0O1xuICAgIHRoaXMucmVidWlsZFJvd3MoKTtcbiAgfVxuXG4gIC8qKiBgZ2VuZXNgIGluIHRoZSByb3dzJyBvcmRlcjogYnkgY291bnQsIG1vc3QgZmlyc3QgKHRpZXMgYnkgbmFtZSksIGVsc2UgYnkgbmFtZS4gKi9cbiAgcHJpdmF0ZSBzb3J0ZWQoZ2VuZXM6IHJlYWRvbmx5IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuICAgIGlmICghdGhpcy5ieUNvdW50KSByZXR1cm4gWy4uLmdlbmVzXS5zb3J0KGJ5TmFtZSk7XG4gICAgY29uc3QgY291bnRzID0gdGhpcy5nZW5lQ291bnRzID8/IHt9O1xuICAgIHJldHVybiBbLi4uZ2VuZXNdLnNvcnQoKGEsIGIpID0+IChjb3VudHNbYl0gPz8gMCkgLSAoY291bnRzW2FdID8/IDApIHx8IGJ5TmFtZShhLCBiKSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGFsbC1nZW5lcyBsaXN0J3Mgcm93czogdGhlIGdlbmVzIG1hdGNoaW5nIHRoZSBmaWx0ZXIsIHVwIHRvIHRoZSBjYXAuIEJ1aWx0IG9ubHkgd2hpbGVcbiAgICogdGhlIGxpc3QgaXMgb3BlbjogdGhlIGNvdW50cyBpbiB2aWV3IGNoYW5nZSB3aXRoIGV2ZXJ5IHBhbiwgYW5kIHRoZSBsaXN0IGNhbiBiZSB0aG91c2FuZHMuXG4gICAqL1xuICBwcml2YXRlIHJlYnVpbGRBbGxSb3dzKCk6IHZvaWQge1xuICAgIGNvbnN0IGxpc3QgPSB0aGlzLnZpZXcudHJhbnNjcmlwdEFsbEdlbmVzICYmIHRoaXMuYWxsR2VuZXNPcGVuID8gdGhpcy5hbGxHZW5lTGlzdCA6IG51bGw7XG4gICAgaWYgKCFsaXN0KSB7XG4gICAgICB0aGlzLmFsbFJvd3MgPSBbXTtcbiAgICAgIHRoaXMuYWxsR2VuZXNNYXRjaGVkID0gMDtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbmVlZGxlID0gdGhpcy5hbGxHZW5lc0ZpbHRlci50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCBzaG93biA9IGFsbEdlbmVTaG93bkJ5KHRoaXMudmlldy50cmFuc2NyaXB0QWxsR2VuZXNIaWRkZW4pO1xuICAgIC8vIEV2ZXJ5IG1hdGNoLCBvcmRlcmVkLCBhbmQgb25seSB0aGVuIGN1dDogYnkgY291bnQgdGhlIGZpcnN0IHJvd3MgYXJlIHRoZSBtb3N0IGFidW5kYW50LlxuICAgIGNvbnN0IGNvZGVzID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgICBsaXN0LmZvckVhY2goKGdlbmUsIGNvZGUpID0+IHtcbiAgICAgIC8vIEFuIGVtcHR5IG5hbWUgaXMgYSBjb2RlIG5vIHRyYW5zY3JpcHQgY2FycmllcyAoYSBjb250cm9sIHByb2JlKS5cbiAgICAgIGlmICghZ2VuZSB8fCAobmVlZGxlICYmICFnZW5lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMobmVlZGxlKSkpIHJldHVybjtcbiAgICAgIGlmICghY29kZXMuaGFzKGdlbmUpKSBjb2Rlcy5zZXQoZ2VuZSwgY29kZSk7XG4gICAgfSk7XG4gICAgdGhpcy5hbGxSb3dzID0gdGhpcy5zb3J0ZWQoWy4uLmNvZGVzLmtleXMoKV0pXG4gICAgICAuc2xpY2UoMCwgQUxMX0dFTkVTX1JPV1MpXG4gICAgICAubWFwKChnZW5lKSA9PiAoe1xuICAgICAgICBnZW5lLFxuICAgICAgICBzaG93bjogc2hvd24oZ2VuZSksXG4gICAgICAgIHN3YXRjaDogdGhpcy5jYW5IaWRlQWxsR2VuZXMgPyB0aGlzLmFsbEdlbmVDb2xvck9mKGdlbmUsIGNvZGVzLmdldChnZW5lKSEpIDogbnVsbCxcbiAgICAgICAgY291bnQ6IHRoaXMuZ2VuZUNvdW50T2YoZ2VuZSksXG4gICAgICB9KSk7XG4gICAgdGhpcy5hbGxHZW5lc01hdGNoZWQgPSBjb2Rlcy5zaXplO1xuICB9XG5cbiAgLyoqIFdoZXRoZXIgXCJBbGwgZ2VuZXNcIiBkcmF3cyBhbnl0aGluZzogbm90IHN3aXRjaGVkIG9mZiB3aG9sZSwgbm9yIGV2ZXJ5IGxpc3RlZCBnZW5lIGhpZGRlbi4gKi9cbiAgcHJpdmF0ZSBhbnlPZkFsbEdlbmVzU2hvd24oKTogYm9vbGVhbiB7XG4gICAgaWYgKGFsbEdlbmVzSGlkZGVuKHRoaXMudmlldykpIHJldHVybiBmYWxzZTtcbiAgICBpZiAoIXRoaXMuY2FuSGlkZUFsbEdlbmVzIHx8ICF0aGlzLmFsbEdlbmVMaXN0KSByZXR1cm4gdHJ1ZTtcbiAgICBjb25zdCBzaG93biA9IGFsbEdlbmVTaG93bkJ5KHRoaXMudmlldy50cmFuc2NyaXB0QWxsR2VuZXNIaWRkZW4pO1xuICAgIHJldHVybiB0aGlzLmFsbEdlbmVMaXN0LnNvbWUoKGcpID0+IGcgJiYgc2hvd24oZykpO1xuICB9XG5cbiAgLyoqIEEgZ2VuZSBvZiBcIkFsbCBnZW5lc1wiIGluIGl0cyBjb2xvdXIgYnkgZ2VuZTogaXRzIGNob3NlbiBvbmUsIGVsc2UgdGhlIHBhbGV0dGUncyBieSBjb2RlLiAqL1xuICBwcml2YXRlIGFsbEdlbmVDb2xvck9mKGdlbmU6IHN0cmluZywgY29kZTogbnVtYmVyKTogc3RyaW5nIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy52aWV3LnRyYW5zY3JpcHRHZW5lQ29sb3JzW2dlbmVdIHx8XG4gICAgICBERUZBVUxUX0NBVEVHT1JJQ0FMX1BBTEVUVEVbY29kZSAlIERFRkFVTFRfQ0FURUdPUklDQUxfUEFMRVRURS5sZW5ndGhdXG4gICAgKTtcbiAgfVxuXG4gIHByb3RlY3RlZCB0b2dnbGVBbGxHZW5lc09wZW4oKTogdm9pZCB7XG4gICAgdGhpcy5hbGxHZW5lc09wZW4gPSAhdGhpcy5hbGxHZW5lc09wZW47XG4gICAgdGhpcy5yZWJ1aWxkQWxsUm93cygpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uQWxsR2VuZXNGaWx0ZXIodGV4dDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5hbGxHZW5lc0ZpbHRlciA9IHRleHQ7XG4gICAgdGhpcy5yZWJ1aWxkQWxsUm93cygpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHRvZ2dsZUdlbmVHcm91cChuYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBuZXh0ID0gbmV3IFNldCh0aGlzLmNvbGxhcHNlZEdlbmVHcm91cHMpO1xuICAgIGlmIChuZXh0LmhhcyhuYW1lKSkgbmV4dC5kZWxldGUobmFtZSk7XG4gICAgZWxzZSBuZXh0LmFkZChuYW1lKTtcbiAgICB0aGlzLmNvbGxhcHNlZEdlbmVHcm91cHMgPSBuZXh0O1xuICB9XG5cbiAgcHJvdGVjdGVkIGlzR2VuZVNob3duKGdlbmU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhdGhpcy52aWV3LnRyYW5zY3JpcHRIaWRkZW5HZW5lcy5pbmNsdWRlcyhnZW5lKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhcmVHZW5lc1Nob3duKGdlbmVzOiBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBnZW5lcy5zb21lKChnKSA9PiB0aGlzLmlzR2VuZVNob3duKGcpKTtcbiAgfVxuXG4gIC8qKiBUaGUgZXllIHRvZ2dsZTogaGlkZSBvciBzaG93IGdlbmVzIHdpdGhvdXQgcmVtb3ZpbmcgdGhlbSBmcm9tIHRoZSBzZWxlY3Rpb24uICovXG4gIHByb3RlY3RlZCBvbkdlbmVzU2hvd24oZ2VuZXM6IHN0cmluZ1tdLCBvbjogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7XG4gICAgICB0cmFuc2NyaXB0SGlkZGVuR2VuZXM6IHRvZ2dsZUhpZGRlbih0aGlzLnZpZXcudHJhbnNjcmlwdEhpZGRlbkdlbmVzLCBnZW5lcywgb24pLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqIFRoZSByb290IGV5ZSB3aGlsZSBldmVyeSBnZW5lIGlzIGRyYXduOiBoaWRlIG9yIHNob3cgdGhlbSBhbGwgKHRoZSAnwrEnIGxlYXZlcyBcIkFsbCBnZW5lc1wiKS4gKi9cbiAgcHJvdGVjdGVkIG9uQWxsR2VuZXNTaG93bihvbjogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7IHRyYW5zY3JpcHRBbGxHZW5lc0hpZGRlbjogb24gPyBbXSA6IFtBTExfR0VORVNdIH0pO1xuICB9XG5cbiAgLyoqIE9uZSBnZW5lJ3MgZXllIGluIHRoZSBhbGwtZ2VuZXMgbGlzdC4gU2hvd2luZyBvbmUgd2hpbGUgYWxsIGFyZSBvZmYgc2hvd3MgaXQgYWxvbmUuICovXG4gIHByb3RlY3RlZCBvbkFsbEdlbmVTaG93bihnZW5lOiBzdHJpbmcsIG9uOiBib29sZWFuKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNhbkhpZGVBbGxHZW5lcykgcmV0dXJuO1xuICAgIHRoaXMuY29udHJvbHM/LnNldFZpZXdTdGF0ZSh7XG4gICAgICB0cmFuc2NyaXB0QWxsR2VuZXNIaWRkZW46IHRvZ2dsZUFsbEdlbmVIaWRkZW4odGhpcy52aWV3LnRyYW5zY3JpcHRBbGxHZW5lc0hpZGRlbiwgZ2VuZSwgb24pLFxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uR2VuZUNvbG9yKGdlbmU6IHN0cmluZywgaGV4OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0R2VuZUNvbG9yczogeyAuLi50aGlzLnZpZXcudHJhbnNjcmlwdEdlbmVDb2xvcnMsIFtnZW5lXTogaGV4IH0gfSk7XG4gIH1cblxuICAvLyDilIDilIAgcGVyLWdlbmUgaWNvbiBhbmQgY29sb3VyIHBpY2tlciDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBwcm90ZWN0ZWQgb3BlbkdlbmVTdHlsZShldmVudDogRXZlbnQsIGdlbmU6IHN0cmluZywgcGFuZWw6IHsgdG9nZ2xlKGU6IEV2ZW50KTogdm9pZDsgaGlkZSgpOiB2b2lkIH0pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zdHlsZUdlbmUgPT09IGdlbmUpIHtcbiAgICAgIHBhbmVsLnRvZ2dsZShldmVudCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc3R5bGVHZW5lID0gZ2VuZTtcbiAgICBwYW5lbC5oaWRlKCk7XG4gICAgLy8gUmUtb3BlbiBhbmNob3JlZCBvbiB0aGUgcm93IHRoYXQgd2FzIGNsaWNrZWQsIG9uY2UgdGhlIHBhbmVsIGhhcyBjbG9zZWQuXG4gICAgc2V0VGltZW91dCgoKSA9PiBwYW5lbC50b2dnbGUoZXZlbnQpKTtcbiAgfVxuXG4gIC8qKiBUaGUgaWNvbiB0aGUgb3BlbiBwaWNrZXIgc2hvd3MgYXMgY2hvc2VuLiAqL1xuICBwcm90ZWN0ZWQgZ2V0IHN0eWxlR2x5cGgoKTogVHJhbnNjcmlwdEdseXBoTmFtZSB8IG51bGwge1xuICAgIGNvbnN0IGdlbmUgPSB0aGlzLnN0eWxlR2VuZTtcbiAgICByZXR1cm4gZ2VuZSA/IHRoaXMuZ2x5cGhPZihnZW5lLCBNYXRoLm1heCgwLCB0aGlzLnZpZXcudHJhbnNjcmlwdEdlbmVzLmluZGV4T2YoZ2VuZSkpKSA6IG51bGw7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2x5cGhQb2ludHMoZ2x5cGg6IFRyYW5zY3JpcHRHbHlwaE5hbWUpOiBzdHJpbmcge1xuICAgIHJldHVybiBnbHlwaFBvaW50cyhnbHlwaCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2x5cGhPZihnZW5lOiBzdHJpbmcsIHNsb3Q6IG51bWJlcik6IFRyYW5zY3JpcHRHbHlwaE5hbWUge1xuICAgIHJldHVybiB0aGlzLnZpZXcudHJhbnNjcmlwdEdseXBoc1tnZW5lXSA/PyBkZWZhdWx0R2x5cGhGb3Ioc2xvdCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25HbHlwaChnZW5lOiBzdHJpbmcsIGdseXBoOiBUcmFuc2NyaXB0R2x5cGhOYW1lKTogdm9pZCB7XG4gICAgdGhpcy5jb250cm9scz8uc2V0Vmlld1N0YXRlKHsgdHJhbnNjcmlwdEdseXBoczogeyAuLi50aGlzLnZpZXcudHJhbnNjcmlwdEdseXBocywgW2dlbmVdOiBnbHlwaCB9IH0pO1xuICB9XG5cbiAgLyoqIEJhY2sgdG8gdGhlIGdlbmUncyBkZWZhdWx0IGljb24gYW5kIGNvbG91ciAoYnkgaXRzIHBvc2l0aW9uIGluIHRoZSBsaXN0KS4gKi9cbiAgcHJvdGVjdGVkIHJlc2V0R2VuZVN0eWxlKGdlbmU6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGNvbG9ycyA9IHsgLi4udGhpcy52aWV3LnRyYW5zY3JpcHRHZW5lQ29sb3JzIH07XG4gICAgY29uc3QgZ2x5cGhzID0geyAuLi50aGlzLnZpZXcudHJhbnNjcmlwdEdseXBocyB9O1xuICAgIGRlbGV0ZSBjb2xvcnNbZ2VuZV07XG4gICAgZGVsZXRlIGdseXBoc1tnZW5lXTtcbiAgICB0aGlzLmNvbnRyb2xzPy5zZXRWaWV3U3RhdGUoeyB0cmFuc2NyaXB0R2VuZUNvbG9yczogY29sb3JzLCB0cmFuc2NyaXB0R2x5cGhzOiBnbHlwaHMgfSk7XG4gIH1cblxuICAvLyDilIDilIAgY29sb3VycyBhbmQgY291bnRzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIC8qKiBUaGUgY29sb3VyIGdlbmUgYHNsb3RgIGlzIGRyYXduIGluIHdoZW4gdHJhbnNjcmlwdHMgYXJlIGNvbG91cmVkIGJ5IGdlbmUuICovXG4gIGdlbmVDb2xvcihzbG90OiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IGdlbmUgPSB0aGlzLnZpZXc/LnRyYW5zY3JpcHRHZW5lc1tzbG90XTtcbiAgICByZXR1cm4gKFxuICAgICAgKGdlbmUgJiYgdGhpcy52aWV3LnRyYW5zY3JpcHRHZW5lQ29sb3JzW2dlbmVdKSB8fFxuICAgICAgREVGQVVMVF9DQVRFR09SSUNBTF9QQUxFVFRFW3Nsb3QgJSBERUZBVUxUX0NBVEVHT1JJQ0FMX1BBTEVUVEUubGVuZ3RoXVxuICAgICk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2VuZUNvbG9yT2YoZ2VuZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5nZW5lQ29sb3IoTWF0aC5tYXgoMCwgdGhpcy52aWV3LnRyYW5zY3JpcHRHZW5lcy5pbmRleE9mKGdlbmUpKSk7XG4gIH1cblxuICAvKiogSW4gQ2x1c3RlciBjb2xvdXJpbmcsIGEgZ2VuZSdzIHN3YXRjaCBpcyBpdHMgY2x1c3RlcidzIGNvbG91ciwgYXMgaXRzIG1hcmtlcnMgYXJlLiAqL1xuICBwcm90ZWN0ZWQgZ2VuZVN3YXRjaE9mKGdlbmU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMudmlldy50cmFuc2NyaXB0Q29sb3JCeSAhPT0gJ2NsdXN0ZXInKSByZXR1cm4gdGhpcy5nZW5lQ29sb3JPZihnZW5lKTtcbiAgICByZXR1cm4gdGhpcy5jbHVzdGVyQ29sb3JzKCkuZ2V0KGNsdXN0ZXJPZkdlbmUoZ2VuZSwgdGhpcy52aWV3LnRyYW5zY3JpcHRHZW5lR3JvdXBzKSkgPz8gdGhpcy5nZW5lQ29sb3JPZihnZW5lKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZW5lQ291bnRPZihnZW5lOiBzdHJpbmcpOiBudW1iZXIgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5nZW5lQ291bnRzID8gKHRoaXMuZ2VuZUNvdW50c1tnZW5lXSA/PyAwKSA6IG51bGw7XG4gIH1cblxuICBwcm90ZWN0ZWQgdHJhY2tCeU5vZGUgPSAoX2k6IG51bWJlciwgbm9kZTogeyBuYW1lOiBzdHJpbmcgfCBudWxsIH0pID0+IG5vZGUubmFtZSA/PyAnJztcbiAgcHJvdGVjdGVkIHRyYWNrQnlMYWJlbFN0cmluZyA9IChfaTogbnVtYmVyLCBzOiBzdHJpbmcpID0+IHM7XG4gIHByb3RlY3RlZCB0cmFja0J5QWxsUm93ID0gKF9pOiBudW1iZXIsIHJvdzogQWxsR2VuZVJvd1ZpZXcpID0+IHJvdy5nZW5lO1xuXG4gIC8qKlxuICAgKiBUaGUgY2x1c3RlciBjb2xvdXJzLCByZWJ1aWx0IG9ubHkgd2hlbiB3aGF0IHRoZXkgY29tZSBmcm9tIGNoYW5nZXMuIFRoZSB0ZW1wbGF0ZSBhc2tzXG4gICAqIG9uY2UgcGVyIGdlbmUgcm93IHBlciBjaGFuZ2UtZGV0ZWN0aW9uIHBhc3MsIGFuZCByZWJ1aWxkaW5nIHBlciBjYWxsIG1hZGUgdGhhdCBPKEfCsikuXG4gICAqL1xuICBwcml2YXRlIGNsdXN0ZXJDb2xvcnMoKTogTWFwPHN0cmluZywgc3RyaW5nPiB7XG4gICAgY29uc3QgeyB0cmFuc2NyaXB0R2VuZXM6IGdlbmVzLCB0cmFuc2NyaXB0R2VuZUdyb3VwczogZ3JvdXBzIH0gPSB0aGlzLnZpZXc7XG4gICAgY29uc3QgaGl0ID0gdGhpcy5jbHVzdGVyQ29sb3JNZW1vO1xuICAgIGlmIChoaXQgJiYgaGl0LmdlbmVzID09PSBnZW5lcyAmJiBoaXQuZ3JvdXBzID09PSBncm91cHMgJiYgaGl0LmNlbGxDb2xvcnMgPT09IHRoaXMuY2VsbEdyb3VwQ29sb3JzKSB7XG4gICAgICByZXR1cm4gaGl0LmNvbG9ycztcbiAgICB9XG4gICAgY29uc3QgY29sb3JzID0gY2x1c3RlckNvbG9yTWFwKGdlbmVzLCBncm91cHMsIHRoaXMuY2VsbEdyb3VwQ29sb3JzLCBERUZBVUxUX0NBVEVHT1JJQ0FMX1BBTEVUVEUpO1xuICAgIHRoaXMuY2x1c3RlckNvbG9yTWVtbyA9IHsgZ2VuZXMsIGdyb3VwcywgY2VsbENvbG9yczogdGhpcy5jZWxsR3JvdXBDb2xvcnMsIGNvbG9ycyB9O1xuICAgIHJldHVybiBjb2xvcnM7XG4gIH1cbiAgcHJpdmF0ZSBjbHVzdGVyQ29sb3JNZW1vOiB7XG4gICAgZ2VuZXM6IFNwYXRpYWxWaWV3U3RhdGVbJ3RyYW5zY3JpcHRHZW5lcyddO1xuICAgIGdyb3VwczogU3BhdGlhbFZpZXdTdGF0ZVsndHJhbnNjcmlwdEdlbmVHcm91cHMnXTtcbiAgICBjZWxsQ29sb3JzOiBNYXA8c3RyaW5nLCBzdHJpbmc+O1xuICAgIGNvbG9yczogTWFwPHN0cmluZywgc3RyaW5nPjtcbiAgfSB8IG51bGwgPSBudWxsO1xuXG4gIHByaXZhdGUgYXN5bmMgcmVmcmVzaENlbGxHcm91cENvbG9ycygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmRhdGFzZXQgPyBjZWxsVHlwZUNvbHVtbkZvcih0aGlzLmRhdGFzZXQsIHRoaXMudmlldykgOiBudWxsO1xuICAgIGlmIChjb2x1bW4gPT09IHRoaXMuY2VsbEdyb3VwQ29sb3JzRm9yKSByZXR1cm47XG4gICAgdGhpcy5jZWxsR3JvdXBDb2xvcnNGb3IgPSBjb2x1bW47XG4gICAgY29uc3QgdGFzayA9IHRoaXMuY2VsbEdyb3VwQ29sb3JzTG9hZC5uZXh0KCk7XG4gICAgY29uc3QgbWFwID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgICBjb25zdCBtZXRhID0gY29sdW1uID8gdGhpcy5kYXRhc2V0Py5jb2x1bW5zLmZpbmQoKGMpID0+IGMubmFtZSA9PT0gY29sdW1uKSA6IG51bGw7XG4gICAgaWYgKG1ldGEgJiYgbWV0YS5raW5kID09PSAnY2F0ZWdvcmljYWwnICYmIHRoaXMuY29udHJvbHMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGNvbG9ycyA9IGF3YWl0IHRoaXMuY29udHJvbHMuY2F0ZWdvcnlDb2xvcnMoY29sdW1uISk7XG4gICAgICAgIG1ldGEuY2F0ZWdvcmllcy5mb3JFYWNoKChjLCBrKSA9PiB7XG4gICAgICAgICAgaWYgKGNvbG9yc1trXSkgbWFwLnNldChjLCBjb2xvcnNba10pO1xuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBObyBjb2xvdXJzOiBwYWxldHRlIGNvbG91cnMsIGFzIHRoZSBtYXJrZXJzIGZhbGwgYmFjayB0by5cbiAgICAgIH1cbiAgICB9XG4gICAgLy8gVGhlIGNlbGxzJyBncm91cGluZyBjaGFuZ2VkIHdoaWxlIHRoZSBjb2xvdXJzIGxvYWRlZDogdGhlIG5ld2VyIHJlcXVlc3QgYXBwbGllcyBpdHMgb3duLlxuICAgIGlmICghdGFzay5pc0N1cnJlbnQoKSkgcmV0dXJuO1xuICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xuICAgICAgdGhpcy5jZWxsR3JvdXBDb2xvcnMgPSBtYXA7XG4gICAgICB0aGlzLnJlYnVpbGRSb3dzKCk7XG4gICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICB9KTtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cInNjLXN1YmhlYWRcIj5TZWxlY3RlZCBnZW5lczwvZGl2PlxuPGRpdiBjbGFzcz1cInNjLWdlbmUtc29ydFwiICpuZ0lmPVwic29ydFNob3duXCIgcm9sZT1cImdyb3VwXCIgYXJpYS1sYWJlbD1cIlNvcnQgZ2VuZXNcIj5cbiAgPHNwYW4gY2xhc3M9XCJzYy1sYmxcIj5Tb3J0IGJ5PC9zcGFuPlxuICA8YnV0dG9uXG4gICAgdHlwZT1cImJ1dHRvblwiXG4gICAgY2xhc3M9XCJzYy1zb3J0LWJ0blwiXG4gICAgW2NsYXNzLmFjdGl2ZV09XCIhYnlDb3VudFwiXG4gICAgW2F0dHIuYXJpYS1wcmVzc2VkXT1cIiFieUNvdW50XCJcbiAgICAoY2xpY2spPVwib25HZW5lU29ydCgnbmFtZScpXCJcbiAgPlxuICAgIE5hbWVcbiAgPC9idXR0b24+XG4gIDxidXR0b25cbiAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICBjbGFzcz1cInNjLXNvcnQtYnRuXCJcbiAgICBbY2xhc3MuYWN0aXZlXT1cImJ5Q291bnRcIlxuICAgIFthdHRyLmFyaWEtcHJlc3NlZF09XCJieUNvdW50XCJcbiAgICB0aXRsZT1cIlRyYW5zY3JpcHRzIGluIHZpZXcsIG1vc3QgZmlyc3RcIlxuICAgIChjbGljayk9XCJvbkdlbmVTb3J0KCdjb3VudCcpXCJcbiAgPlxuICAgIENvdW50XG4gIDwvYnV0dG9uPlxuPC9kaXY+XG48ZGl2IGNsYXNzPVwic2MtZ2VuZS10cmVlXCI+XG4gIDxkaXYgY2xhc3M9XCJzYy1nZW5lLXJvdyBzYy1nZW5lLXJvb3RcIj5cbiAgICA8YnV0dG9uXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgIGNsYXNzPVwic2MtZXllXCJcbiAgICAgIChjbGljayk9XCJcbiAgICAgICAgdmlldy50cmFuc2NyaXB0QWxsR2VuZXMgPyBvbkFsbEdlbmVzU2hvd24oIXJvb3RTaG93bikgOiBvbkdlbmVzU2hvd24odmlldy50cmFuc2NyaXB0R2VuZXMsICFyb290U2hvd24pXG4gICAgICBcIlxuICAgID5cbiAgICAgIDxpIGNsYXNzPVwicGlcIiBbY2xhc3MucGktZXllXT1cInJvb3RTaG93blwiIFtjbGFzcy5waS1leWUtc2xhc2hdPVwiIXJvb3RTaG93blwiPjwvaT5cbiAgICA8L2J1dHRvbj5cbiAgICA8c3BhbiBjbGFzcz1cInNjLWdyb3VwLWxhYmVsXCI+R2VuZXM8L3NwYW4+XG4gICAgPHNwYW4gY2xhc3M9XCJzYy1jb3VudFwiXG4gICAgICA+KHt7ICh2aWV3LnRyYW5zY3JpcHRBbGxHZW5lcyA/IGdlbmVUb3RhbCA6IHZpZXcudHJhbnNjcmlwdEdlbmVzLmxlbmd0aCkgfCBudW1iZXIgfX0ve3tcbiAgICAgICAgZ2VuZVRvdGFsIHwgbnVtYmVyXG4gICAgICB9fSk8L3NwYW5cbiAgICA+XG4gICAgPGJ1dHRvblxuICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICBjbGFzcz1cInNjLWljb24tYnRuXCJcbiAgICAgIChjbGljayk9XCJnZW5lVHJlZU9wZW4gPSAhZ2VuZVRyZWVPcGVuXCJcbiAgICAgICpuZ0lmPVwiIXZpZXcudHJhbnNjcmlwdEFsbEdlbmVzICYmIHZpZXcudHJhbnNjcmlwdEdlbmVzLmxlbmd0aFwiXG4gICAgPlxuICAgICAgPGkgY2xhc3M9XCJwaVwiIFtjbGFzcy5waS1jaGV2cm9uLWRvd25dPVwiZ2VuZVRyZWVPcGVuXCIgW2NsYXNzLnBpLWNoZXZyb24tcmlnaHRdPVwiIWdlbmVUcmVlT3BlblwiPjwvaT5cbiAgICA8L2J1dHRvbj5cbiAgICA8YnV0dG9uXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgIGNsYXNzPVwic2MtaWNvbi1idG5cIlxuICAgICAgKGNsaWNrKT1cInRvZ2dsZUFsbEdlbmVzT3BlbigpXCJcbiAgICAgICpuZ0lmPVwidmlldy50cmFuc2NyaXB0QWxsR2VuZXMgJiYgYWxsR2VuZUxpc3Q/Lmxlbmd0aFwiXG4gICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFsbEdlbmVzT3BlbiA/ICdIaWRlIHRoZSBnZW5lIGxpc3QnIDogJ1Nob3cgZXZlcnkgZ2VuZSdcIlxuICAgID5cbiAgICAgIDxpIGNsYXNzPVwicGlcIiBbY2xhc3MucGktY2hldnJvbi1kb3duXT1cImFsbEdlbmVzT3BlblwiIFtjbGFzcy5waS1jaGV2cm9uLXJpZ2h0XT1cIiFhbGxHZW5lc09wZW5cIj48L2k+XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuICA8IS0tIFwiQWxsIGdlbmVzXCI6IGV2ZXJ5IGdlbmUgb2YgdGhlIGRhdGFzZXQsIGVhY2ggd2l0aCBpdHMgZXllIHdoZW4gdGhlIGRhdGFzZXQgc2F5cyB3aGljaFxuICAgICAgIHRyYW5zY3JpcHRzIGFyZSB3aG9zZSAoaXRzIGdlbmUgbGlzdCBpbiBjb2RlIG9yZGVyKS4gLS0+XG4gIDxuZy1jb250YWluZXIgKm5nSWY9XCJhbGxHZW5lc09wZW4gJiYgdmlldy50cmFuc2NyaXB0QWxsR2VuZXMgJiYgYWxsR2VuZUxpc3Q/Lmxlbmd0aFwiPlxuICAgIDxpbnB1dFxuICAgICAgcElucHV0VGV4dFxuICAgICAgY2xhc3M9XCJzYy1nZW5lLWZpbHRlclwiXG4gICAgICBwbGFjZWhvbGRlcj1cIkZpbHRlciBnZW5lc+KAplwiXG4gICAgICBhcmlhLWxhYmVsPVwiRmlsdGVyIGdlbmVzXCJcbiAgICAgIFt2YWx1ZV09XCJhbGxHZW5lc0ZpbHRlclwiXG4gICAgICAoaW5wdXQpPVwib25BbGxHZW5lc0ZpbHRlcigkYW55KCRldmVudC50YXJnZXQpLnZhbHVlKVwiXG4gICAgLz5cbiAgICA8c21hbGwgY2xhc3M9XCJzYy1oaW50XCIgKm5nSWY9XCIhY2FuSGlkZUFsbEdlbmVzXCI+XG4gICAgICBUaGlzIGRhdGFzZXQgZG9lcyBub3Qgc2F5IHdoaWNoIHRyYW5zY3JpcHRzIGFyZSB3aG9zZSwgc28gaXRzIGdlbmVzIGNhbm5vdCBiZSBoaWRkZW4gb25lIGJ5IG9uZS5cbiAgICA8L3NtYWxsPlxuICAgIDxzbWFsbCBjbGFzcz1cInNjLWhpbnRcIiAqbmdJZj1cImNhbkhpZGVBbGxHZW5lcyAmJiB2aWV3LnRyYW5zY3JpcHRNb2RlID09PSAnZGVuc2l0eSdcIj5cbiAgICAgIFRoZSBkZW5zaXR5IG1hcCBkcmF3cyBldmVyeSBnZW5lIGFzIG9uZSByYXN0ZXI6IGdlbmVzIGFyZSBoaWRkZW4gb25lIGJ5IG9uZSBhcyBjaXJjbGVzIG9yIGljb25zLlxuICAgIDwvc21hbGw+XG4gICAgPGRpdiBjbGFzcz1cInNjLWdlbmUtcm93IHNjLWdlbmUtbGVhZiBuZXN0ZWRcIiAqbmdGb3I9XCJsZXQgcm93IG9mIGFsbFJvd3M7IHRyYWNrQnk6IHRyYWNrQnlBbGxSb3dcIj5cbiAgICAgIDxidXR0b25cbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIGNsYXNzPVwic2MtZXllXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cIiFjYW5IaWRlQWxsR2VuZXMgfHwgdmlldy50cmFuc2NyaXB0TW9kZSA9PT0gJ2RlbnNpdHknXCJcbiAgICAgICAgKGNsaWNrKT1cIm9uQWxsR2VuZVNob3duKHJvdy5nZW5lLCAhcm93LnNob3duKVwiXG4gICAgICA+XG4gICAgICAgIDxpIGNsYXNzPVwicGlcIiBbY2xhc3MucGktZXllXT1cInJvdy5zaG93blwiIFtjbGFzcy5waS1leWUtc2xhc2hdPVwiIXJvdy5zaG93blwiPjwvaT5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHNwYW4gY2xhc3M9XCJzYy1nZW5lLWljb25cIiAqbmdJZj1cInJvdy5zd2F0Y2hcIiBbc3R5bGUuY29sb3JdPVwicm93LnN3YXRjaFwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuICAgICAgICA8c3ZnIHZpZXdCb3g9XCItMS4yIC0xLjIgMi40IDIuNFwiIGNsYXNzPVwic2MtZ2x5cGgtc3ZnXCI+PGNpcmNsZSByPVwiMC43NVwiPjwvY2lyY2xlPjwvc3ZnPlxuICAgICAgPC9zcGFuPlxuICAgICAgPHNwYW4gY2xhc3M9XCJzYy1ncm91cC1sYWJlbFwiIFt0aXRsZV09XCJyb3cuZ2VuZVwiPnt7IHJvdy5nZW5lIH19PC9zcGFuPlxuICAgICAgPHNwYW4gY2xhc3M9XCJzYy1nZW5lLWNvdW50XCIgKm5nSWY9XCJyb3cuY291bnQgIT09IG51bGxcIiB0aXRsZT1cIlRyYW5zY3JpcHRzIGluIHZpZXdcIj57e1xuICAgICAgICByb3cuY291bnQgfCBudW1iZXJcbiAgICAgIH19PC9zcGFuPlxuICAgIDwvZGl2PlxuICAgIDxzbWFsbCBjbGFzcz1cInNjLWhpbnRcIiAqbmdJZj1cImFsbEdlbmVzTWF0Y2hlZCA+IGFsbFJvd3MubGVuZ3RoXCI+XG4gICAgICBTaG93aW5nIHt7IGFsbFJvd3MubGVuZ3RoIHwgbnVtYmVyIH19IG9mIHt7IGFsbEdlbmVzTWF0Y2hlZCB8IG51bWJlciB9fSBnZW5lczogZmlsdGVyIHRvIGZpbmQgdGhlIG90aGVycy5cbiAgICA8L3NtYWxsPlxuICAgIDxzbWFsbCBjbGFzcz1cInNjLWhpbnRcIiAqbmdJZj1cImFsbEdlbmVzTWF0Y2hlZCA9PT0gMFwiPk5vIGdlbmUgbWF0Y2hlcy48L3NtYWxsPlxuICA8L25nLWNvbnRhaW5lcj5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImdlbmVUcmVlT3BlbiAmJiAhdmlldy50cmFuc2NyaXB0QWxsR2VuZXNcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBub2RlIG9mIHNvcnRlZFRyZWU7IHRyYWNrQnk6IHRyYWNrQnlOb2RlXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwic2MtZ2VuZS1yb3cgc2MtZ2VuZS1ncm91cFwiICpuZ0lmPVwibm9kZS5uYW1lXCI+XG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwic2MtZXllXCIgKGNsaWNrKT1cIm9uR2VuZXNTaG93bihub2RlLmdlbmVzLCAhZ3JvdXBTaG93bi5nZXQobm9kZS5uYW1lKSlcIj5cbiAgICAgICAgICA8aVxuICAgICAgICAgICAgY2xhc3M9XCJwaVwiXG4gICAgICAgICAgICBbY2xhc3MucGktZXllXT1cImdyb3VwU2hvd24uZ2V0KG5vZGUubmFtZSlcIlxuICAgICAgICAgICAgW2NsYXNzLnBpLWV5ZS1zbGFzaF09XCIhZ3JvdXBTaG93bi5nZXQobm9kZS5uYW1lKVwiXG4gICAgICAgICAgPjwvaT5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwic2MtZ3JvdXAtbGFiZWxcIiBbdGl0bGVdPVwibm9kZS5uYW1lXCI+e3sgbm9kZS5uYW1lIH19PC9zcGFuPlxuICAgICAgICA8c3BhbiBjbGFzcz1cInNjLWNvdW50XCI+KHt7IG5vZGUuZ2VuZXMubGVuZ3RoIH19KTwvc3Bhbj5cbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJzYy1pY29uLWJ0blwiIChjbGljayk9XCJ0b2dnbGVHZW5lR3JvdXAobm9kZS5uYW1lKVwiPlxuICAgICAgICAgIDxpXG4gICAgICAgICAgICBjbGFzcz1cInBpXCJcbiAgICAgICAgICAgIFtjbGFzcy5waS1jaGV2cm9uLWRvd25dPVwiIWNvbGxhcHNlZEdlbmVHcm91cHMuaGFzKG5vZGUubmFtZSlcIlxuICAgICAgICAgICAgW2NsYXNzLnBpLWNoZXZyb24tcmlnaHRdPVwiY29sbGFwc2VkR2VuZUdyb3Vwcy5oYXMobm9kZS5uYW1lKVwiXG4gICAgICAgICAgPjwvaT5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhbm9kZS5uYW1lIHx8ICFjb2xsYXBzZWRHZW5lR3JvdXBzLmhhcyhub2RlLm5hbWUpXCI+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICBjbGFzcz1cInNjLWdlbmUtcm93IHNjLWdlbmUtbGVhZlwiXG4gICAgICAgICAgW2NsYXNzLm5lc3RlZF09XCIhIW5vZGUubmFtZVwiXG4gICAgICAgICAgKm5nRm9yPVwibGV0IGdlbmUgb2Ygbm9kZS5nZW5lczsgdHJhY2tCeTogdHJhY2tCeUxhYmVsU3RyaW5nXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwic2MtZXllXCIgKGNsaWNrKT1cIm9uR2VuZXNTaG93bihbZ2VuZV0sICFyb3dzLmdldChnZW5lKT8uc2hvd24pXCI+XG4gICAgICAgICAgICA8aSBjbGFzcz1cInBpXCIgW2NsYXNzLnBpLWV5ZV09XCJyb3dzLmdldChnZW5lKT8uc2hvd25cIiBbY2xhc3MucGktZXllLXNsYXNoXT1cIiFyb3dzLmdldChnZW5lKT8uc2hvd25cIj48L2k+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPCEtLSBUaGUgZ2VuZSdzIG1hcmtlciwgaW4gaXRzIGNvbG91cjogaXRzIGljb24gaW4gSWNvbnMgbW9kZSwgYSBkb3QgZm9yIGNpcmNsZXMuXG4gICAgICAgICAgICAgICBDbGlja2luZyBpdCBvcGVucyB0aGUgaWNvbiBhbmQgY29sb3VyIHBpY2tlciAoYXMgWGVuaXVtIEV4cGxvcmVyIGRvZXMpLiAtLT5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNsYXNzPVwic2MtZ2VuZS1pY29uXCJcbiAgICAgICAgICAgIFtzdHlsZS5jb2xvcl09XCJyb3dzLmdldChnZW5lKT8uc3dhdGNoXCJcbiAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ0ljb24gYW5kIGNvbG91ciBmb3IgJyArIGdlbmVcIlxuICAgICAgICAgICAgcFRvb2x0aXA9XCJJY29uIGFuZCBjb2xvdXJcIlxuICAgICAgICAgICAgdG9vbHRpcFBvc2l0aW9uPVwidG9wXCJcbiAgICAgICAgICAgIChjbGljayk9XCJvcGVuR2VuZVN0eWxlKCRldmVudCwgZ2VuZSwgZ2VuZVBvcClcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxzdmcgdmlld0JveD1cIi0xLjIgLTEuMiAyLjQgMi40XCIgY2xhc3M9XCJzYy1nbHlwaC1zdmdcIj5cbiAgICAgICAgICAgICAgPHBvbHlnb25cbiAgICAgICAgICAgICAgICAqbmdJZj1cInZpZXcudHJhbnNjcmlwdE1vZGUgPT09ICdnbHlwaHMnOyBlbHNlIGRvdEljb25cIlxuICAgICAgICAgICAgICAgIFthdHRyLnBvaW50c109XCJyb3dzLmdldChnZW5lKT8ucG9pbnRzXCJcbiAgICAgICAgICAgICAgPjwvcG9seWdvbj5cbiAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNkb3RJY29uPjxjaXJjbGUgcj1cIjAuNzVcIj48L2NpcmNsZT48L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJzYy1ncm91cC1sYWJlbFwiPnt7IGdlbmUgfX08L3NwYW4+XG4gICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgIGNsYXNzPVwic2MtZ2VuZS1jb3VudFwiXG4gICAgICAgICAgICAqbmdJZj1cInJvd3MuZ2V0KGdlbmUpPy5jb3VudCBhcyBuOyBlbHNlIHplcm9Db3VudFwiXG4gICAgICAgICAgICB0aXRsZT1cIlRyYW5zY3JpcHRzIGluIHZpZXdcIlxuICAgICAgICAgICAgPnt7IG4gfCBudW1iZXIgfX08L3NwYW5cbiAgICAgICAgICA+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICN6ZXJvQ291bnQ+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInNjLWdlbmUtY291bnRcIiAqbmdJZj1cImdlbmVDb3VudHNcIiB0aXRsZT1cIlRyYW5zY3JpcHRzIGluIHZpZXdcIj4wPC9zcGFuPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIDwvbmctY29udGFpbmVyPlxuICA8IS0tIE9uZSBwaWNrZXIgZm9yIGV2ZXJ5IGdlbmUgcm93LCBmaWxsZWQgZm9yIHRoZSBnZW5lIHRoYXQgb3BlbmVkIGl0LiAtLT5cbiAgPHAtb3ZlcmxheVBhbmVsICNnZW5lUG9wIHN0eWxlQ2xhc3M9XCJzYy1nZW5lLXN0eWxlXCIgYXBwZW5kVG89XCJib2R5XCI+XG4gICAgPG5nLXRlbXBsYXRlIHBUZW1wbGF0ZT1cImNvbnRlbnRcIj5cbiAgICAgIDxzcGF0aWFsLWdlbmUtc3R5bGVcbiAgICAgICAgKm5nSWY9XCJzdHlsZUdlbmUgYXMgZ2VuZVwiXG4gICAgICAgIFtnZW5lXT1cImdlbmVcIlxuICAgICAgICB3aGF0PVwiVHJhbnNjcmlwdFwiXG4gICAgICAgIFtjb2xvcl09XCJnZW5lQ29sb3JPZihnZW5lKVwiXG4gICAgICAgIFtnbHlwaF09XCJzdHlsZUdseXBoID8/ICdjaXJjbGUnXCJcbiAgICAgICAgW2ljb25IaW50XT1cIlxuICAgICAgICAgIHZpZXcudHJhbnNjcmlwdE1vZGUgIT09ICdnbHlwaHMnID8gJ0ljb25zIHNob3cgd2hlbiB0aGUgdHJhbnNjcmlwdCBwb2ludCBzdHlsZSBpcyBJY29ucy4nIDogbnVsbFxuICAgICAgICBcIlxuICAgICAgICAoY29sb3JDaGFuZ2UpPVwib25HZW5lQ29sb3IoZ2VuZSwgJGV2ZW50KVwiXG4gICAgICAgIChnbHlwaENoYW5nZSk9XCJvbkdseXBoKGdlbmUsICRldmVudClcIlxuICAgICAgICAocmVzZXRTdHlsZSk9XCJyZXNldEdlbmVTdHlsZShnZW5lKVwiXG4gICAgICA+PC9zcGF0aWFsLWdlbmUtc3R5bGU+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbiAgPC9wLW92ZXJsYXlQYW5lbD5cbiAgPGRpdiBjbGFzcz1cInNjLWdlbmUtZm9vdGVyXCI+XG4gICAge3sgKHZpZXcudHJhbnNjcmlwdEFsbEdlbmVzID8gZ2VuZVRvdGFsIDogdmlldy50cmFuc2NyaXB0R2VuZXMubGVuZ3RoKSB8IG51bWJlciB9fS97eyBnZW5lVG90YWwgfCBudW1iZXIgfX1cbiAgICBnZW5lcyBzZWxlY3RlZFxuICA8L2Rpdj5cbjwvZGl2PlxuIl19