@jax-data-science/sci-image-visualizer 0.9.0 → 0.10.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 (131) hide show
  1. package/esm2022/index.mjs +7 -1
  2. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  3. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  4. package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
  5. package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
  6. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  7. package/esm2022/lib/contracts/viz-config.mjs +1 -1
  8. package/esm2022/lib/geometry/loft.mjs +128 -0
  9. package/esm2022/lib/geometry/polylabel.mjs +156 -0
  10. package/esm2022/lib/geometry/reconstruct.mjs +315 -0
  11. package/esm2022/lib/geometry/reslice-image.mjs +57 -0
  12. package/esm2022/lib/geometry/section.mjs +215 -0
  13. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +11 -7
  14. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +20 -3
  15. package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
  16. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +28 -5
  17. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
  18. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +9 -2
  19. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +5 -2
  20. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +81 -1
  21. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
  22. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +115 -4
  23. package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
  24. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +15 -3
  25. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +18 -7
  26. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +38 -8
  27. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +1 -1
  28. package/esm2022/lib/models/class-preset.mjs +1 -1
  29. package/esm2022/lib/models/polygon-factory.mjs +17 -1
  30. package/esm2022/lib/models/region-geojson.mjs +44 -6
  31. package/esm2022/lib/models/region.mjs +1 -1
  32. package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
  33. package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
  34. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +77 -13
  35. package/esm2022/lib/region-editor/region-editor.component.mjs +527 -42
  36. package/esm2022/lib/region-editor/region-metrics.mjs +20 -2
  37. package/esm2022/lib/region-editor/region-persistence.service.mjs +36 -10
  38. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +24 -8
  39. package/esm2022/lib/region-overlay/region-geometry.mjs +3 -3
  40. package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
  41. package/esm2022/lib/region-overlay/region-style.mjs +97 -0
  42. package/esm2022/lib/region-source/http-region-source.mjs +104 -0
  43. package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
  44. package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
  45. package/esm2022/lib/region-source/region-source.mjs +67 -0
  46. package/esm2022/lib/region-source/region-tiles.mjs +708 -0
  47. package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
  48. package/esm2022/lib/routing-visualizer.service.mjs +418 -22
  49. package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
  50. package/esm2022/lib/store/class-color.util.mjs +10 -5
  51. package/esm2022/lib/store/class-signatures.mjs +63 -0
  52. package/esm2022/lib/store/region-scope-cache.mjs +5 -1
  53. package/esm2022/lib/store/region-source-scope.mjs +171 -0
  54. package/esm2022/lib/store/region-store.service.mjs +724 -12
  55. package/esm2022/lib/store/visualizer-store.service.mjs +33 -6
  56. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +8 -2
  57. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +55 -15
  58. package/esm2022/lib/toolbar/toolbar.component.mjs +19 -5
  59. package/esm2022/lib/visualizer/region-load.mjs +67 -4
  60. package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
  61. package/esm2022/lib/visualizer.component.mjs +128 -6
  62. package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs} +7239 -1153
  63. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
  64. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs} +4 -4
  65. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map} +1 -1
  66. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
  67. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
  68. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +3 -3
  69. package/fesm2022/region-source.worker.js +1067 -0
  70. package/index.d.ts +6 -0
  71. package/lib/contracts/image.contract.d.ts +4 -0
  72. package/lib/contracts/region-editor-api.contract.d.ts +84 -0
  73. package/lib/contracts/region-store.contract.d.ts +22 -0
  74. package/lib/contracts/section-view.contract.d.ts +44 -0
  75. package/lib/contracts/visualizer.contract.d.ts +10 -0
  76. package/lib/contracts/viz-config.d.ts +8 -0
  77. package/lib/geometry/loft.d.ts +22 -0
  78. package/lib/geometry/polylabel.d.ts +23 -0
  79. package/lib/geometry/reconstruct.d.ts +54 -0
  80. package/lib/geometry/reslice-image.d.ts +33 -0
  81. package/lib/geometry/section.d.ts +52 -0
  82. package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -2
  83. package/lib/implementations/napari-js/napari-loading-state.d.ts +8 -1
  84. package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
  85. package/lib/implementations/napari-js/napari-region-overlay.d.ts +6 -1
  86. package/lib/implementations/napari-js/napari-scene.d.ts +33 -0
  87. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +3 -1
  88. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +48 -0
  89. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
  90. package/lib/implementations/napari-js/napari-volume-scene.d.ts +45 -1
  91. package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
  92. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +4 -3
  93. package/lib/implementations/osd/osd-region-overlay.d.ts +10 -3
  94. package/lib/implementations/tile-server/tile-protocol.d.ts +3 -0
  95. package/lib/models/class-preset.d.ts +7 -0
  96. package/lib/models/polygon-factory.d.ts +5 -0
  97. package/lib/models/region-geojson.d.ts +40 -0
  98. package/lib/models/region.d.ts +19 -0
  99. package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
  100. package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
  101. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +36 -6
  102. package/lib/region-editor/region-editor.component.d.ts +133 -17
  103. package/lib/region-editor/region-metrics.d.ts +8 -0
  104. package/lib/region-editor/region-persistence.service.d.ts +12 -4
  105. package/lib/region-editor/region-table/region-table.component.d.ts +10 -4
  106. package/lib/region-overlay/region-geometry.d.ts +4 -3
  107. package/lib/region-overlay/region-source-layer.d.ts +96 -0
  108. package/lib/region-overlay/region-style.d.ts +52 -0
  109. package/lib/region-source/http-region-source.d.ts +45 -0
  110. package/lib/region-source/region-source-ops.d.ts +89 -0
  111. package/lib/region-source/region-source-worker.d.ts +7 -0
  112. package/lib/region-source/region-source.d.ts +82 -0
  113. package/lib/region-source/region-tiles.d.ts +289 -0
  114. package/lib/region-source/worker-region-source.d.ts +65 -0
  115. package/lib/routing-visualizer.service.d.ts +138 -1
  116. package/lib/section-pane/section-pane.component.d.ts +47 -0
  117. package/lib/store/class-color.util.d.ts +6 -3
  118. package/lib/store/class-signatures.d.ts +11 -0
  119. package/lib/store/region-scope-cache.d.ts +2 -0
  120. package/lib/store/region-source-scope.d.ts +68 -0
  121. package/lib/store/region-store.service.d.ts +206 -2
  122. package/lib/store/visualizer-store.service.d.ts +10 -0
  123. package/lib/toolbar/region-tools/region-tools.component.d.ts +3 -1
  124. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +20 -9
  125. package/lib/toolbar/toolbar.component.d.ts +9 -2
  126. package/lib/visualizer/region-load.d.ts +23 -4
  127. package/lib/visualizer/volume-sections.d.ts +64 -0
  128. package/lib/visualizer.component.d.ts +31 -0
  129. package/package.json +2 -2
  130. package/src/lib/assets/slice.svg +23 -0
  131. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +0 -1
@@ -2,20 +2,18 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from
2
2
  import { CommonModule } from '@angular/common';
3
3
  import { FormsModule } from '@angular/forms';
4
4
  import { ButtonModule } from 'primeng/button';
5
- import { InputNumberModule } from 'primeng/inputnumber';
6
5
  import { SliderModule } from 'primeng/slider';
7
6
  import { TooltipModule } from 'primeng/tooltip';
8
7
  import * as i0 from "@angular/core";
9
8
  import * as i1 from "@angular/common";
10
9
  import * as i2 from "@angular/forms";
11
10
  import * as i3 from "primeng/button";
12
- import * as i4 from "primeng/inputnumber";
13
- import * as i5 from "primeng/slider";
14
- import * as i6 from "primeng/tooltip";
11
+ import * as i4 from "primeng/slider";
12
+ import * as i5 from "primeng/tooltip";
15
13
  /**
16
- * The toolbar's z-stack group: a live slice scrubber for the views that swap
17
- * slices in place, or (Plotly heatmap) the single-image / stack toggle with a
18
- * slice-number field. Presentational: the host owns `zIndex`.
14
+ * The toolbar's z-stack group: the slice bar, and (Plotly heatmap) the single-image / stack
15
+ * toggle. The views that swap slices in place follow the bar as it moves; the heatmap's single
16
+ * image is re-plotted at the slice it settles on. Presentational: the host owns `zIndex`.
19
17
  */
20
18
  export class StackControlsComponent {
21
19
  constructor() {
@@ -40,21 +38,63 @@ export class StackControlsComponent {
40
38
  this.zSlide = new EventEmitter();
41
39
  /** A stack-mode choice was picked. */
42
40
  this.selectStackOption = new EventEmitter();
43
- /** A slice number was typed (blank reports the current slice). */
41
+ /** The heatmap's slice bar moved to a slice (the host shows its number). */
44
42
  this.zIndexInput = new EventEmitter();
45
- /** Enter in the slice field / the reload button: re-plot at the typed slice. */
43
+ /** The heatmap's slice bar settled: re-plot at that slice. */
46
44
  this.reloadAndPlot = new EventEmitter();
45
+ /** A drag of the bar is under way (its end re-plots the heatmap, not each step). */
46
+ this.dragging = false;
47
+ this.replot = null;
47
48
  }
48
- /** The slice field reports what was typed (blank keeps the current slice). */
49
- onSliceInput(value) {
50
- this.zIndexInput.emit(value == null || value === '' ? this.zIndex : Number(value));
49
+ /** How long key steps on the heatmap's bar pause before the slice is re-plotted. */
50
+ static { this.REPLOT_DELAY_MS = 400; }
51
+ /** The heatmap in single-image mode: its bar re-plots the slice it settles on. */
52
+ get singleImage() {
53
+ return this.stackToggle && !this.showStack;
54
+ }
55
+ /** The bar moved: a live view follows it; the heatmap shows the number, and re-plots after key steps pause. */
56
+ onSliceChange(z) {
57
+ if (z === undefined)
58
+ return;
59
+ if (this.liveScrubber) {
60
+ this.zScrub.emit(z);
61
+ return;
62
+ }
63
+ this.zIndexInput.emit(z);
64
+ if (this.dragging)
65
+ return;
66
+ this.cancelReplot();
67
+ this.replot = setTimeout(() => {
68
+ this.replot = null;
69
+ this.reloadAndPlot.emit();
70
+ }, StackControlsComponent.REPLOT_DELAY_MS);
71
+ }
72
+ /** The bar was let go (a drag's end, or a click on its track). */
73
+ onSliceEnd(z) {
74
+ this.dragging = false;
75
+ if (this.liveScrubber) {
76
+ this.zSlide.emit(z);
77
+ return;
78
+ }
79
+ if (z !== undefined)
80
+ this.zIndexInput.emit(z);
81
+ this.cancelReplot();
82
+ this.reloadAndPlot.emit();
83
+ }
84
+ cancelReplot() {
85
+ if (this.replot !== null)
86
+ clearTimeout(this.replot);
87
+ this.replot = null;
88
+ }
89
+ ngOnDestroy() {
90
+ this.cancelReplot();
51
91
  }
52
92
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: StackControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
53
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: StackControlsComponent, isStandalone: true, selector: "toolbar-stack-controls", inputs: { liveScrubber: "liveScrubber", stackToggle: "stackToggle", showStack: "showStack", stackOptions: "stackOptions", zIndex: "zIndex", maxIndex: "maxIndex" }, outputs: { zScrub: "zScrub", zSlide: "zSlide", selectStackOption: "selectStackOption", zIndexInput: "zIndexInput", reloadAndPlot: "reloadAndPlot" }, ngImport: i0, template: "<span class=\"toolbar-separator\"></span>\n<!-- Live views: scrub z-slices (the renderer swaps slices in place). -->\n<ng-container *ngIf=\"liveScrubber\">\n <span class=\"flex align-items-center mx-1 toolbar-text\">Slice</span>\n <p-slider\n [ngModel]=\"zIndex\"\n [min]=\"0\"\n [max]=\"maxIndex\"\n ariaLabel=\"Slice\"\n (onChange)=\"zScrub.emit($event.value)\"\n (onSlideEnd)=\"zSlide.emit($event.value)\"\n pTooltip=\"Slice through the stack (\u2190 / \u2192 keys)\"\n tooltipPosition=\"bottom\"\n [style]=\"{ width: '16rem' }\"\n styleClass=\"wand-sensitivity-slider\"\n ></p-slider>\n <span class=\"flex align-items-center mx-1 toolbar-text\">{{ zIndex }} of {{ maxIndex }}</span>\n</ng-container>\n<!-- Heatmap view: single-image (high-def zoom) vs stack (frame slider). Plotly-only \u2014\n hidden for napari, which has no single/stack toggle or per-frame fetch, and for the\n spatial-omics modes: a 3D omics dataset publishes its reference volume as a z-stack\n image, and these modes draw observations, not one of its slices. -->\n<ng-container *ngIf=\"stackToggle\">\n <p-button\n icon=\"pi pi-image\"\n size=\"small\"\n ariaLabel=\"Single image mode\"\n [text]=\"showStack\"\n pTooltip=\"Single image mode: enables high-def zoom\"\n tooltipPosition=\"bottom\"\n (onClick)=\"selectStackOption.emit(stackOptions[0])\"\n >\n </p-button>\n <p-button\n icon=\"pi pi-images\"\n size=\"small\"\n ariaLabel=\"Stack mode\"\n [text]=\"!showStack\"\n pTooltip=\"Stack mode, enables slicing through image frames\"\n tooltipPosition=\"bottom\"\n (onClick)=\"selectStackOption.emit(stackOptions[1])\"\n >\n </p-button>\n <ng-container *ngIf=\"!showStack\">\n <span class=\"flex align-items-center mx-1 toolbar-text\">Slice</span>\n <div class=\"p-inputgroup\" style=\"width: auto\">\n <p-inputNumber\n styleClass=\"w-3rem toolbar-input\"\n ariaLabel=\"Slice number\"\n pTooltip=\"View image in stack (&#x23CE;)\"\n [ngModel]=\"zIndex\"\n [min]=\"0\"\n [max]=\"maxIndex\"\n (onInput)=\"onSliceInput($event.value)\"\n (keydown.enter)=\"reloadAndPlot.emit()\"\n />\n <p-button\n icon=\"pi pi-refresh\"\n size=\"small\"\n [text]=\"true\"\n ariaLabel=\"Plot this slice\"\n (onClick)=\"reloadAndPlot.emit()\"\n pTooltip=\"Plot this slice\"\n tooltipPosition=\"bottom\"\n >\n </p-button>\n </div>\n <span class=\"flex align-items-center mx-1 toolbar-text\">of {{ maxIndex }}</span>\n </ng-container>\n</ng-container>\n", styles: [".toolbar-text{color:var(--primary-color);font-size:.875rem}.toolbar-separator{border-left:1px solid var(--surface-border);height:1.5rem;margin:0 .25rem;align-self:center}.toolbar-icon-dark{filter:brightness(0) invert(47%) sepia(98%) saturate(567%) hue-rotate(181deg) brightness(103%) contrast(98%)}.toolbar-icon-active{filter:brightness(0) invert(1)}.wand-sensitivity-value{min-width:2rem;text-align:right}:host{display:contents}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i3.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i4.InputNumber, selector: "p-inputNumber", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabelledBy", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "variant", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus", "disabled"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: SliderModule }, { kind: "component", type: i5.Slider, selector: "p-slider", inputs: ["animate", "disabled", "min", "max", "orientation", "step", "range", "style", "styleClass", "ariaLabel", "ariaLabelledBy", "tabindex", "autofocus"], outputs: ["onChange", "onSlideEnd"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
93
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: StackControlsComponent, isStandalone: true, selector: "toolbar-stack-controls", inputs: { liveScrubber: "liveScrubber", stackToggle: "stackToggle", showStack: "showStack", stackOptions: "stackOptions", zIndex: "zIndex", maxIndex: "maxIndex" }, outputs: { zScrub: "zScrub", zSlide: "zSlide", selectStackOption: "selectStackOption", zIndexInput: "zIndexInput", reloadAndPlot: "reloadAndPlot" }, ngImport: i0, template: "<span class=\"toolbar-separator\"></span>\n<!-- Heatmap view: single-image (high-def zoom) vs stack (frame slider). Plotly-only \u2014\n hidden for napari, which has no single/stack toggle or per-frame fetch, and for the\n spatial-omics modes: a 3D omics dataset publishes its reference volume as a z-stack\n image, and these modes draw observations, not one of its slices. -->\n<ng-container *ngIf=\"stackToggle\">\n <p-button\n icon=\"pi pi-image\"\n size=\"small\"\n ariaLabel=\"Single image mode\"\n [text]=\"showStack\"\n pTooltip=\"Single image mode: enables high-def zoom\"\n tooltipPosition=\"bottom\"\n (onClick)=\"selectStackOption.emit(stackOptions[0])\"\n >\n </p-button>\n <p-button\n icon=\"pi pi-images\"\n size=\"small\"\n ariaLabel=\"Stack mode\"\n [text]=\"!showStack\"\n pTooltip=\"Stack mode, enables slicing through image frames\"\n tooltipPosition=\"bottom\"\n (onClick)=\"selectStackOption.emit(stackOptions[1])\"\n >\n </p-button>\n</ng-container>\n<!-- The slice bar. Live views swap the slice in place as it moves; the heatmap's single image\n is re-plotted at the slice the bar settles on (a drag let go, or a pause in key steps). -->\n<ng-container *ngIf=\"liveScrubber || singleImage\">\n <span class=\"flex align-items-center mx-1 toolbar-text\">Slice</span>\n <p-slider\n [ngModel]=\"zIndex\"\n [min]=\"0\"\n [max]=\"maxIndex\"\n ariaLabel=\"Slice\"\n (pointerdown)=\"dragging = true\"\n (onChange)=\"onSliceChange($event.value)\"\n (onSlideEnd)=\"onSliceEnd($event.value)\"\n [pTooltip]=\"liveScrubber ? 'Slice through the stack (\u2190 / \u2192 keys)' : 'Slice to plot (\u2190 / \u2192 keys)'\"\n tooltipPosition=\"bottom\"\n [style]=\"{ width: '16rem' }\"\n styleClass=\"wand-sensitivity-slider\"\n ></p-slider>\n <span class=\"flex align-items-center mx-1 toolbar-text\">{{ zIndex }} of {{ maxIndex }}</span>\n</ng-container>\n", styles: [".toolbar-text{color:var(--primary-color);font-size:.875rem}.toolbar-separator{border-left:1px solid var(--surface-border);height:1.5rem;margin:0 .25rem;align-self:center}.toolbar-icon-dark{filter:brightness(0) invert(47%) sepia(98%) saturate(567%) hue-rotate(181deg) brightness(103%) contrast(98%)}.toolbar-icon-active{filter:brightness(0) invert(1)}.wand-sensitivity-value{min-width:2rem;text-align:right}:host{display:contents}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i3.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SliderModule }, { kind: "component", type: i4.Slider, selector: "p-slider", inputs: ["animate", "disabled", "min", "max", "orientation", "step", "range", "style", "styleClass", "ariaLabel", "ariaLabelledBy", "tabindex", "autofocus"], outputs: ["onChange", "onSlideEnd"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
54
94
  }
55
95
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: StackControlsComponent, decorators: [{
56
96
  type: Component,
57
- args: [{ selector: 'toolbar-stack-controls', standalone: true, imports: [CommonModule, FormsModule, ButtonModule, InputNumberModule, SliderModule, TooltipModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"toolbar-separator\"></span>\n<!-- Live views: scrub z-slices (the renderer swaps slices in place). -->\n<ng-container *ngIf=\"liveScrubber\">\n <span class=\"flex align-items-center mx-1 toolbar-text\">Slice</span>\n <p-slider\n [ngModel]=\"zIndex\"\n [min]=\"0\"\n [max]=\"maxIndex\"\n ariaLabel=\"Slice\"\n (onChange)=\"zScrub.emit($event.value)\"\n (onSlideEnd)=\"zSlide.emit($event.value)\"\n pTooltip=\"Slice through the stack (\u2190 / \u2192 keys)\"\n tooltipPosition=\"bottom\"\n [style]=\"{ width: '16rem' }\"\n styleClass=\"wand-sensitivity-slider\"\n ></p-slider>\n <span class=\"flex align-items-center mx-1 toolbar-text\">{{ zIndex }} of {{ maxIndex }}</span>\n</ng-container>\n<!-- Heatmap view: single-image (high-def zoom) vs stack (frame slider). Plotly-only \u2014\n hidden for napari, which has no single/stack toggle or per-frame fetch, and for the\n spatial-omics modes: a 3D omics dataset publishes its reference volume as a z-stack\n image, and these modes draw observations, not one of its slices. -->\n<ng-container *ngIf=\"stackToggle\">\n <p-button\n icon=\"pi pi-image\"\n size=\"small\"\n ariaLabel=\"Single image mode\"\n [text]=\"showStack\"\n pTooltip=\"Single image mode: enables high-def zoom\"\n tooltipPosition=\"bottom\"\n (onClick)=\"selectStackOption.emit(stackOptions[0])\"\n >\n </p-button>\n <p-button\n icon=\"pi pi-images\"\n size=\"small\"\n ariaLabel=\"Stack mode\"\n [text]=\"!showStack\"\n pTooltip=\"Stack mode, enables slicing through image frames\"\n tooltipPosition=\"bottom\"\n (onClick)=\"selectStackOption.emit(stackOptions[1])\"\n >\n </p-button>\n <ng-container *ngIf=\"!showStack\">\n <span class=\"flex align-items-center mx-1 toolbar-text\">Slice</span>\n <div class=\"p-inputgroup\" style=\"width: auto\">\n <p-inputNumber\n styleClass=\"w-3rem toolbar-input\"\n ariaLabel=\"Slice number\"\n pTooltip=\"View image in stack (&#x23CE;)\"\n [ngModel]=\"zIndex\"\n [min]=\"0\"\n [max]=\"maxIndex\"\n (onInput)=\"onSliceInput($event.value)\"\n (keydown.enter)=\"reloadAndPlot.emit()\"\n />\n <p-button\n icon=\"pi pi-refresh\"\n size=\"small\"\n [text]=\"true\"\n ariaLabel=\"Plot this slice\"\n (onClick)=\"reloadAndPlot.emit()\"\n pTooltip=\"Plot this slice\"\n tooltipPosition=\"bottom\"\n >\n </p-button>\n </div>\n <span class=\"flex align-items-center mx-1 toolbar-text\">of {{ maxIndex }}</span>\n </ng-container>\n</ng-container>\n", styles: [".toolbar-text{color:var(--primary-color);font-size:.875rem}.toolbar-separator{border-left:1px solid var(--surface-border);height:1.5rem;margin:0 .25rem;align-self:center}.toolbar-icon-dark{filter:brightness(0) invert(47%) sepia(98%) saturate(567%) hue-rotate(181deg) brightness(103%) contrast(98%)}.toolbar-icon-active{filter:brightness(0) invert(1)}.wand-sensitivity-value{min-width:2rem;text-align:right}:host{display:contents}\n"] }]
97
+ args: [{ selector: 'toolbar-stack-controls', standalone: true, imports: [CommonModule, FormsModule, ButtonModule, SliderModule, TooltipModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"toolbar-separator\"></span>\n<!-- Heatmap view: single-image (high-def zoom) vs stack (frame slider). Plotly-only \u2014\n hidden for napari, which has no single/stack toggle or per-frame fetch, and for the\n spatial-omics modes: a 3D omics dataset publishes its reference volume as a z-stack\n image, and these modes draw observations, not one of its slices. -->\n<ng-container *ngIf=\"stackToggle\">\n <p-button\n icon=\"pi pi-image\"\n size=\"small\"\n ariaLabel=\"Single image mode\"\n [text]=\"showStack\"\n pTooltip=\"Single image mode: enables high-def zoom\"\n tooltipPosition=\"bottom\"\n (onClick)=\"selectStackOption.emit(stackOptions[0])\"\n >\n </p-button>\n <p-button\n icon=\"pi pi-images\"\n size=\"small\"\n ariaLabel=\"Stack mode\"\n [text]=\"!showStack\"\n pTooltip=\"Stack mode, enables slicing through image frames\"\n tooltipPosition=\"bottom\"\n (onClick)=\"selectStackOption.emit(stackOptions[1])\"\n >\n </p-button>\n</ng-container>\n<!-- The slice bar. Live views swap the slice in place as it moves; the heatmap's single image\n is re-plotted at the slice the bar settles on (a drag let go, or a pause in key steps). -->\n<ng-container *ngIf=\"liveScrubber || singleImage\">\n <span class=\"flex align-items-center mx-1 toolbar-text\">Slice</span>\n <p-slider\n [ngModel]=\"zIndex\"\n [min]=\"0\"\n [max]=\"maxIndex\"\n ariaLabel=\"Slice\"\n (pointerdown)=\"dragging = true\"\n (onChange)=\"onSliceChange($event.value)\"\n (onSlideEnd)=\"onSliceEnd($event.value)\"\n [pTooltip]=\"liveScrubber ? 'Slice through the stack (\u2190 / \u2192 keys)' : 'Slice to plot (\u2190 / \u2192 keys)'\"\n tooltipPosition=\"bottom\"\n [style]=\"{ width: '16rem' }\"\n styleClass=\"wand-sensitivity-slider\"\n ></p-slider>\n <span class=\"flex align-items-center mx-1 toolbar-text\">{{ zIndex }} of {{ maxIndex }}</span>\n</ng-container>\n", styles: [".toolbar-text{color:var(--primary-color);font-size:.875rem}.toolbar-separator{border-left:1px solid var(--surface-border);height:1.5rem;margin:0 .25rem;align-self:center}.toolbar-icon-dark{filter:brightness(0) invert(47%) sepia(98%) saturate(567%) hue-rotate(181deg) brightness(103%) contrast(98%)}.toolbar-icon-active{filter:brightness(0) invert(1)}.wand-sensitivity-value{min-width:2rem;text-align:right}:host{display:contents}\n"] }]
58
98
  }], propDecorators: { liveScrubber: [{
59
99
  type: Input
60
100
  }], stackToggle: [{
@@ -78,4 +118,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
78
118
  }], reloadAndPlot: [{
79
119
  type: Output
80
120
  }] } });
81
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stY29udHJvbHMuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi90b29sYmFyL3N0YWNrLWNvbnRyb2xzL3N0YWNrLWNvbnRyb2xzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci9zdGFjay1jb250cm9scy9zdGFjay1jb250cm9scy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hHLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7Ozs7Ozs7O0FBUWhEOzs7O0dBSUc7QUFTSCxNQUFNLE9BQU8sc0JBQXNCO0lBUm5DO1FBU0Usb0NBQW9DO1FBQzNCLGlCQUFZLEdBQUcsS0FBSyxDQUFDO1FBQzlCLDZEQUE2RDtRQUNwRCxnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUM3Qiw2Q0FBNkM7UUFDcEMsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUMzQixnREFBZ0Q7UUFDdkMsaUJBQVksR0FBa0I7WUFDckMsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUU7WUFDdEMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUU7U0FDL0IsQ0FBQztRQUNGLG1DQUFtQztRQUMxQixXQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLDRCQUE0QjtRQUNuQixhQUFRLEdBQUcsQ0FBQyxDQUFDO1FBRXRCLHNEQUFzRDtRQUM1QyxXQUFNLEdBQUcsSUFBSSxZQUFZLEVBQXNCLENBQUM7UUFDMUQsaURBQWlEO1FBQ3ZDLFdBQU0sR0FBRyxJQUFJLFlBQVksRUFBc0IsQ0FBQztRQUMxRCxzQ0FBc0M7UUFDNUIsc0JBQWlCLEdBQUcsSUFBSSxZQUFZLEVBQWUsQ0FBQztRQUM5RCxrRUFBa0U7UUFDeEQsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBQ25ELGdGQUFnRjtRQUN0RSxrQkFBYSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7S0FNcEQ7SUFKQyw4RUFBOEU7SUFDcEUsWUFBWSxDQUFDLEtBQTZCO1FBQ2xELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLElBQUksS0FBSyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDckYsQ0FBQzs4R0EvQlUsc0JBQXNCO2tHQUF0QixzQkFBc0IsMllDM0JuQyx5bEZBc0VBLHdlRGhEWSxZQUFZLGtJQUFFLFdBQVcsOFZBQUUsWUFBWSw2WEFBRSxpQkFBaUIseXZCQUFFLFlBQVksK1JBQUUsYUFBYTs7MkZBS3RGLHNCQUFzQjtrQkFSbEMsU0FBUzsrQkFDRSx3QkFBd0IsY0FDdEIsSUFBSSxXQUNQLENBQUMsWUFBWSxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsWUFBWSxFQUFFLGFBQWEsQ0FBQyxtQkFHakYsdUJBQXVCLENBQUMsTUFBTTs4QkFJdEMsWUFBWTtzQkFBcEIsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBRUcsWUFBWTtzQkFBcEIsS0FBSztnQkFLRyxNQUFNO3NCQUFkLEtBQUs7Z0JBRUcsUUFBUTtzQkFBaEIsS0FBSztnQkFHSSxNQUFNO3NCQUFmLE1BQU07Z0JBRUcsTUFBTTtzQkFBZixNQUFNO2dCQUVHLGlCQUFpQjtzQkFBMUIsTUFBTTtnQkFFRyxXQUFXO3NCQUFwQixNQUFNO2dCQUVHLGFBQWE7c0JBQXRCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIElucHV0LCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEJ1dHRvbk1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvYnV0dG9uJztcbmltcG9ydCB7IElucHV0TnVtYmVyTW9kdWxlIH0gZnJvbSAncHJpbWVuZy9pbnB1dG51bWJlcic7XG5pbXBvcnQgeyBTbGlkZXJNb2R1bGUgfSBmcm9tICdwcmltZW5nL3NsaWRlcic7XG5pbXBvcnQgeyBUb29sdGlwTW9kdWxlIH0gZnJvbSAncHJpbWVuZy90b29sdGlwJztcblxuLyoqIEEgc3RhY2stbW9kZSBjaG9pY2UgKGB2YWxgICdmYWxzZScgPSBzaW5nbGUgaW1hZ2UsICd0cnVlJyA9IHN0YWNrKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RhY2tPcHRpb24ge1xuICBuYW1lOiBzdHJpbmc7XG4gIHZhbDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSB0b29sYmFyJ3Mgei1zdGFjayBncm91cDogYSBsaXZlIHNsaWNlIHNjcnViYmVyIGZvciB0aGUgdmlld3MgdGhhdCBzd2FwXG4gKiBzbGljZXMgaW4gcGxhY2UsIG9yIChQbG90bHkgaGVhdG1hcCkgdGhlIHNpbmdsZS1pbWFnZSAvIHN0YWNrIHRvZ2dsZSB3aXRoIGFcbiAqIHNsaWNlLW51bWJlciBmaWVsZC4gUHJlc2VudGF0aW9uYWw6IHRoZSBob3N0IG93bnMgYHpJbmRleGAuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3Rvb2xiYXItc3RhY2stY29udHJvbHMnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBGb3Jtc01vZHVsZSwgQnV0dG9uTW9kdWxlLCBJbnB1dE51bWJlck1vZHVsZSwgU2xpZGVyTW9kdWxlLCBUb29sdGlwTW9kdWxlXSxcbiAgdGVtcGxhdGVVcmw6ICcuL3N0YWNrLWNvbnRyb2xzLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vc3RhY2stY29udHJvbHMuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFN0YWNrQ29udHJvbHNDb21wb25lbnQge1xuICAvKiogU2hvdyB0aGUgbGl2ZSBzbGljZSBzY3J1YmJlci4gKi9cbiAgQElucHV0KCkgbGl2ZVNjcnViYmVyID0gZmFsc2U7XG4gIC8qKiBTaG93IHRoZSBzaW5nbGUtaW1hZ2UgLyBzdGFjayB0b2dnbGUgKFBsb3RseSBoZWF0bWFwKS4gKi9cbiAgQElucHV0KCkgc3RhY2tUb2dnbGUgPSBmYWxzZTtcbiAgLyoqIFN0YWNrIG1vZGUgaXMgb24gKHRoZSB0b2dnbGUncyBzdGF0ZSkuICovXG4gIEBJbnB1dCgpIHNob3dTdGFjayA9IGZhbHNlO1xuICAvKiogVGhlIHR3byBzdGFjay1tb2RlIGNob2ljZXMgb2YgdGhlIHRvZ2dsZS4gKi9cbiAgQElucHV0KCkgc3RhY2tPcHRpb25zOiBTdGFja09wdGlvbltdID0gW1xuICAgIHsgbmFtZTogJ1NpbmdsZSBpbWFnZScsIHZhbDogJ2ZhbHNlJyB9LFxuICAgIHsgbmFtZTogJ1N0YWNrJywgdmFsOiAndHJ1ZScgfSxcbiAgXTtcbiAgLyoqIFRoZSBjdXJyZW50IHNsaWNlICgwLWJhc2VkKS4gKi9cbiAgQElucHV0KCkgekluZGV4ID0gMDtcbiAgLyoqIFRoZSBsYXN0IHNsaWNlIGluZGV4LiAqL1xuICBASW5wdXQoKSBtYXhJbmRleCA9IDA7XG5cbiAgLyoqIFRoZSBsaXZlIHNjcnViYmVyIG1vdmVkIChmaXJlcyB3aGlsZSBkcmFnZ2luZykuICovXG4gIEBPdXRwdXQoKSB6U2NydWIgPSBuZXcgRXZlbnRFbWl0dGVyPG51bWJlciB8IHVuZGVmaW5lZD4oKTtcbiAgLyoqIFRoZSBsaXZlIHNjcnViYmVyIHdhcyByZWxlYXNlZCBvbiBhIHNsaWNlLiAqL1xuICBAT3V0cHV0KCkgelNsaWRlID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXIgfCB1bmRlZmluZWQ+KCk7XG4gIC8qKiBBIHN0YWNrLW1vZGUgY2hvaWNlIHdhcyBwaWNrZWQuICovXG4gIEBPdXRwdXQoKSBzZWxlY3RTdGFja09wdGlvbiA9IG5ldyBFdmVudEVtaXR0ZXI8U3RhY2tPcHRpb24+KCk7XG4gIC8qKiBBIHNsaWNlIG51bWJlciB3YXMgdHlwZWQgKGJsYW5rIHJlcG9ydHMgdGhlIGN1cnJlbnQgc2xpY2UpLiAqL1xuICBAT3V0cHV0KCkgekluZGV4SW5wdXQgPSBuZXcgRXZlbnRFbWl0dGVyPG51bWJlcj4oKTtcbiAgLyoqIEVudGVyIGluIHRoZSBzbGljZSBmaWVsZCAvIHRoZSByZWxvYWQgYnV0dG9uOiByZS1wbG90IGF0IHRoZSB0eXBlZCBzbGljZS4gKi9cbiAgQE91dHB1dCgpIHJlbG9hZEFuZFBsb3QgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgLyoqIFRoZSBzbGljZSBmaWVsZCByZXBvcnRzIHdoYXQgd2FzIHR5cGVkIChibGFuayBrZWVwcyB0aGUgY3VycmVudCBzbGljZSkuICovXG4gIHByb3RlY3RlZCBvblNsaWNlSW5wdXQodmFsdWU6IHN0cmluZyB8IG51bWJlciB8IG51bGwpOiB2b2lkIHtcbiAgICB0aGlzLnpJbmRleElucHV0LmVtaXQodmFsdWUgPT0gbnVsbCB8fCB2YWx1ZSA9PT0gJycgPyB0aGlzLnpJbmRleCA6IE51bWJlcih2YWx1ZSkpO1xuICB9XG59XG4iLCI8c3BhbiBjbGFzcz1cInRvb2xiYXItc2VwYXJhdG9yXCI+PC9zcGFuPlxuPCEtLSBMaXZlIHZpZXdzOiBzY3J1YiB6LXNsaWNlcyAodGhlIHJlbmRlcmVyIHN3YXBzIHNsaWNlcyBpbiBwbGFjZSkuIC0tPlxuPG5nLWNvbnRhaW5lciAqbmdJZj1cImxpdmVTY3J1YmJlclwiPlxuICA8c3BhbiBjbGFzcz1cImZsZXggYWxpZ24taXRlbXMtY2VudGVyIG14LTEgdG9vbGJhci10ZXh0XCI+U2xpY2U8L3NwYW4+XG4gIDxwLXNsaWRlclxuICAgIFtuZ01vZGVsXT1cInpJbmRleFwiXG4gICAgW21pbl09XCIwXCJcbiAgICBbbWF4XT1cIm1heEluZGV4XCJcbiAgICBhcmlhTGFiZWw9XCJTbGljZVwiXG4gICAgKG9uQ2hhbmdlKT1cInpTY3J1Yi5lbWl0KCRldmVudC52YWx1ZSlcIlxuICAgIChvblNsaWRlRW5kKT1cInpTbGlkZS5lbWl0KCRldmVudC52YWx1ZSlcIlxuICAgIHBUb29sdGlwPVwiU2xpY2UgdGhyb3VnaCB0aGUgc3RhY2sgKOKGkCAvIOKGkiBrZXlzKVwiXG4gICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICBbc3R5bGVdPVwieyB3aWR0aDogJzE2cmVtJyB9XCJcbiAgICBzdHlsZUNsYXNzPVwid2FuZC1zZW5zaXRpdml0eS1zbGlkZXJcIlxuICA+PC9wLXNsaWRlcj5cbiAgPHNwYW4gY2xhc3M9XCJmbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBteC0xIHRvb2xiYXItdGV4dFwiPnt7IHpJbmRleCB9fSBvZiB7eyBtYXhJbmRleCB9fTwvc3Bhbj5cbjwvbmctY29udGFpbmVyPlxuPCEtLSBIZWF0bWFwIHZpZXc6IHNpbmdsZS1pbWFnZSAoaGlnaC1kZWYgem9vbSkgdnMgc3RhY2sgKGZyYW1lIHNsaWRlcikuIFBsb3RseS1vbmx5IOKAlFxuICAgICBoaWRkZW4gZm9yIG5hcGFyaSwgd2hpY2ggaGFzIG5vIHNpbmdsZS9zdGFjayB0b2dnbGUgb3IgcGVyLWZyYW1lIGZldGNoLCBhbmQgZm9yIHRoZVxuICAgICBzcGF0aWFsLW9taWNzIG1vZGVzOiBhIDNEIG9taWNzIGRhdGFzZXQgcHVibGlzaGVzIGl0cyByZWZlcmVuY2Ugdm9sdW1lIGFzIGEgei1zdGFja1xuICAgICBpbWFnZSwgYW5kIHRoZXNlIG1vZGVzIGRyYXcgb2JzZXJ2YXRpb25zLCBub3Qgb25lIG9mIGl0cyBzbGljZXMuIC0tPlxuPG5nLWNvbnRhaW5lciAqbmdJZj1cInN0YWNrVG9nZ2xlXCI+XG4gIDxwLWJ1dHRvblxuICAgIGljb249XCJwaSBwaS1pbWFnZVwiXG4gICAgc2l6ZT1cInNtYWxsXCJcbiAgICBhcmlhTGFiZWw9XCJTaW5nbGUgaW1hZ2UgbW9kZVwiXG4gICAgW3RleHRdPVwic2hvd1N0YWNrXCJcbiAgICBwVG9vbHRpcD1cIlNpbmdsZSBpbWFnZSBtb2RlOiBlbmFibGVzIGhpZ2gtZGVmIHpvb21cIlxuICAgIHRvb2x0aXBQb3NpdGlvbj1cImJvdHRvbVwiXG4gICAgKG9uQ2xpY2spPVwic2VsZWN0U3RhY2tPcHRpb24uZW1pdChzdGFja09wdGlvbnNbMF0pXCJcbiAgPlxuICA8L3AtYnV0dG9uPlxuICA8cC1idXR0b25cbiAgICBpY29uPVwicGkgcGktaW1hZ2VzXCJcbiAgICBzaXplPVwic21hbGxcIlxuICAgIGFyaWFMYWJlbD1cIlN0YWNrIG1vZGVcIlxuICAgIFt0ZXh0XT1cIiFzaG93U3RhY2tcIlxuICAgIHBUb29sdGlwPVwiU3RhY2sgbW9kZSwgZW5hYmxlcyBzbGljaW5nIHRocm91Z2ggaW1hZ2UgZnJhbWVzXCJcbiAgICB0b29sdGlwUG9zaXRpb249XCJib3R0b21cIlxuICAgIChvbkNsaWNrKT1cInNlbGVjdFN0YWNrT3B0aW9uLmVtaXQoc3RhY2tPcHRpb25zWzFdKVwiXG4gID5cbiAgPC9wLWJ1dHRvbj5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFzaG93U3RhY2tcIj5cbiAgICA8c3BhbiBjbGFzcz1cImZsZXggYWxpZ24taXRlbXMtY2VudGVyIG14LTEgdG9vbGJhci10ZXh0XCI+U2xpY2U8L3NwYW4+XG4gICAgPGRpdiBjbGFzcz1cInAtaW5wdXRncm91cFwiIHN0eWxlPVwid2lkdGg6IGF1dG9cIj5cbiAgICAgIDxwLWlucHV0TnVtYmVyXG4gICAgICAgIHN0eWxlQ2xhc3M9XCJ3LTNyZW0gdG9vbGJhci1pbnB1dFwiXG4gICAgICAgIGFyaWFMYWJlbD1cIlNsaWNlIG51bWJlclwiXG4gICAgICAgIHBUb29sdGlwPVwiVmlldyBpbWFnZSBpbiBzdGFjayAoJiN4MjNDRTspXCJcbiAgICAgICAgW25nTW9kZWxdPVwiekluZGV4XCJcbiAgICAgICAgW21pbl09XCIwXCJcbiAgICAgICAgW21heF09XCJtYXhJbmRleFwiXG4gICAgICAgIChvbklucHV0KT1cIm9uU2xpY2VJbnB1dCgkZXZlbnQudmFsdWUpXCJcbiAgICAgICAgKGtleWRvd24uZW50ZXIpPVwicmVsb2FkQW5kUGxvdC5lbWl0KClcIlxuICAgICAgLz5cbiAgICAgIDxwLWJ1dHRvblxuICAgICAgICBpY29uPVwicGkgcGktcmVmcmVzaFwiXG4gICAgICAgIHNpemU9XCJzbWFsbFwiXG4gICAgICAgIFt0ZXh0XT1cInRydWVcIlxuICAgICAgICBhcmlhTGFiZWw9XCJQbG90IHRoaXMgc2xpY2VcIlxuICAgICAgICAob25DbGljayk9XCJyZWxvYWRBbmRQbG90LmVtaXQoKVwiXG4gICAgICAgIHBUb29sdGlwPVwiUGxvdCB0aGlzIHNsaWNlXCJcbiAgICAgICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICAgID5cbiAgICAgIDwvcC1idXR0b24+XG4gICAgPC9kaXY+XG4gICAgPHNwYW4gY2xhc3M9XCJmbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBteC0xIHRvb2xiYXItdGV4dFwiPm9mIHt7IG1heEluZGV4IH19PC9zcGFuPlxuICA8L25nLWNvbnRhaW5lcj5cbjwvbmctY29udGFpbmVyPlxuIl19
121
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stY29udHJvbHMuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi90b29sYmFyL3N0YWNrLWNvbnRyb2xzL3N0YWNrLWNvbnRyb2xzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci9zdGFjay1jb250cm9scy9zdGFjay1jb250cm9scy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQWEsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNHLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7Ozs7Ozs7QUFRaEQ7Ozs7R0FJRztBQVNILE1BQU0sT0FBTyxzQkFBc0I7SUFSbkM7UUFTRSxvQ0FBb0M7UUFDM0IsaUJBQVksR0FBRyxLQUFLLENBQUM7UUFDOUIsNkRBQTZEO1FBQ3BELGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBQzdCLDZDQUE2QztRQUNwQyxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBQzNCLGdEQUFnRDtRQUN2QyxpQkFBWSxHQUFrQjtZQUNyQyxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRTtZQUN0QyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRTtTQUMvQixDQUFDO1FBQ0YsbUNBQW1DO1FBQzFCLFdBQU0sR0FBRyxDQUFDLENBQUM7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O2dCQUVHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBS0csTUFBTTtzQkFBZCxLQUFLO2dCQUVHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBR0ksTUFBTTtzQkFBZixNQUFNO2dCQUVHLE1BQU07c0JBQWYsTUFBTTtnQkFFRyxpQkFBaUI7c0JBQTFCLE1BQU07Z0JBRUcsV0FBVztzQkFBcEIsTUFBTTtnQkFFRyxhQUFhO3NCQUF0QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25EZXN0cm95LCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEJ1dHRvbk1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvYnV0dG9uJztcbmltcG9ydCB7IFNsaWRlck1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvc2xpZGVyJztcbmltcG9ydCB7IFRvb2x0aXBNb2R1bGUgfSBmcm9tICdwcmltZW5nL3Rvb2x0aXAnO1xuXG4vKiogQSBzdGFjay1tb2RlIGNob2ljZSAoYHZhbGAgJ2ZhbHNlJyA9IHNpbmdsZSBpbWFnZSwgJ3RydWUnID0gc3RhY2spLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdGFja09wdGlvbiB7XG4gIG5hbWU6IHN0cmluZztcbiAgdmFsOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIHRvb2xiYXIncyB6LXN0YWNrIGdyb3VwOiB0aGUgc2xpY2UgYmFyLCBhbmQgKFBsb3RseSBoZWF0bWFwKSB0aGUgc2luZ2xlLWltYWdlIC8gc3RhY2tcbiAqIHRvZ2dsZS4gVGhlIHZpZXdzIHRoYXQgc3dhcCBzbGljZXMgaW4gcGxhY2UgZm9sbG93IHRoZSBiYXIgYXMgaXQgbW92ZXM7IHRoZSBoZWF0bWFwJ3Mgc2luZ2xlXG4gKiBpbWFnZSBpcyByZS1wbG90dGVkIGF0IHRoZSBzbGljZSBpdCBzZXR0bGVzIG9uLiBQcmVzZW50YXRpb25hbDogdGhlIGhvc3Qgb3ducyBgekluZGV4YC5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9vbGJhci1zdGFjay1jb250cm9scycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIEZvcm1zTW9kdWxlLCBCdXR0b25Nb2R1bGUsIFNsaWRlck1vZHVsZSwgVG9vbHRpcE1vZHVsZV0sXG4gIHRlbXBsYXRlVXJsOiAnLi9zdGFjay1jb250cm9scy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3N0YWNrLWNvbnRyb2xzLmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBTdGFja0NvbnRyb2xzQ29tcG9uZW50IGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgLyoqIFNob3cgdGhlIGxpdmUgc2xpY2Ugc2NydWJiZXIuICovXG4gIEBJbnB1dCgpIGxpdmVTY3J1YmJlciA9IGZhbHNlO1xuICAvKiogU2hvdyB0aGUgc2luZ2xlLWltYWdlIC8gc3RhY2sgdG9nZ2xlIChQbG90bHkgaGVhdG1hcCkuICovXG4gIEBJbnB1dCgpIHN0YWNrVG9nZ2xlID0gZmFsc2U7XG4gIC8qKiBTdGFjayBtb2RlIGlzIG9uICh0aGUgdG9nZ2xlJ3Mgc3RhdGUpLiAqL1xuICBASW5wdXQoKSBzaG93U3RhY2sgPSBmYWxzZTtcbiAgLyoqIFRoZSB0d28gc3RhY2stbW9kZSBjaG9pY2VzIG9mIHRoZSB0b2dnbGUuICovXG4gIEBJbnB1dCgpIHN0YWNrT3B0aW9uczogU3RhY2tPcHRpb25bXSA9IFtcbiAgICB7IG5hbWU6ICdTaW5nbGUgaW1hZ2UnLCB2YWw6ICdmYWxzZScgfSxcbiAgICB7IG5hbWU6ICdTdGFjaycsIHZhbDogJ3RydWUnIH0sXG4gIF07XG4gIC8qKiBUaGUgY3VycmVudCBzbGljZSAoMC1iYXNlZCkuICovXG4gIEBJbnB1dCgpIHpJbmRleCA9IDA7XG4gIC8qKiBUaGUgbGFzdCBzbGljZSBpbmRleC4gKi9cbiAgQElucHV0KCkgbWF4SW5kZXggPSAwO1xuXG4gIC8qKiBUaGUgbGl2ZSBzY3J1YmJlciBtb3ZlZCAoZmlyZXMgd2hpbGUgZHJhZ2dpbmcpLiAqL1xuICBAT3V0cHV0KCkgelNjcnViID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXIgfCB1bmRlZmluZWQ+KCk7XG4gIC8qKiBUaGUgbGl2ZSBzY3J1YmJlciB3YXMgcmVsZWFzZWQgb24gYSBzbGljZS4gKi9cbiAgQE91dHB1dCgpIHpTbGlkZSA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyIHwgdW5kZWZpbmVkPigpO1xuICAvKiogQSBzdGFjay1tb2RlIGNob2ljZSB3YXMgcGlja2VkLiAqL1xuICBAT3V0cHV0KCkgc2VsZWN0U3RhY2tPcHRpb24gPSBuZXcgRXZlbnRFbWl0dGVyPFN0YWNrT3B0aW9uPigpO1xuICAvKiogVGhlIGhlYXRtYXAncyBzbGljZSBiYXIgbW92ZWQgdG8gYSBzbGljZSAodGhlIGhvc3Qgc2hvd3MgaXRzIG51bWJlcikuICovXG4gIEBPdXRwdXQoKSB6SW5kZXhJbnB1dCA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xuICAvKiogVGhlIGhlYXRtYXAncyBzbGljZSBiYXIgc2V0dGxlZDogcmUtcGxvdCBhdCB0aGF0IHNsaWNlLiAqL1xuICBAT3V0cHV0KCkgcmVsb2FkQW5kUGxvdCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAvKiogSG93IGxvbmcga2V5IHN0ZXBzIG9uIHRoZSBoZWF0bWFwJ3MgYmFyIHBhdXNlIGJlZm9yZSB0aGUgc2xpY2UgaXMgcmUtcGxvdHRlZC4gKi9cbiAgc3RhdGljIHJlYWRvbmx5IFJFUExPVF9ERUxBWV9NUyA9IDQwMDtcblxuICAvKiogQSBkcmFnIG9mIHRoZSBiYXIgaXMgdW5kZXIgd2F5IChpdHMgZW5kIHJlLXBsb3RzIHRoZSBoZWF0bWFwLCBub3QgZWFjaCBzdGVwKS4gKi9cbiAgcHJvdGVjdGVkIGRyYWdnaW5nID0gZmFsc2U7XG4gIHByaXZhdGUgcmVwbG90OiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBUaGUgaGVhdG1hcCBpbiBzaW5nbGUtaW1hZ2UgbW9kZTogaXRzIGJhciByZS1wbG90cyB0aGUgc2xpY2UgaXQgc2V0dGxlcyBvbi4gKi9cbiAgcHJvdGVjdGVkIGdldCBzaW5nbGVJbWFnZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zdGFja1RvZ2dsZSAmJiAhdGhpcy5zaG93U3RhY2s7XG4gIH1cblxuICAvKiogVGhlIGJhciBtb3ZlZDogYSBsaXZlIHZpZXcgZm9sbG93cyBpdDsgdGhlIGhlYXRtYXAgc2hvd3MgdGhlIG51bWJlciwgYW5kIHJlLXBsb3RzIGFmdGVyIGtleSBzdGVwcyBwYXVzZS4gKi9cbiAgcHJvdGVjdGVkIG9uU2xpY2VDaGFuZ2UoejogbnVtYmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgaWYgKHogPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICAgIGlmICh0aGlzLmxpdmVTY3J1YmJlcikge1xuICAgICAgdGhpcy56U2NydWIuZW1pdCh6KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy56SW5kZXhJbnB1dC5lbWl0KHopO1xuICAgIGlmICh0aGlzLmRyYWdnaW5nKSByZXR1cm47XG4gICAgdGhpcy5jYW5jZWxSZXBsb3QoKTtcbiAgICB0aGlzLnJlcGxvdCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5yZXBsb3QgPSBudWxsO1xuICAgICAgdGhpcy5yZWxvYWRBbmRQbG90LmVtaXQoKTtcbiAgICB9LCBTdGFja0NvbnRyb2xzQ29tcG9uZW50LlJFUExPVF9ERUxBWV9NUyk7XG4gIH1cblxuICAvKiogVGhlIGJhciB3YXMgbGV0IGdvIChhIGRyYWcncyBlbmQsIG9yIGEgY2xpY2sgb24gaXRzIHRyYWNrKS4gKi9cbiAgcHJvdGVjdGVkIG9uU2xpY2VFbmQoejogbnVtYmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgdGhpcy5kcmFnZ2luZyA9IGZhbHNlO1xuICAgIGlmICh0aGlzLmxpdmVTY3J1YmJlcikge1xuICAgICAgdGhpcy56U2xpZGUuZW1pdCh6KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHogIT09IHVuZGVmaW5lZCkgdGhpcy56SW5kZXhJbnB1dC5lbWl0KHopO1xuICAgIHRoaXMuY2FuY2VsUmVwbG90KCk7XG4gICAgdGhpcy5yZWxvYWRBbmRQbG90LmVtaXQoKTtcbiAgfVxuXG4gIHByaXZhdGUgY2FuY2VsUmVwbG90KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnJlcGxvdCAhPT0gbnVsbCkgY2xlYXJUaW1lb3V0KHRoaXMucmVwbG90KTtcbiAgICB0aGlzLnJlcGxvdCA9IG51bGw7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmNhbmNlbFJlcGxvdCgpO1xuICB9XG59XG4iLCI8c3BhbiBjbGFzcz1cInRvb2xiYXItc2VwYXJhdG9yXCI+PC9zcGFuPlxuPCEtLSBIZWF0bWFwIHZpZXc6IHNpbmdsZS1pbWFnZSAoaGlnaC1kZWYgem9vbSkgdnMgc3RhY2sgKGZyYW1lIHNsaWRlcikuIFBsb3RseS1vbmx5IOKAlFxuICAgICBoaWRkZW4gZm9yIG5hcGFyaSwgd2hpY2ggaGFzIG5vIHNpbmdsZS9zdGFjayB0b2dnbGUgb3IgcGVyLWZyYW1lIGZldGNoLCBhbmQgZm9yIHRoZVxuICAgICBzcGF0aWFsLW9taWNzIG1vZGVzOiBhIDNEIG9taWNzIGRhdGFzZXQgcHVibGlzaGVzIGl0cyByZWZlcmVuY2Ugdm9sdW1lIGFzIGEgei1zdGFja1xuICAgICBpbWFnZSwgYW5kIHRoZXNlIG1vZGVzIGRyYXcgb2JzZXJ2YXRpb25zLCBub3Qgb25lIG9mIGl0cyBzbGljZXMuIC0tPlxuPG5nLWNvbnRhaW5lciAqbmdJZj1cInN0YWNrVG9nZ2xlXCI+XG4gIDxwLWJ1dHRvblxuICAgIGljb249XCJwaSBwaS1pbWFnZVwiXG4gICAgc2l6ZT1cInNtYWxsXCJcbiAgICBhcmlhTGFiZWw9XCJTaW5nbGUgaW1hZ2UgbW9kZVwiXG4gICAgW3RleHRdPVwic2hvd1N0YWNrXCJcbiAgICBwVG9vbHRpcD1cIlNpbmdsZSBpbWFnZSBtb2RlOiBlbmFibGVzIGhpZ2gtZGVmIHpvb21cIlxuICAgIHRvb2x0aXBQb3NpdGlvbj1cImJvdHRvbVwiXG4gICAgKG9uQ2xpY2spPVwic2VsZWN0U3RhY2tPcHRpb24uZW1pdChzdGFja09wdGlvbnNbMF0pXCJcbiAgPlxuICA8L3AtYnV0dG9uPlxuICA8cC1idXR0b25cbiAgICBpY29uPVwicGkgcGktaW1hZ2VzXCJcbiAgICBzaXplPVwic21hbGxcIlxuICAgIGFyaWFMYWJlbD1cIlN0YWNrIG1vZGVcIlxuICAgIFt0ZXh0XT1cIiFzaG93U3RhY2tcIlxuICAgIHBUb29sdGlwPVwiU3RhY2sgbW9kZSwgZW5hYmxlcyBzbGljaW5nIHRocm91Z2ggaW1hZ2UgZnJhbWVzXCJcbiAgICB0b29sdGlwUG9zaXRpb249XCJib3R0b21cIlxuICAgIChvbkNsaWNrKT1cInNlbGVjdFN0YWNrT3B0aW9uLmVtaXQoc3RhY2tPcHRpb25zWzFdKVwiXG4gID5cbiAgPC9wLWJ1dHRvbj5cbjwvbmctY29udGFpbmVyPlxuPCEtLSBUaGUgc2xpY2UgYmFyLiBMaXZlIHZpZXdzIHN3YXAgdGhlIHNsaWNlIGluIHBsYWNlIGFzIGl0IG1vdmVzOyB0aGUgaGVhdG1hcCdzIHNpbmdsZSBpbWFnZVxuICAgICBpcyByZS1wbG90dGVkIGF0IHRoZSBzbGljZSB0aGUgYmFyIHNldHRsZXMgb24gKGEgZHJhZyBsZXQgZ28sIG9yIGEgcGF1c2UgaW4ga2V5IHN0ZXBzKS4gLS0+XG48bmctY29udGFpbmVyICpuZ0lmPVwibGl2ZVNjcnViYmVyIHx8IHNpbmdsZUltYWdlXCI+XG4gIDxzcGFuIGNsYXNzPVwiZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgbXgtMSB0b29sYmFyLXRleHRcIj5TbGljZTwvc3Bhbj5cbiAgPHAtc2xpZGVyXG4gICAgW25nTW9kZWxdPVwiekluZGV4XCJcbiAgICBbbWluXT1cIjBcIlxuICAgIFttYXhdPVwibWF4SW5kZXhcIlxuICAgIGFyaWFMYWJlbD1cIlNsaWNlXCJcbiAgICAocG9pbnRlcmRvd24pPVwiZHJhZ2dpbmcgPSB0cnVlXCJcbiAgICAob25DaGFuZ2UpPVwib25TbGljZUNoYW5nZSgkZXZlbnQudmFsdWUpXCJcbiAgICAob25TbGlkZUVuZCk9XCJvblNsaWNlRW5kKCRldmVudC52YWx1ZSlcIlxuICAgIFtwVG9vbHRpcF09XCJsaXZlU2NydWJiZXIgPyAnU2xpY2UgdGhyb3VnaCB0aGUgc3RhY2sgKOKGkCAvIOKGkiBrZXlzKScgOiAnU2xpY2UgdG8gcGxvdCAo4oaQIC8g4oaSIGtleXMpJ1wiXG4gICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICBbc3R5bGVdPVwieyB3aWR0aDogJzE2cmVtJyB9XCJcbiAgICBzdHlsZUNsYXNzPVwid2FuZC1zZW5zaXRpdml0eS1zbGlkZXJcIlxuICA+PC9wLXNsaWRlcj5cbiAgPHNwYW4gY2xhc3M9XCJmbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBteC0xIHRvb2xiYXItdGV4dFwiPnt7IHpJbmRleCB9fSBvZiB7eyBtYXhJbmRleCB9fTwvc3Bhbj5cbjwvbmctY29udGFpbmVyPlxuIl19