@jax-data-science/sci-image-visualizer 0.8.3 → 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 (579) hide show
  1. package/README.md +201 -460
  2. package/esm2022/index.mjs +34 -15
  3. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
  4. package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
  5. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
  7. package/esm2022/lib/contracts/color.mjs +60 -0
  8. package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
  9. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
  10. package/esm2022/lib/contracts/display-types.mjs +11 -1
  11. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  12. package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
  13. package/esm2022/lib/contracts/intensity.mjs +48 -5
  14. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  15. package/esm2022/lib/contracts/plot-type.mjs +134 -17
  16. package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
  17. package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
  18. package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
  19. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
  20. package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
  21. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  22. package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
  23. package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
  24. package/esm2022/lib/contracts/sam.contract.mjs +1 -1
  25. package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
  26. package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
  27. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  28. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
  29. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  30. package/esm2022/lib/contracts/viz-config.mjs +2 -1
  31. package/esm2022/lib/geometry/contour.mjs +63 -0
  32. package/esm2022/lib/geometry/loft.mjs +128 -0
  33. package/esm2022/lib/geometry/polylabel.mjs +156 -0
  34. package/esm2022/lib/geometry/raster.mjs +98 -0
  35. package/esm2022/lib/geometry/reconstruct.mjs +315 -0
  36. package/esm2022/lib/geometry/reslice-image.mjs +57 -0
  37. package/esm2022/lib/geometry/ring.mjs +201 -0
  38. package/esm2022/lib/geometry/section.mjs +215 -0
  39. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
  40. package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
  41. package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
  42. package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
  43. package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
  44. package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
  45. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +12 -9
  46. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +83 -0
  47. package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
  48. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +180 -591
  49. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
  50. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
  51. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
  52. package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
  53. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +270 -0
  54. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
  55. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
  56. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
  57. package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
  58. package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
  59. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +347 -0
  60. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +427 -4207
  61. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
  62. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +550 -0
  63. package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
  64. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
  65. package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
  66. package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
  67. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +194 -0
  68. package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
  69. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
  70. package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
  71. package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
  72. package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
  73. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
  74. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
  75. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
  76. package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
  77. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
  78. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
  79. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
  80. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
  81. package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
  82. package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
  83. package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
  84. package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
  85. package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
  86. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +164 -0
  87. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +213 -716
  88. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
  89. package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
  90. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
  91. package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
  92. package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
  93. package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
  94. package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
  95. package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
  96. package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
  97. package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
  98. package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
  99. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
  100. package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
  101. package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
  102. package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
  103. package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
  104. package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
  105. package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
  106. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
  107. package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
  108. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
  109. package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
  110. package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
  111. package/esm2022/lib/implementations/region-centroids.mjs +47 -0
  112. package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
  113. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
  114. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
  115. package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
  116. package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
  117. package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
  118. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
  119. package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
  120. package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
  121. package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
  122. package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
  123. package/esm2022/lib/models/bezier.mjs +1 -11
  124. package/esm2022/lib/models/class-preset.mjs +41 -3
  125. package/esm2022/lib/models/geometry.mjs +27 -164
  126. package/esm2022/lib/models/polygon-edit.mjs +254 -0
  127. package/esm2022/lib/models/polygon-factory.mjs +134 -0
  128. package/esm2022/lib/models/region-clone.mjs +68 -0
  129. package/esm2022/lib/models/region-geojson.mjs +411 -0
  130. package/esm2022/lib/models/region.mjs +34 -33
  131. package/esm2022/lib/models/shape.mjs +18 -16
  132. package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
  133. package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
  134. package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
  135. package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
  136. package/esm2022/lib/plot.utilities.mjs +296 -473
  137. package/esm2022/lib/processing/image-crop.mjs +1 -1
  138. package/esm2022/lib/processing/processing-image.mjs +28 -15
  139. package/esm2022/lib/provide-visualization.mjs +40 -14
  140. package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
  141. package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
  142. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +163 -0
  143. package/esm2022/lib/region-editor/file-stem.mjs +13 -0
  144. package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
  145. package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
  146. package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
  147. package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
  148. package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
  149. package/esm2022/lib/region-editor/region-editor.component.mjs +896 -660
  150. package/esm2022/lib/region-editor/region-metrics.mjs +86 -0
  151. package/esm2022/lib/region-editor/region-persistence.service.mjs +160 -0
  152. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +169 -0
  153. package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
  154. package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
  155. package/esm2022/lib/region-ops.service.mjs +28 -70
  156. package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
  157. package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
  158. package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
  159. package/esm2022/lib/region-overlay/region-style.mjs +97 -0
  160. package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
  161. package/esm2022/lib/region-source/http-region-source.mjs +104 -0
  162. package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
  163. package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
  164. package/esm2022/lib/region-source/region-source.mjs +67 -0
  165. package/esm2022/lib/region-source/region-tiles.mjs +708 -0
  166. package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
  167. package/esm2022/lib/render-orchestrator.mjs +14 -11
  168. package/esm2022/lib/render-session.mjs +207 -0
  169. package/esm2022/lib/routing-visualizer.service.mjs +858 -414
  170. package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
  171. package/esm2022/lib/spatial/density-raster.mjs +14 -0
  172. package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
  173. package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
  174. package/esm2022/lib/spatial/gene-search.mjs +1 -1
  175. package/esm2022/lib/spatial/glyphs.mjs +97 -0
  176. package/esm2022/lib/spatial/lod.mjs +187 -0
  177. package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
  178. package/esm2022/lib/spatial/spatial-density.mjs +25 -16
  179. package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
  180. package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
  181. package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
  182. package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
  183. package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
  184. package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
  185. package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
  186. package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
  187. package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
  188. package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
  189. package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
  190. package/esm2022/lib/spatial/stats.mjs +71 -0
  191. package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
  192. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
  193. package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
  194. package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
  195. package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
  196. package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
  197. package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
  198. package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
  199. package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
  200. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
  201. package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
  202. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
  203. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
  204. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
  205. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
  206. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
  207. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
  208. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
  209. package/esm2022/lib/store/class-color.util.mjs +53 -5
  210. package/esm2022/lib/store/class-signatures.mjs +63 -0
  211. package/esm2022/lib/store/region-history.mjs +146 -0
  212. package/esm2022/lib/store/region-scope-cache.mjs +144 -0
  213. package/esm2022/lib/store/region-selection.mjs +82 -0
  214. package/esm2022/lib/store/region-source-scope.mjs +171 -0
  215. package/esm2022/lib/store/region-store.service.mjs +986 -670
  216. package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
  217. package/esm2022/lib/store/visualizer-store.service.mjs +81 -76
  218. package/esm2022/lib/toast-outlets.mjs +5 -4
  219. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
  220. package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
  221. package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
  222. package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
  223. package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
  224. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +120 -0
  225. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
  226. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
  227. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
  228. package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
  229. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
  230. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
  231. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
  232. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
  233. package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
  234. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
  235. package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
  236. package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
  237. package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
  238. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +121 -0
  239. package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
  240. package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
  241. package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
  242. package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
  243. package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
  244. package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
  245. package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
  246. package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
  247. package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
  248. package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
  249. package/esm2022/lib/toolbar/toolbar.component.mjs +84 -119
  250. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
  251. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
  252. package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
  253. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
  254. package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
  255. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
  256. package/esm2022/lib/util/mark-for-check.mjs +17 -0
  257. package/esm2022/lib/util/supersede.mjs +56 -0
  258. package/esm2022/lib/visualization.module.mjs +39 -141
  259. package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
  260. package/esm2022/lib/visualizer/region-actions.mjs +149 -0
  261. package/esm2022/lib/visualizer/region-load.mjs +123 -0
  262. package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
  263. package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
  264. package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
  265. package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
  266. package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
  267. package/esm2022/lib/visualizer.component.mjs +602 -1902
  268. package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
  269. package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
  270. package/esm2022/lib/workers/spatial-math.mjs +190 -0
  271. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs +47169 -0
  272. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
  273. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs +238 -0
  274. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map +1 -0
  275. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
  276. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
  277. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
  278. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
  279. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34467
  280. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  281. package/fesm2022/mask.worker.js +36 -917
  282. package/fesm2022/onnx-sam.worker.js +52 -16
  283. package/fesm2022/region-source.worker.js +1067 -0
  284. package/fesm2022/spatial-math.worker.js +471 -0
  285. package/fesm2022/tsne.worker.js +32 -15
  286. package/index.d.ts +19 -10
  287. package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
  288. package/lib/contracts/capabilities.contract.d.ts +4 -2
  289. package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
  290. package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
  291. package/lib/contracts/color.d.ts +27 -0
  292. package/lib/contracts/colormap-lut.d.ts +19 -4
  293. package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
  294. package/lib/contracts/display-types.d.ts +21 -0
  295. package/lib/contracts/image.contract.d.ts +4 -0
  296. package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
  297. package/lib/contracts/intensity.d.ts +13 -2
  298. package/lib/contracts/plot-type.d.ts +3 -1
  299. package/lib/contracts/ports/image-state.port.d.ts +6 -2
  300. package/lib/contracts/ports/preferences.port.d.ts +4 -0
  301. package/lib/contracts/ports/region-io.port.d.ts +1 -0
  302. package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
  303. package/lib/contracts/ports/tile-access.port.d.ts +1 -0
  304. package/lib/contracts/region-editor-api.contract.d.ts +85 -1
  305. package/lib/contracts/region-overlay.contract.d.ts +5 -0
  306. package/lib/contracts/region-store.contract.d.ts +22 -0
  307. package/lib/contracts/sam.contract.d.ts +7 -0
  308. package/lib/contracts/section-view.contract.d.ts +44 -0
  309. package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
  310. package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
  311. package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
  312. package/lib/contracts/visualizer.contract.d.ts +231 -54
  313. package/lib/contracts/viz-config.d.ts +9 -0
  314. package/lib/geometry/contour.d.ts +24 -0
  315. package/lib/geometry/loft.d.ts +22 -0
  316. package/lib/geometry/polylabel.d.ts +23 -0
  317. package/lib/geometry/raster.d.ts +42 -0
  318. package/lib/geometry/reconstruct.d.ts +54 -0
  319. package/lib/geometry/reslice-image.d.ts +33 -0
  320. package/lib/geometry/ring.d.ts +67 -0
  321. package/lib/geometry/section.d.ts +52 -0
  322. package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
  323. package/lib/implementations/base-store-visualizer.d.ts +61 -15
  324. package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
  325. package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
  326. package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
  327. package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
  328. package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -3
  329. package/lib/implementations/napari-js/napari-loading-state.d.ts +37 -0
  330. package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
  331. package/lib/implementations/napari-js/napari-region-overlay.d.ts +68 -71
  332. package/lib/implementations/napari-js/napari-scene.d.ts +126 -0
  333. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
  334. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
  335. package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
  336. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +91 -0
  337. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
  338. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
  339. package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
  340. package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
  341. package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
  342. package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
  343. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +169 -883
  344. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
  345. package/lib/implementations/napari-js/napari-volume-scene.d.ts +148 -0
  346. package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
  347. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
  348. package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
  349. package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
  350. package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
  351. package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
  352. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
  353. package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
  354. package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
  355. package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
  356. package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
  357. package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
  358. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
  359. package/lib/implementations/osd/display-pipeline.d.ts +38 -9
  360. package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
  361. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
  362. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
  363. package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
  364. package/lib/implementations/osd/osd-coords.d.ts +6 -4
  365. package/lib/implementations/osd/osd-export.d.ts +36 -0
  366. package/lib/implementations/osd/osd-lib.d.ts +7 -0
  367. package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
  368. package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
  369. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +38 -0
  370. package/lib/implementations/osd/osd-region-overlay.d.ts +46 -51
  371. package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
  372. package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
  373. package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
  374. package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
  375. package/lib/implementations/osd/osd-viewport.d.ts +77 -0
  376. package/lib/implementations/osd/osd-zoom.d.ts +6 -0
  377. package/lib/implementations/osd/simple-source.d.ts +161 -0
  378. package/lib/implementations/osd/slice-cache.d.ts +12 -3
  379. package/lib/implementations/osd/tile-client.d.ts +11 -14
  380. package/lib/implementations/osd/tile-recolor.d.ts +141 -0
  381. package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
  382. package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
  383. package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
  384. package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
  385. package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
  386. package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
  387. package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
  388. package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
  389. package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
  390. package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
  391. package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
  392. package/lib/implementations/plotly/plotly.service.d.ts +136 -401
  393. package/lib/implementations/region-centroids.d.ts +14 -0
  394. package/lib/implementations/simple-slice-access.service.d.ts +7 -4
  395. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
  396. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
  397. package/lib/implementations/tile-server/index.d.ts +5 -0
  398. package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
  399. package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
  400. package/lib/implementations/tile-server/tile-protocol.d.ts +83 -0
  401. package/lib/implementations/tile-server/transport.d.ts +62 -0
  402. package/lib/intensity/intensity-profile.d.ts +66 -0
  403. package/lib/intensity/intensity-profile.service.d.ts +108 -0
  404. package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
  405. package/lib/models/bezier.d.ts +0 -5
  406. package/lib/models/class-preset.d.ts +25 -0
  407. package/lib/models/geometry.d.ts +14 -48
  408. package/lib/models/polygon-edit.d.ts +72 -0
  409. package/lib/models/polygon-factory.d.ts +45 -0
  410. package/lib/models/region-clone.d.ts +20 -0
  411. package/lib/models/region-geojson.d.ts +57 -0
  412. package/lib/models/region.d.ts +59 -4
  413. package/lib/models/shape.d.ts +8 -0
  414. package/lib/plot-mode/contribution-host.d.ts +125 -0
  415. package/lib/plot-mode/plot-type-menu.d.ts +60 -0
  416. package/lib/plot-mode/tool-params-model.d.ts +49 -0
  417. package/lib/plot.utilities.d.ts +19 -30
  418. package/lib/processing/processing-image.d.ts +5 -2
  419. package/lib/provide-visualization.d.ts +19 -2
  420. package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
  421. package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
  422. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +86 -0
  423. package/lib/region-editor/file-stem.d.ts +7 -0
  424. package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
  425. package/lib/region-editor/mask-export.service.d.ts +54 -0
  426. package/lib/region-editor/mask-raster.d.ts +2 -8
  427. package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
  428. package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
  429. package/lib/region-editor/region-editor.component.d.ts +283 -200
  430. package/lib/region-editor/region-metrics.d.ts +34 -0
  431. package/lib/region-editor/region-persistence.service.d.ts +77 -0
  432. package/lib/region-editor/region-table/region-table.component.d.ts +89 -0
  433. package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
  434. package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
  435. package/lib/region-ops.service.d.ts +1 -7
  436. package/lib/region-overlay/region-geometry.d.ts +158 -0
  437. package/lib/region-overlay/region-hit-test.d.ts +38 -0
  438. package/lib/region-overlay/region-source-layer.d.ts +96 -0
  439. package/lib/region-overlay/region-style.d.ts +52 -0
  440. package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
  441. package/lib/region-source/http-region-source.d.ts +45 -0
  442. package/lib/region-source/region-source-ops.d.ts +89 -0
  443. package/lib/region-source/region-source-worker.d.ts +7 -0
  444. package/lib/region-source/region-source.d.ts +82 -0
  445. package/lib/region-source/region-tiles.d.ts +289 -0
  446. package/lib/region-source/worker-region-source.d.ts +65 -0
  447. package/lib/render-orchestrator.d.ts +6 -2
  448. package/lib/render-session.d.ts +75 -0
  449. package/lib/routing-visualizer.service.d.ts +248 -59
  450. package/lib/section-pane/section-pane.component.d.ts +47 -0
  451. package/lib/spatial/density-raster.d.ts +6 -0
  452. package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
  453. package/lib/spatial/embedding-compute.d.ts +21 -2
  454. package/lib/spatial/glyphs.d.ts +16 -0
  455. package/lib/spatial/lod.d.ts +94 -0
  456. package/lib/spatial/spatial-controls.facade.d.ts +64 -0
  457. package/lib/spatial/spatial-density.d.ts +15 -5
  458. package/lib/spatial/spatial-encoding.d.ts +11 -44
  459. package/lib/spatial/spatial-expression.d.ts +40 -22
  460. package/lib/spatial/spatial-framing.d.ts +1 -0
  461. package/lib/spatial/spatial-heatmap.d.ts +2 -0
  462. package/lib/spatial/spatial-hover.d.ts +4 -16
  463. package/lib/spatial/spatial-panel-model.d.ts +135 -0
  464. package/lib/spatial/spatial-selection.d.ts +21 -26
  465. package/lib/spatial/spatial-tile-merge.d.ts +41 -0
  466. package/lib/spatial/spatial-tiles.d.ts +9 -256
  467. package/lib/spatial/stats.d.ts +38 -0
  468. package/lib/spatial/transcript-grouping.d.ts +119 -0
  469. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
  470. package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
  471. package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
  472. package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
  473. package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
  474. package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
  475. package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
  476. package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
  477. package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
  478. package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
  479. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
  480. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
  481. package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
  482. package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
  483. package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
  484. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
  485. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
  486. package/lib/store/class-color.util.d.ts +39 -2
  487. package/lib/store/class-signatures.d.ts +11 -0
  488. package/lib/store/region-history.d.ts +66 -0
  489. package/lib/store/region-scope-cache.d.ts +65 -0
  490. package/lib/store/region-selection.d.ts +36 -0
  491. package/lib/store/region-source-scope.d.ts +68 -0
  492. package/lib/store/region-store.service.d.ts +312 -116
  493. package/lib/store/visualizer-store.service.d.ts +32 -33
  494. package/lib/toast-outlets.d.ts +4 -3
  495. package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
  496. package/lib/toolbar/canvas-tools.d.ts +20 -0
  497. package/lib/toolbar/crop/slide-crop.d.ts +10 -4
  498. package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
  499. package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
  500. package/lib/toolbar/region-tools/region-tools.component.d.ts +62 -0
  501. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
  502. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
  503. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
  504. package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
  505. package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
  506. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
  507. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
  508. package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
  509. package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
  510. package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
  511. package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
  512. package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
  513. package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
  514. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +51 -0
  515. package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
  516. package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
  517. package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
  518. package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
  519. package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
  520. package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
  521. package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
  522. package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
  523. package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
  524. package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
  525. package/lib/toolbar/toolbar.component.d.ts +55 -84
  526. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
  527. package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
  528. package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
  529. package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
  530. package/lib/toolbar/wand/wand.service.d.ts +22 -116
  531. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
  532. package/lib/util/mark-for-check.d.ts +11 -0
  533. package/lib/util/supersede.d.ts +53 -0
  534. package/lib/visualization.module.d.ts +18 -39
  535. package/lib/visualizer/floating-drag.directive.d.ts +30 -0
  536. package/lib/visualizer/region-actions.d.ts +54 -0
  537. package/lib/visualizer/region-load.d.ts +46 -0
  538. package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
  539. package/lib/visualizer/tool-modes.d.ts +49 -0
  540. package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
  541. package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
  542. package/lib/visualizer/volume-sections.d.ts +64 -0
  543. package/lib/visualizer.component.d.ts +232 -447
  544. package/lib/workers/spatial-math-ops.d.ts +65 -0
  545. package/lib/workers/spatial-math-worker.d.ts +7 -0
  546. package/lib/workers/spatial-math.d.ts +74 -0
  547. package/package.json +12 -3
  548. package/src/lib/assets/slice.svg +23 -0
  549. package/src/lib/styles/_viz-icons-rules.scss +73 -0
  550. package/src/lib/styles/viz-icons.scss +14 -0
  551. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
  552. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
  553. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
  554. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
  555. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
  556. package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
  557. package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
  558. package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
  559. package/src/lib/assets/cell-detection.svg +0 -37
  560. package/src/lib/assets/click.svg +0 -1
  561. package/src/lib/assets/colormap-luts.json +0 -1
  562. package/src/lib/assets/edit-selection-white.svg +0 -47
  563. package/src/lib/assets/icons/colormap-earth.png +0 -0
  564. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  565. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  566. package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
  567. package/src/lib/assets/picture-segmentation.svg +0 -43
  568. package/src/lib/assets/test/download-379.svg +0 -1
  569. package/src/lib/assets/test/download-98.svg +0 -1
  570. package/src/lib/assets/test/json-1.svg +0 -1
  571. package/src/lib/assets/test/load-53.svg +0 -1
  572. package/src/lib/assets/test/mask-44.svg +0 -1
  573. package/src/lib/assets/test/mask-download-44.svg +0 -15
  574. package/src/lib/assets/test/mask-save-44.svg +0 -11
  575. package/src/lib/assets/test/overlay-1.svg +0 -1
  576. package/src/lib/assets/test/overlay-4.svg +0 -1
  577. package/src/lib/assets/test/region-26.svg +0 -1
  578. package/src/lib/assets/test/save-56.svg +0 -1
  579. package/src/lib/assets/test/upload-43.svg +0 -1
@@ -0,0 +1,108 @@
1
+ import { Subscription } from 'rxjs';
2
+ import { takeUntil } from 'rxjs/operators';
3
+ /**
4
+ * One viewer's segmentation runs and their sticky progress toast (jit-ui#90): the
5
+ * box-prompt SAM and Cellpose tools, contributed whole-view tools, and the
6
+ * interactive SAM point tool whose feeds it bridges.
7
+ *
8
+ * The toast is keyed per viewer (`toastKey`), so a run in a pipeline preview does not
9
+ * show in the main view; results and failures go to the viewer's `resultKey` outlet,
10
+ * which the sticky toast's teardown does not clear. The toast template binds
11
+ * {@link status}, {@link progress}, {@link downloading} and {@link busy}.
12
+ */
13
+ export class SegmentationRunner {
14
+ constructor(messages, toastKey, resultKey,
15
+ /** Re-render the toast (its feeds may fire outside the zone). */
16
+ changed) {
17
+ this.messages = messages;
18
+ this.toastKey = toastKey;
19
+ this.resultKey = resultKey;
20
+ this.changed = changed;
21
+ this.status = '';
22
+ /** Encoder download, 0..100. */
23
+ this.progress = 0;
24
+ this.downloading = false;
25
+ /** Any segmentation work in flight (the indeterminate spinner). */
26
+ this.busy = false;
27
+ /** Whether the sticky toast is up — re-adding it would stack one per point click. */
28
+ this.shown = false;
29
+ }
30
+ /** Surface the interactive SAM point tool's status and download progress, which runs
31
+ * inside the renderer on each click (the first click pulls the encoder). */
32
+ bindPointTool(tool, until$) {
33
+ tool.progress$.pipe(takeUntil(until$)).subscribe((f) => this.onProgress(f));
34
+ tool.status$.pipe(takeUntil(until$)).subscribe((m) => {
35
+ this.status = m;
36
+ this.changed();
37
+ });
38
+ tool.busy$.pipe(takeUntil(until$)).subscribe((busy) => {
39
+ this.busy = busy;
40
+ if (busy)
41
+ this.show('SAM point segmentation');
42
+ this.changed();
43
+ });
44
+ }
45
+ /**
46
+ * Run `op` with the tool's status and download progress in the sticky toast, then
47
+ * report the outcome: the region count (or the tool's last status line) on success,
48
+ * the error on failure. The toast stays until the run settles.
49
+ */
50
+ async run(label, tool, op) {
51
+ this.status = 'Starting…';
52
+ this.progress = 0;
53
+ this.downloading = false;
54
+ this.busy = true;
55
+ // The last non-empty status is what the result reports: `tool` is only an
56
+ // Observable pair, so there is no `.value` to sample once the run settles.
57
+ let lastStatus = '';
58
+ const subs = new Subscription();
59
+ subs.add(tool.progress$.subscribe((f) => this.onProgress(f)));
60
+ subs.add(tool.status$.subscribe((m) => {
61
+ if (!m)
62
+ return;
63
+ lastStatus = m;
64
+ this.status = m;
65
+ this.changed();
66
+ }));
67
+ this.show(label);
68
+ try {
69
+ const n = await op();
70
+ this.messages.add({
71
+ key: this.resultKey,
72
+ severity: n > 0 ? 'success' : 'warn',
73
+ summary: label,
74
+ detail: lastStatus || (n > 0 ? `Added ${n} region(s).` : 'No regions added.'),
75
+ });
76
+ }
77
+ catch (e) {
78
+ this.messages.add({ key: this.resultKey, severity: 'error', summary: `${label} failed`, detail: String(e) });
79
+ }
80
+ finally {
81
+ subs.unsubscribe();
82
+ this.hide();
83
+ }
84
+ }
85
+ /** Show the sticky toast once (idempotent). */
86
+ show(summary) {
87
+ if (this.shown)
88
+ return;
89
+ this.shown = true;
90
+ this.messages.add({ key: this.toastKey, sticky: true, severity: 'info', summary });
91
+ }
92
+ /** Dismiss the sticky toast and reset its progress/spinner state. */
93
+ hide() {
94
+ this.shown = false;
95
+ this.busy = false;
96
+ this.downloading = false;
97
+ this.progress = 0;
98
+ this.messages.clear(this.toastKey);
99
+ this.changed();
100
+ }
101
+ onProgress(f) {
102
+ this.downloading = f >= 0 && f < 1;
103
+ if (f >= 0)
104
+ this.progress = Math.min(100, Math.round(f * 100));
105
+ this.changed();
106
+ }
107
+ }
108
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VnbWVudGF0aW9uLXJ1bm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci9zZWdtZW50YXRpb24vc2VnbWVudGF0aW9uLXJ1bm5lci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWMsWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ2hELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQVUzQzs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLE9BQU8sa0JBQWtCO0lBVTdCLFlBQ21CLFFBQStDLEVBQ3ZELFFBQWdCLEVBQ2hCLFNBQWlCO0lBQzFCLGlFQUFpRTtJQUNoRCxPQUFtQjtRQUpuQixhQUFRLEdBQVIsUUFBUSxDQUF1QztRQUN2RCxhQUFRLEdBQVIsUUFBUSxDQUFRO1FBQ2hCLGNBQVMsR0FBVCxTQUFTLENBQVE7UUFFVCxZQUFPLEdBQVAsT0FBTyxDQUFZO1FBZHRDLFdBQU0sR0FBRyxFQUFFLENBQUM7UUFDWixnQ0FBZ0M7UUFDaEMsYUFBUSxHQUFHLENBQUMsQ0FBQztRQUNiLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLG1FQUFtRTtRQUNuRSxTQUFJLEdBQUcsS0FBSyxDQUFDO1FBQ2IscUZBQXFGO1FBQzdFLFVBQUssR0FBRyxLQUFLLENBQUM7SUFRbkIsQ0FBQztJQUVKO2lGQUM2RTtJQUM3RSxhQUFhLENBQUMsSUFBMkQsRUFBRSxNQUEyQjtRQUNwRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM1RSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMs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QUM7UUFDbEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNyRixDQUFDO0lBRUQscUVBQXFFO0lBQ3JFLElBQUk7UUFDRixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQztRQUNsQixJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQztRQUN6QixJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQztRQUNsQixJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2pCLENBQUM7SUFFTyxVQUFVLENBQUMsQ0FBUztRQUMxQixJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQUUsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQy9ELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNqQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IE1lc3NhZ2VTZXJ2aWNlIH0gZnJvbSAncHJpbWVuZy9hcGknO1xuXG4vKiogQSBzZWdtZW50YXRpb24gdG9vbCdzIGxpdmUgZmVlZHM6IHN0YXR1cyBsaW5lIGFuZCBlbmNvZGVyLWRvd25sb2FkIHByb2dyZXNzICgwLi4xLCA8MCA9IG5vbmUpLlxuICogIE9ic2VydmFibGVzLCBub3Qgc3ViamVjdHMsIHNvIGEgY29udHJpYnV0ZWQgdG9vbCBuZWVkIG5vdCBleHBvc2UgaXRzIGludGVybmFscy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2VnbWVudGF0aW9uUHJvZ3Jlc3Mge1xuICBzdGF0dXMkOiBPYnNlcnZhYmxlPHN0cmluZz47XG4gIHByb2dyZXNzJDogT2JzZXJ2YWJsZTxudW1iZXI+O1xufVxuXG4vKipcbiAqIE9uZSB2aWV3ZXIncyBzZWdtZW50YXRpb24gcnVucyBhbmQgdGhlaXIgc3RpY2t5IHByb2dyZXNzIHRvYXN0IChqaXQtdWkjOTApOiB0aGVcbiAqIGJveC1wcm9tcHQgU0FNIGFuZCBDZWxscG9zZSB0b29scywgY29udHJpYnV0ZWQgd2hvbGUtdmlldyB0b29scywgYW5kIHRoZVxuICogaW50ZXJhY3RpdmUgU0FNIHBvaW50IHRvb2wgd2hvc2UgZmVlZHMgaXQgYnJpZGdlcy5cbiAqXG4gKiBUaGUgdG9hc3QgaXMga2V5ZWQgcGVyIHZpZXdlciAoYHRvYXN0S2V5YCksIHNvIGEgcnVuIGluIGEgcGlwZWxpbmUgcHJldmlldyBkb2VzIG5vdFxuICogc2hvdyBpbiB0aGUgbWFpbiB2aWV3OyByZXN1bHRzIGFuZCBmYWlsdXJlcyBnbyB0byB0aGUgdmlld2VyJ3MgYHJlc3VsdEtleWAgb3V0bGV0LFxuICogd2hpY2ggdGhlIHN0aWNreSB0b2FzdCdzIHRlYXJkb3duIGRvZXMgbm90IGNsZWFyLiBUaGUgdG9hc3QgdGVtcGxhdGUgYmluZHNcbiAqIHtAbGluayBzdGF0dXN9LCB7QGxpbmsgcHJvZ3Jlc3N9LCB7QGxpbmsgZG93bmxvYWRpbmd9IGFuZCB7QGxpbmsgYnVzeX0uXG4gKi9cbmV4cG9ydCBjbGFzcyBTZWdtZW50YXRpb25SdW5uZXIge1xuICBzdGF0dXMgPSAnJztcbiAgLyoqIEVuY29kZXIgZG93bmxvYWQsIDAuLjEwMC4gKi9cbiAgcHJvZ3Jlc3MgPSAwO1xuICBkb3dubG9hZGluZyA9IGZhbHNlO1xuICAvKiogQW55IHNlZ21lbnRhdGlvbiB3b3JrIGluIGZsaWdodCAodGhlIGluZGV0ZXJtaW5hdGUgc3Bpbm5lcikuICovXG4gIGJ1c3kgPSBmYWxzZTtcbiAgLyoqIFdoZXRoZXIgdGhlIHN0aWNreSB0b2FzdCBpcyB1cCDigJQgcmUtYWRkaW5nIGl0IHdvdWxkIHN0YWNrIG9uZSBwZXIgcG9pbnQgY2xpY2suICovXG4gIHByaXZhdGUgc2hvd24gPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IG1lc3NhZ2VzOiBQaWNrPE1lc3NhZ2VTZXJ2aWNlLCAnYWRkJyB8ICdjbGVhcic+LFxuICAgIHJlYWRvbmx5IHRvYXN0S2V5OiBzdHJpbmcsXG4gICAgcmVhZG9ubHkgcmVzdWx0S2V5OiBzdHJpbmcsXG4gICAgLyoqIFJlLXJlbmRlciB0aGUgdG9hc3QgKGl0cyBmZWVkcyBtYXkgZmlyZSBvdXRzaWRlIHRoZSB6b25lKS4gKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGNoYW5nZWQ6ICgpID0+IHZvaWQsXG4gICkge31cblxuICAvKiogU3VyZmFjZSB0aGUgaW50ZXJhY3RpdmUgU0FNIHBvaW50IHRvb2wncyBzdGF0dXMgYW5kIGRvd25sb2FkIHByb2dyZXNzLCB3aGljaCBydW5zXG4gICAqICBpbnNpZGUgdGhlIHJlbmRlcmVyIG9uIGVhY2ggY2xpY2sgKHRoZSBmaXJzdCBjbGljayBwdWxscyB0aGUgZW5jb2RlcikuICovXG4gIGJpbmRQb2ludFRvb2wodG9vbDogU2VnbWVudGF0aW9uUHJvZ3Jlc3MgJiB7IGJ1c3kkOiBPYnNlcnZhYmxlPGJvb2xlYW4+IH0sIHVudGlsJDogT2JzZXJ2YWJsZTx1bmtub3duPik6IHZvaWQge1xuICAgIHRvb2wucHJvZ3Jlc3MkLnBpcGUodGFrZVVudGlsKHVudGlsJCkpLnN1YnNjcmliZSgoZikgPT4gdGhpcy5vblByb2dyZXNzKGYpKTtcbiAgICB0b29sLnN0YXR1cyQucGlwZSh0YWtlVW50aWwodW50aWwkKSkuc3Vic2NyaWJlKChtKSA9PiB7XG4gICAgICB0aGlzLnN0YXR1cyA9IG07XG4gICAgICB0aGlzLmNoYW5nZWQoKTtcbiAgICB9KTtcbiAgICB0b29sLmJ1c3kkLnBpcGUodGFrZVVudGlsKHVudGlsJCkpLnN1YnNjcmliZSgoYnVzeSkgPT4ge1xuICAgICAgdGhpcy5idXN5ID0gYnVzeTtcbiAgICAgIGlmIChidXN5KSB0aGlzLnNob3coJ1NBTSBwb2ludCBzZWdtZW50YXRpb24nKTtcbiAgICAgIHRoaXMuY2hhbmdlZCgpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJ1biBgb3BgIHdpdGggdGhlIHRvb2wncyBzdGF0dXMgYW5kIGRvd25sb2FkIHByb2dyZXNzIGluIHRoZSBzdGlja3kgdG9hc3QsIHRoZW5cbiAgICogcmVwb3J0IHRoZSBvdXRjb21lOiB0aGUgcmVnaW9uIGNvdW50IChvciB0aGUgdG9vbCdzIGxhc3Qgc3RhdHVzIGxpbmUpIG9uIHN1Y2Nlc3MsXG4gICAqIHRoZSBlcnJvciBvbiBmYWlsdXJlLiBUaGUgdG9hc3Qgc3RheXMgdW50aWwgdGhlIHJ1biBzZXR0bGVzLlxuICAgKi9cbiAgYXN5bmMgcnVuKGxhYmVsOiBzdHJpbmcsIHRvb2w6IFNlZ21lbnRhdGlvblByb2dyZXNzLCBvcDogKCkgPT4gUHJvbWlzZTxudW1iZXI+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5zdGF0dXMgPSAnU3RhcnRpbmfigKYnO1xuICAgIHRoaXMucHJvZ3Jlc3MgPSAwO1xuICAgIHRoaXMuZG93bmxvYWRpbmcgPSBmYWxzZTtcbiAgICB0aGlzLmJ1c3kgPSB0cnVlO1xuICAgIC8vIFRoZSBsYXN0IG5vbi1lbXB0eSBzdGF0dXMgaXMgd2hhdCB0aGUgcmVzdWx0IHJlcG9ydHM6IGB0b29sYCBpcyBvbmx5IGFuXG4gICAgLy8gT2JzZXJ2YWJsZSBwYWlyLCBzbyB0aGVyZSBpcyBubyBgLnZhbHVlYCB0byBzYW1wbGUgb25jZSB0aGUgcnVuIHNldHRsZXMuXG4gICAgbGV0IGxhc3RTdGF0dXMgPSAnJztcbiAgICBjb25zdCBzdWJzID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuICAgIHN1YnMuYWRkKHRvb2wucHJvZ3Jlc3MkLnN1YnNjcmliZSgoZikgPT4gdGhpcy5vblByb2dyZXNzKGYpKSk7XG4gICAgc3Vicy5hZGQoXG4gICAgICB0b29sLnN0YXR1cyQuc3Vic2NyaWJlKChtKSA9PiB7XG4gICAgICAgIGlmICghbSkgcmV0dXJuO1xuICAgICAgICBsYXN0U3RhdHVzID0gbTtcbiAgICAgICAgdGhpcy5zdGF0dXMgPSBtO1xuICAgICAgICB0aGlzLmNoYW5nZWQoKTtcbiAgICAgIH0pLFxuICAgICk7XG4gICAgdGhpcy5zaG93KGxhYmVsKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgbiA9IGF3YWl0IG9wKCk7XG4gICAgICB0aGlzLm1lc3NhZ2VzLmFkZCh7XG4gICAgICAgIGtleTogdGhpcy5yZXN1bHRLZXksXG4gICAgICAgIHNldmVyaXR5OiBuID4gMCA/ICdzdWNjZXNzJyA6ICd3YXJuJyxcbiAgICAgICAgc3VtbWFyeTogbGFiZWwsXG4gICAgICAgIGRldGFpbDogbGFzdFN0YXR1cyB8fCAobiA+IDAgPyBgQWRkZWQgJHtufSByZWdpb24ocykuYCA6ICdObyByZWdpb25zIGFkZGVkLicpLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5tZXNzYWdlcy5hZGQoeyBrZXk6IHRoaXMucmVzdWx0S2V5LCBzZXZlcml0eTogJ2Vycm9yJywgc3VtbWFyeTogYCR7bGFiZWx9IGZhaWxlZGAsIGRldGFpbDogU3RyaW5nKGUpIH0pO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBzdWJzLnVuc3Vic2NyaWJlKCk7XG4gICAgICB0aGlzLmhpZGUoKTtcbiAgICB9XG4gIH1cblxuICAvKiogU2hvdyB0aGUgc3RpY2t5IHRvYXN0IG9uY2UgKGlkZW1wb3RlbnQpLiAqL1xuICBzaG93KHN1bW1hcnk6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLnNob3duKSByZXR1cm47XG4gICAgdGhpcy5zaG93biA9IHRydWU7XG4gICAgdGhpcy5tZXNzYWdlcy5hZGQoeyBrZXk6IHRoaXMudG9hc3RLZXksIHN0aWNreTogdHJ1ZSwgc2V2ZXJpdHk6ICdpbmZvJywgc3VtbWFyeSB9KTtcbiAgfVxuXG4gIC8qKiBEaXNtaXNzIHRoZSBzdGlja3kgdG9hc3QgYW5kIHJlc2V0IGl0cyBwcm9ncmVzcy9zcGlubmVyIHN0YXRlLiAqL1xuICBoaWRlKCk6IHZvaWQge1xuICAgIHRoaXMuc2hvd24gPSBmYWxzZTtcbiAgICB0aGlzLmJ1c3kgPSBmYWxzZTtcbiAgICB0aGlzLmRvd25sb2FkaW5nID0gZmFsc2U7XG4gICAgdGhpcy5wcm9ncmVzcyA9IDA7XG4gICAgdGhpcy5tZXNzYWdlcy5jbGVhcih0aGlzLnRvYXN0S2V5KTtcbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgfVxuXG4gIHByaXZhdGUgb25Qcm9ncmVzcyhmOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmRvd25sb2FkaW5nID0gZiA+PSAwICYmIGYgPCAxO1xuICAgIGlmIChmID49IDApIHRoaXMucHJvZ3Jlc3MgPSBNYXRoLm1pbigxMDAsIE1hdGgucm91bmQoZiAqIDEwMCkpO1xuICAgIHRoaXMuY2hhbmdlZCgpO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,155 @@
1
+ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { SharedModule } from 'primeng/api';
4
+ import { ButtonModule } from 'primeng/button';
5
+ import { MenuModule } from 'primeng/menu';
6
+ import { TooltipModule } from 'primeng/tooltip';
7
+ import { MODEL_INFO } from '../model-info';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "@angular/common";
10
+ import * as i2 from "primeng/api";
11
+ import * as i3 from "primeng/button";
12
+ import * as i4 from "primeng/menu";
13
+ import * as i5 from "primeng/tooltip";
14
+ /**
15
+ * The toolbar's segmentation group: SAM box prompt, SAM point prompts and the
16
+ * shared SAM model picker, cellpose, and the contributed no-prompt tools (run,
17
+ * pick checkpoint, parameters). Presentational: the host runs every action.
18
+ */
19
+ export class SegmentationToolsComponent {
20
+ constructor() {
21
+ /** The armed tool's mode (`samPoint` highlights the point-prompt button), or null. */
22
+ this.activeDragMode = null;
23
+ /** SAM model picker options + current selection (jit-ui#90 P1). */
24
+ this.samModels = [];
25
+ /** The selected SAM model id. */
26
+ this.samModelId = '';
27
+ /** Contributed no-prompt tools, already filtered and sorted by the host. */
28
+ this.contributedTools = [];
29
+ /** Active checkpoint per contributed tool, keyed by tool id. */
30
+ this.toolModelIds = {};
31
+ /** Run box-prompted SAM segmentation on the drawn rectangles (jit-ui#90). */
32
+ this.segmentRegions = new EventEmitter();
33
+ /** Run cellpose-SAM (auto) inside each drawn rectangle's crop (jit-ui#90). */
34
+ this.segmentCellpose = new EventEmitter();
35
+ /** The SAM point tool's toggle ('samPoint'). */
36
+ this.toggleDragMode = new EventEmitter();
37
+ /** A SAM model was picked from the model menu (its id). */
38
+ this.samModelChange = new EventEmitter();
39
+ /** Run a contributed tool over the current view (its id). */
40
+ this.runTool = new EventEmitter();
41
+ /** A contributed tool's checkpoint was picked. */
42
+ this.toolModelChange = new EventEmitter();
43
+ /** Open a contributed tool's parameter dialog (its id). */
44
+ this.openToolParams = new EventEmitter();
45
+ /** Model picker for the Segment button's dropdown menu. The active model
46
+ * (`samModelId`) is marked with a check; selecting an item emits
47
+ * `samModelChange` (jit-ui#90 P1).
48
+ *
49
+ * Held as a stable array (rebuilt only when `samModels`/`samModelId` change),
50
+ * NOT a getter: a getter returns a fresh array with new `command` closures on
51
+ * every change-detection tick, which makes the bound `p-menu` overlay rebuild
52
+ * its DOM mid-interaction and swallow the click on a menu item.
53
+ *
54
+ * `tooltip` carries the model's description from {@link MODEL_INFO}; the
55
+ * menus' shared item template turns it into the hover info icon. p-menu's own
56
+ * rendering ignores the field (it reads `item.title`), so it is free to use. */
57
+ this.samMenuItems = [];
58
+ /**
59
+ * Model menus for the contributed tools, keyed by tool id. Same stable-array
60
+ * reasoning as {@link samMenuItems} — and it is why this is a map rebuilt in
61
+ * `ngOnChanges` rather than a method called from the template, which would
62
+ * hand `p-menu` a new array every tick.
63
+ *
64
+ * A contributed tool supplies its own per-model description, so unlike the
65
+ * SAM menu these do not consult {@link MODEL_INFO}: this library has no
66
+ * copy for checkpoints it does not know about.
67
+ */
68
+ this.toolMenuItems = {};
69
+ }
70
+ ngOnChanges(changes) {
71
+ if (changes['samModels'] || changes['samModelId']) {
72
+ this.samMenuItems = this.samModels.map((m) => ({
73
+ label: m.label,
74
+ icon: m.id === this.samModelId ? 'pi pi-check' : 'pi pi-fw',
75
+ tooltip: MODEL_INFO[m.id],
76
+ infoLabel: this.infoLabel(m.label, MODEL_INFO[m.id]),
77
+ command: () => this.samModelChange.emit(m.id),
78
+ }));
79
+ }
80
+ if (changes['contributedTools'] || changes['toolModelIds']) {
81
+ this.toolMenuItems = {};
82
+ for (const tool of this.contributedTools) {
83
+ const active = this.toolModelIds[tool.id] ?? tool.defaultModelId();
84
+ this.toolMenuItems[tool.id] = tool.models().map((m) => ({
85
+ label: m.label,
86
+ icon: m.id === active ? 'pi pi-check' : 'pi pi-fw',
87
+ tooltip: m.info,
88
+ infoLabel: this.infoLabel(m.label, m.info),
89
+ command: () => this.toolModelChange.emit({ toolId: tool.id, modelId: m.id }),
90
+ }));
91
+ }
92
+ }
93
+ }
94
+ /**
95
+ * Strip markup from a model description so it can be read aloud.
96
+ *
97
+ * The copy in MODEL_INFO and in a contribution's `ToolModelOption.info` is
98
+ * written for a visual tooltip rendered with `[escape]="false"`, so it carries
99
+ * `<b>` and `<br>`. Passed to `aria-label` verbatim a screen reader announces
100
+ * the tags, so they are removed and `<br>` becomes a sentence break. Entities
101
+ * used in that copy (`&nbsp;`, `&times;`, `&amp;`) are decoded for the same
102
+ * reason.
103
+ */
104
+ plainText(html) {
105
+ return (html ?? '')
106
+ .replace(/<br\s*\/?>/gi, '. ')
107
+ .replace(/<[^>]+>/g, '')
108
+ .replace(/&nbsp;/g, ' ')
109
+ .replace(/&times;/g, 'x')
110
+ .replace(/&amp;/g, '&')
111
+ .replace(/\s+/g, ' ')
112
+ .trim();
113
+ }
114
+ /** The info button's `aria-label` (`infoLabel` on a menu item), built once with the
115
+ * menu rather than by a template call on every check; none without a description. */
116
+ infoLabel(label, info) {
117
+ return info ? `About ${label}: ${this.plainText(info)}` : undefined;
118
+ }
119
+ /** Keeps each contributed tool's `p-menu` overlay alive across CD ticks —
120
+ * re-creating it mid-interaction swallows the click on a menu item. */
121
+ trackToolById(_index, tool) {
122
+ return tool.id;
123
+ }
124
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SegmentationToolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
125
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: SegmentationToolsComponent, isStandalone: true, selector: "toolbar-segmentation-tools", inputs: { activeDragMode: "activeDragMode", samModels: "samModels", samModelId: "samModelId", contributedTools: "contributedTools", toolModelIds: "toolModelIds" }, outputs: { segmentRegions: "segmentRegions", segmentCellpose: "segmentCellpose", toggleDragMode: "toggleDragMode", samModelChange: "samModelChange", runTool: "runTool", toolModelChange: "toolModelChange", openToolParams: "openToolParams" }, usesOnChanges: true, ngImport: i0, template: "<!-- SAM (jit-ui#90): box-prompt segment, interactive point prompts, and a\n model picker. -->\n<span class=\"toolbar-separator\"></span>\n<!-- SAM controls grouped: box-prompt Segment, then the point-prompt tool,\n then the model-picker dropdown (the chevron) which governs BOTH tools.\n Falls back to Segment + point with no model picker when none are set. -->\n<span *ngIf=\"samModels.length; else segmentPlain\" class=\"p-buttonset segment-split\">\n <p-button\n size=\"small\"\n [text]=\"true\"\n ariaLabel=\"Segment with SAM (box prompt)\"\n pTooltip=\"Segment the drawn rectangles with SAM (box prompt)\"\n tooltipPosition=\"bottom\"\n (onClick)=\"segmentRegions.emit()\"\n >\n <img src=\"assets/plotting/sam-box-prompt.svg\" class=\"toolbar-icon-dark\" style=\"width: 1rem\" />\n </p-button>\n <ng-container [ngTemplateOutlet]=\"samPointBtn\"></ng-container>\n <p-button\n icon=\"pi pi-chevron-down\"\n size=\"small\"\n [text]=\"true\"\n ariaLabel=\"Pick the SAM model\"\n pTooltip=\"Pick the SAM model (used by both segment tools)\"\n tooltipPosition=\"bottom\"\n (onClick)=\"samModelMenu.toggle($event)\"\n >\n </p-button>\n</span>\n<ng-template #segmentPlain>\n <span class=\"p-buttonset segment-split\">\n <p-button\n size=\"small\"\n [text]=\"true\"\n ariaLabel=\"Segment with SAM (box prompt)\"\n pTooltip=\"Segment the drawn rectangles with SAM (box prompt)\"\n tooltipPosition=\"bottom\"\n (onClick)=\"segmentRegions.emit()\"\n >\n <img src=\"assets/plotting/sam-box-prompt.svg\" class=\"toolbar-icon-dark\" style=\"width: 1rem\" />\n </p-button>\n <ng-container [ngTemplateOutlet]=\"samPointBtn\"></ng-container>\n </span>\n</ng-template>\n<!-- Point-prompt tool \u2014 shared between the models / no-models layouts so it\n always sits just left of the model dropdown. -->\n<ng-template #samPointBtn>\n <p-button\n size=\"small\"\n ariaLabel=\"SAM point prompts\"\n [text]=\"activeDragMode !== 'samPoint'\"\n pTooltip=\"SAM point prompts: click a fiber to segment it as a new region;\n Shift/Alt-click to refine (exclude) the current one.<br>Esc undoes it.\"\n [escape]=\"false\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toggleDragMode.emit('samPoint')\"\n >\n <img\n src=\"assets/plotting/sam-point-prompt.svg\"\n [class]=\"activeDragMode === 'samPoint' ? 'toolbar-icon-active' : 'toolbar-icon-dark'\"\n style=\"width: 1rem\"\n />\n </p-button>\n</ng-template>\n<p-menu #samModelMenu styleClass=\"model-menu\" [model]=\"samMenuItems\" [popup]=\"true\" appendTo=\"body\">\n <ng-template pTemplate=\"item\" let-item>\n <ng-container\n [ngTemplateOutlet]=\"modelMenuItem\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n ></ng-container>\n </ng-template>\n</p-menu>\n\n<!-- Shared item body for all three model pickers (SAM / YOLO / retinal):\n the standard check-or-blank icon and label, plus an info icon carrying\n the model's description as a hover tooltip. This replaced a single\n \"About the SAM models\" overlay panel \u2014 per-model text sits next to the\n model it describes, and YOLO/retinal get the same affordance.\n\n p-menu puts its click handler on the wrapping `.p-menuitem-content`,\n outside this template, so `command` still fires and the whole row stays\n clickable \u2014 which is also why the info icon has to stop propagation, or\n reading about a model would switch to it. -->\n<ng-template #modelMenuItem let-item>\n <a class=\"p-menuitem-link model-menu-item\">\n <span class=\"p-menuitem-icon\" [ngClass]=\"item.icon\"></span>\n <span class=\"p-menuitem-text\">{{ item.label }}</span>\n <!-- `bottom` like every other tooltip in this toolbar, and for room:\n these menus open under buttons that can sit near the right edge,\n where a `right` tooltip has a few hundred px and squeezes its text\n into a narrow column instead of using its max-width. -->\n <!-- A focusable <button>, not a bare <i>. As an <i> the description\n was reachable only by hovering a mouse: not tabbable, no\n accessible name, nothing for a screen reader to announce \u2014 so\n keyboard and AT users could pick a checkpoint but never read what\n it was. PrimeNG's tooltip shows on focus as well as hover, so\n making it a button restores it for free.\n\n `aria-describedby` is deliberately not used: the tooltip is\n rendered into `body` on demand and has no stable id to point at.\n The description is carried on `aria-label` instead, which is\n announced whether or not the tooltip is showing. It is stripped of\n markup first, since the copy contains `<b>`/`<br>` for the visual\n tooltip and those would otherwise be read out literally. -->\n <button\n *ngIf=\"item.tooltip\"\n type=\"button\"\n class=\"pi pi-info-circle model-info-icon\"\n [attr.aria-label]=\"item.infoLabel\"\n [pTooltip]=\"item.tooltip\"\n [escape]=\"false\"\n tooltipPosition=\"bottom\"\n appendTo=\"body\"\n tooltipStyleClass=\"model-info-tooltip\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"$event.stopPropagation()\"\n (keydown.space)=\"$event.stopPropagation()\"\n ></button>\n </a>\n</ng-template>\n<p-button\n size=\"small\"\n [text]=\"true\"\n ariaLabel=\"Segment cells (cellpose-SAM)\"\n pTooltip=\"Auto-segment cells inside each drawn rectangle (cellpose-SAM)\"\n tooltipPosition=\"bottom\"\n (onClick)=\"segmentCellpose.emit()\"\n>\n <img src=\"assets/plotting/cells.svg\" class=\"toolbar-icon-dark\" style=\"width: 1rem\" />\n</p-button>\n\n<!-- Contributed no-prompt tools (TOOLBAR_TOOLS). Unlike the SAM and\n cellpose tools these take no prompt \u2014 they sweep the whole current\n view rather than being pointed at something \u2014 so there is nothing to\n draw first. Each renders the same split button: run, pick checkpoint,\n open parameters.\n\n Nothing here names a specific tool. The library ships none; a host\n registers them, which is what lets this package be published without\n the closed model dependencies. -->\n<ng-container *ngFor=\"let tool of contributedTools; trackBy: trackToolById\">\n <span class=\"p-buttonset segment-split\">\n <p-button\n size=\"small\"\n [text]=\"true\"\n [ariaLabel]=\"tool.label\"\n [pTooltip]=\"tool.runTooltip\"\n tooltipPosition=\"bottom\"\n (onClick)=\"runTool.emit(tool.id)\"\n >\n <!-- `toolbar-icon-dark` is hardcoded rather than bound, unlike the\n toggle tools: these fire a run and have no active state. -->\n <img\n *ngIf=\"tool.icon.src\"\n [src]=\"tool.icon.src\"\n class=\"toolbar-icon-dark\"\n style=\"width: 1rem\"\n [alt]=\"tool.label\"\n />\n <i *ngIf=\"tool.icon.pi\" class=\"pi {{ tool.icon.pi }}\"></i>\n </p-button>\n <p-button\n icon=\"pi pi-chevron-down\"\n size=\"small\"\n [text]=\"true\"\n [ariaLabel]=\"'Pick the model for ' + tool.label\"\n [pTooltip]=\"tool.modelTooltip || 'Pick the model'\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toolMenu.toggle($event)\"\n >\n </p-button>\n <p-button\n *ngIf=\"tool.params.length\"\n icon=\"pi pi-sliders-h\"\n size=\"small\"\n [text]=\"true\"\n [ariaLabel]=\"'Parameters for ' + tool.label\"\n [pTooltip]=\"tool.paramsTooltip || 'Parameters'\"\n tooltipPosition=\"bottom\"\n (onClick)=\"openToolParams.emit(tool.id)\"\n >\n </p-button>\n </span>\n <p-menu #toolMenu styleClass=\"model-menu\" [model]=\"toolMenuItems[tool.id] || []\" [popup]=\"true\" appendTo=\"body\">\n <ng-template pTemplate=\"item\" let-item>\n <ng-container\n [ngTemplateOutlet]=\"modelMenuItem\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n ></ng-container>\n </ng-template>\n </p-menu>\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.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: SharedModule }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { 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: MenuModule }, { kind: "component", type: i4.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "appendTo", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaLabel", "ariaLabelledBy", "id", "tabindex"], outputs: ["onShow", "onHide", "onBlur", "onFocus"] }, { 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: "ngmodule", type: TooltipModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
126
+ }
127
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SegmentationToolsComponent, decorators: [{
128
+ type: Component,
129
+ args: [{ selector: 'toolbar-segmentation-tools', standalone: true, imports: [CommonModule, SharedModule, ButtonModule, MenuModule, TooltipModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- SAM (jit-ui#90): box-prompt segment, interactive point prompts, and a\n model picker. -->\n<span class=\"toolbar-separator\"></span>\n<!-- SAM controls grouped: box-prompt Segment, then the point-prompt tool,\n then the model-picker dropdown (the chevron) which governs BOTH tools.\n Falls back to Segment + point with no model picker when none are set. -->\n<span *ngIf=\"samModels.length; else segmentPlain\" class=\"p-buttonset segment-split\">\n <p-button\n size=\"small\"\n [text]=\"true\"\n ariaLabel=\"Segment with SAM (box prompt)\"\n pTooltip=\"Segment the drawn rectangles with SAM (box prompt)\"\n tooltipPosition=\"bottom\"\n (onClick)=\"segmentRegions.emit()\"\n >\n <img src=\"assets/plotting/sam-box-prompt.svg\" class=\"toolbar-icon-dark\" style=\"width: 1rem\" />\n </p-button>\n <ng-container [ngTemplateOutlet]=\"samPointBtn\"></ng-container>\n <p-button\n icon=\"pi pi-chevron-down\"\n size=\"small\"\n [text]=\"true\"\n ariaLabel=\"Pick the SAM model\"\n pTooltip=\"Pick the SAM model (used by both segment tools)\"\n tooltipPosition=\"bottom\"\n (onClick)=\"samModelMenu.toggle($event)\"\n >\n </p-button>\n</span>\n<ng-template #segmentPlain>\n <span class=\"p-buttonset segment-split\">\n <p-button\n size=\"small\"\n [text]=\"true\"\n ariaLabel=\"Segment with SAM (box prompt)\"\n pTooltip=\"Segment the drawn rectangles with SAM (box prompt)\"\n tooltipPosition=\"bottom\"\n (onClick)=\"segmentRegions.emit()\"\n >\n <img src=\"assets/plotting/sam-box-prompt.svg\" class=\"toolbar-icon-dark\" style=\"width: 1rem\" />\n </p-button>\n <ng-container [ngTemplateOutlet]=\"samPointBtn\"></ng-container>\n </span>\n</ng-template>\n<!-- Point-prompt tool \u2014 shared between the models / no-models layouts so it\n always sits just left of the model dropdown. -->\n<ng-template #samPointBtn>\n <p-button\n size=\"small\"\n ariaLabel=\"SAM point prompts\"\n [text]=\"activeDragMode !== 'samPoint'\"\n pTooltip=\"SAM point prompts: click a fiber to segment it as a new region;\n Shift/Alt-click to refine (exclude) the current one.<br>Esc undoes it.\"\n [escape]=\"false\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toggleDragMode.emit('samPoint')\"\n >\n <img\n src=\"assets/plotting/sam-point-prompt.svg\"\n [class]=\"activeDragMode === 'samPoint' ? 'toolbar-icon-active' : 'toolbar-icon-dark'\"\n style=\"width: 1rem\"\n />\n </p-button>\n</ng-template>\n<p-menu #samModelMenu styleClass=\"model-menu\" [model]=\"samMenuItems\" [popup]=\"true\" appendTo=\"body\">\n <ng-template pTemplate=\"item\" let-item>\n <ng-container\n [ngTemplateOutlet]=\"modelMenuItem\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n ></ng-container>\n </ng-template>\n</p-menu>\n\n<!-- Shared item body for all three model pickers (SAM / YOLO / retinal):\n the standard check-or-blank icon and label, plus an info icon carrying\n the model's description as a hover tooltip. This replaced a single\n \"About the SAM models\" overlay panel \u2014 per-model text sits next to the\n model it describes, and YOLO/retinal get the same affordance.\n\n p-menu puts its click handler on the wrapping `.p-menuitem-content`,\n outside this template, so `command` still fires and the whole row stays\n clickable \u2014 which is also why the info icon has to stop propagation, or\n reading about a model would switch to it. -->\n<ng-template #modelMenuItem let-item>\n <a class=\"p-menuitem-link model-menu-item\">\n <span class=\"p-menuitem-icon\" [ngClass]=\"item.icon\"></span>\n <span class=\"p-menuitem-text\">{{ item.label }}</span>\n <!-- `bottom` like every other tooltip in this toolbar, and for room:\n these menus open under buttons that can sit near the right edge,\n where a `right` tooltip has a few hundred px and squeezes its text\n into a narrow column instead of using its max-width. -->\n <!-- A focusable <button>, not a bare <i>. As an <i> the description\n was reachable only by hovering a mouse: not tabbable, no\n accessible name, nothing for a screen reader to announce \u2014 so\n keyboard and AT users could pick a checkpoint but never read what\n it was. PrimeNG's tooltip shows on focus as well as hover, so\n making it a button restores it for free.\n\n `aria-describedby` is deliberately not used: the tooltip is\n rendered into `body` on demand and has no stable id to point at.\n The description is carried on `aria-label` instead, which is\n announced whether or not the tooltip is showing. It is stripped of\n markup first, since the copy contains `<b>`/`<br>` for the visual\n tooltip and those would otherwise be read out literally. -->\n <button\n *ngIf=\"item.tooltip\"\n type=\"button\"\n class=\"pi pi-info-circle model-info-icon\"\n [attr.aria-label]=\"item.infoLabel\"\n [pTooltip]=\"item.tooltip\"\n [escape]=\"false\"\n tooltipPosition=\"bottom\"\n appendTo=\"body\"\n tooltipStyleClass=\"model-info-tooltip\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"$event.stopPropagation()\"\n (keydown.space)=\"$event.stopPropagation()\"\n ></button>\n </a>\n</ng-template>\n<p-button\n size=\"small\"\n [text]=\"true\"\n ariaLabel=\"Segment cells (cellpose-SAM)\"\n pTooltip=\"Auto-segment cells inside each drawn rectangle (cellpose-SAM)\"\n tooltipPosition=\"bottom\"\n (onClick)=\"segmentCellpose.emit()\"\n>\n <img src=\"assets/plotting/cells.svg\" class=\"toolbar-icon-dark\" style=\"width: 1rem\" />\n</p-button>\n\n<!-- Contributed no-prompt tools (TOOLBAR_TOOLS). Unlike the SAM and\n cellpose tools these take no prompt \u2014 they sweep the whole current\n view rather than being pointed at something \u2014 so there is nothing to\n draw first. Each renders the same split button: run, pick checkpoint,\n open parameters.\n\n Nothing here names a specific tool. The library ships none; a host\n registers them, which is what lets this package be published without\n the closed model dependencies. -->\n<ng-container *ngFor=\"let tool of contributedTools; trackBy: trackToolById\">\n <span class=\"p-buttonset segment-split\">\n <p-button\n size=\"small\"\n [text]=\"true\"\n [ariaLabel]=\"tool.label\"\n [pTooltip]=\"tool.runTooltip\"\n tooltipPosition=\"bottom\"\n (onClick)=\"runTool.emit(tool.id)\"\n >\n <!-- `toolbar-icon-dark` is hardcoded rather than bound, unlike the\n toggle tools: these fire a run and have no active state. -->\n <img\n *ngIf=\"tool.icon.src\"\n [src]=\"tool.icon.src\"\n class=\"toolbar-icon-dark\"\n style=\"width: 1rem\"\n [alt]=\"tool.label\"\n />\n <i *ngIf=\"tool.icon.pi\" class=\"pi {{ tool.icon.pi }}\"></i>\n </p-button>\n <p-button\n icon=\"pi pi-chevron-down\"\n size=\"small\"\n [text]=\"true\"\n [ariaLabel]=\"'Pick the model for ' + tool.label\"\n [pTooltip]=\"tool.modelTooltip || 'Pick the model'\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toolMenu.toggle($event)\"\n >\n </p-button>\n <p-button\n *ngIf=\"tool.params.length\"\n icon=\"pi pi-sliders-h\"\n size=\"small\"\n [text]=\"true\"\n [ariaLabel]=\"'Parameters for ' + tool.label\"\n [pTooltip]=\"tool.paramsTooltip || 'Parameters'\"\n tooltipPosition=\"bottom\"\n (onClick)=\"openToolParams.emit(tool.id)\"\n >\n </p-button>\n </span>\n <p-menu #toolMenu styleClass=\"model-menu\" [model]=\"toolMenuItems[tool.id] || []\" [popup]=\"true\" appendTo=\"body\">\n <ng-template pTemplate=\"item\" let-item>\n <ng-container\n [ngTemplateOutlet]=\"modelMenuItem\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n ></ng-container>\n </ng-template>\n </p-menu>\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"] }]
130
+ }], propDecorators: { activeDragMode: [{
131
+ type: Input
132
+ }], samModels: [{
133
+ type: Input
134
+ }], samModelId: [{
135
+ type: Input
136
+ }], contributedTools: [{
137
+ type: Input
138
+ }], toolModelIds: [{
139
+ type: Input
140
+ }], segmentRegions: [{
141
+ type: Output
142
+ }], segmentCellpose: [{
143
+ type: Output
144
+ }], toggleDragMode: [{
145
+ type: Output
146
+ }], samModelChange: [{
147
+ type: Output
148
+ }], runTool: [{
149
+ type: Output
150
+ }], toolModelChange: [{
151
+ type: Output
152
+ }], openToolParams: [{
153
+ type: Output
154
+ }] } });
155
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VnbWVudGF0aW9uLXRvb2xzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci9zZWdtZW50YXRpb24tdG9vbHMvc2VnbWVudGF0aW9uLXRvb2xzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci9zZWdtZW50YXRpb24tdG9vbHMvc2VnbWVudGF0aW9uLXRvb2xzLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBRUwsTUFBTSxHQUVQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQVksWUFBWSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUdoRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7Ozs7O0FBRTNDOzs7O0dBSUc7QUFTSCxNQUFNLE9BQU8sMEJBQTBCO0lBUnZDO1FBU0Usc0ZBQXNGO1FBQzdFLG1CQUFjLEdBQWtCLElBQUksQ0FBQztRQUM5QyxtRUFBbUU7UUFDMUQsY0FBUyxHQUFvQyxFQUFFLENBQUM7UUFDekQsaUNBQWlDO1FBQ3hCLGVBQVUsR0FBRyxFQUFFLENBQUM7UUFDekIsNEVBQTRFO1FBQ25FLHFCQUFnQixHQUE4QixFQUFFLENBQUM7UUFDMUQsZ0VBQWdFO1FBQ3ZELGlCQUFZLEdBQTJCLEVBQUUsQ0FBQztRQUVuRCw2RUFBNkU7UUFDbkUsbUJBQWMsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBQ3BELDhFQUE4RTtRQUNwRSxvQkFBZSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFDckQsZ0RBQWdEO1FBQ3RDLG1CQUFjLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUN0RCwyREFBMkQ7UUFDakQsbUJBQWMsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBQ3RELDZEQUE2RDtRQUNuRCxZQUFPLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUMvQyxrREFBa0Q7UUFDeEMsb0JBQWUsR0FBRyxJQUFJLFlBQVksRUFBdUMsQ0FBQztRQUNwRiwyREFBMkQ7UUFDakQsbUJBQWMsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBRXREOzs7Ozs7Ozs7Ozt5RkFXaUY7UUFDdkUsaUJBQVksR0FBZSxFQUFFLENBQUM7UUFDeEM7Ozs7Ozs7OztXQVNHO1FBQ08sa0JBQWEsR0FBK0IsRUFBRSxDQUFDO0tBMkQxRDtJQXpEQyxXQUFXLENBQUMsT0FBc0I7UUFDaEMsSUFBSSxPQUFPLENBQUMsV0FBVyxDQUFDLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7WUFDbEQsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDN0MsS0FBSyxFQUFFLENBQUMsQ0FBQyxLQUFLO2dCQUNkLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsVUFBVTtnQkFDM0QsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUN6QixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3BELE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2FBQzlDLENBQUMsQ0FBQyxDQUFDO1FBQ04sQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLGtCQUFrQixDQUFDLElBQUksT0FBTyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7WUFDM0QsSUFBSSxDQUFDLGFBQWEsR0FBRyxFQUFFLENBQUM7WUFDeEIsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDekMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUNuRSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO29CQUN0RCxLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUs7b0JBQ2QsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLFVBQVU7b0JBQ2xELE9BQU8sRUFBRSxDQUFDLENBQUMsSUFBSTtvQkFDZixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUM7b0JBQzFDLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7aUJBQzdFLENBQUMsQ0FBQyxDQUFDO1lBQ04sQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ08sU0FBUyxDQUFDLElBQVk7UUFDOUIsT0FBTyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUM7YUFDaEIsT0FBTyxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUM7YUFDN0IsT0FBTyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUM7YUFDdkIsT0FBTyxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUM7YUFDdkIsT0FBTyxDQUFDLFVBQVUsRUFBRSxHQUFHLENBQUM7YUFDeEIsT0FBTyxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUM7YUFDdEIsT0FBTyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUM7YUFDcEIsSUFBSSxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQ7MEZBQ3NGO0lBQzlFLFNBQVMsQ0FBQyxLQUFhLEVBQUUsSUFBd0I7UUFDdkQsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsS0FBSyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQ3RFLENBQUM7SUFFRDs0RUFDd0U7SUFDOUQsYUFBYSxDQUFDLE1BQWMsRUFBRSxJQUFvQjtRQUMxRCxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDakIsQ0FBQzs4R0E1R1UsMEJBQTBCO2tHQUExQiwwQkFBMEIsZ2dCQy9CdkMsczdQQWdNQSx3ZUR0S1ksWUFBWSxvZ0JBQUUsWUFBWSxxSUFBRSxZQUFZLDZYQUFFLFVBQVUsaXFCQUFFLGFBQWE7OzJGQUtsRSwwQkFBMEI7a0JBUnRDLFNBQVM7K0JBQ0UsNEJBQTRCLGNBQzFCLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxhQUFhLENBQUMsbUJBRzdELHVCQUF1QixDQUFDLE1BQU07OEJBSXRDLGNBQWM7c0JBQXRCLEtBQUs7Z0JBRUcsU0FBUztzQkFBakIsS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFFRyxZQUFZO3NCQUFwQixLQUFLO2dCQUdJLGNBQWM7c0JBQXZCLE1BQU07Z0JBRUcsZUFBZTtzQkFBeEIsTUFBTTtnQkFFRyxjQUFjO3NCQUF2QixNQUFNO2dCQUVHLGNBQWM7c0JBQXZCLE1BQU07Z0JBRUcsT0FBTztzQkFBaEIsTUFBTTtnQkFFRyxlQUFlO3NCQUF4QixNQUFNO2dCQUVHLGNBQWM7c0JBQXZCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgTWVudUl0ZW0sIFNoYXJlZE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvYXBpJztcbmltcG9ydCB7IEJ1dHRvbk1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvYnV0dG9uJztcbmltcG9ydCB7IE1lbnVNb2R1bGUgfSBmcm9tICdwcmltZW5nL21lbnUnO1xuaW1wb3J0IHsgVG9vbHRpcE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvdG9vbHRpcCc7XG5cbmltcG9ydCB7IFRvb2xiYXJUb29sQ29udHJpYnV0aW9uIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3Rvb2xiYXItdG9vbC5jb250cmFjdCc7XG5pbXBvcnQgeyBNT0RFTF9JTkZPIH0gZnJvbSAnLi4vbW9kZWwtaW5mbyc7XG5cbi8qKlxuICogVGhlIHRvb2xiYXIncyBzZWdtZW50YXRpb24gZ3JvdXA6IFNBTSBib3ggcHJvbXB0LCBTQU0gcG9pbnQgcHJvbXB0cyBhbmQgdGhlXG4gKiBzaGFyZWQgU0FNIG1vZGVsIHBpY2tlciwgY2VsbHBvc2UsIGFuZCB0aGUgY29udHJpYnV0ZWQgbm8tcHJvbXB0IHRvb2xzIChydW4sXG4gKiBwaWNrIGNoZWNrcG9pbnQsIHBhcmFtZXRlcnMpLiBQcmVzZW50YXRpb25hbDogdGhlIGhvc3QgcnVucyBldmVyeSBhY3Rpb24uXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3Rvb2xiYXItc2VnbWVudGF0aW9uLXRvb2xzJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgU2hhcmVkTW9kdWxlLCBCdXR0b25Nb2R1bGUsIE1lbnVNb2R1bGUsIFRvb2x0aXBNb2R1bGVdLFxuICB0ZW1wbGF0ZVVybDogJy4vc2VnbWVudGF0aW9uLXRvb2xzLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vc2VnbWVudGF0aW9uLXRvb2xzLmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBTZWdtZW50YXRpb25Ub29sc0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG4gIC8qKiBUaGUgYXJtZWQgdG9vbCdzIG1vZGUgKGBzYW1Qb2ludGAgaGlnaGxpZ2h0cyB0aGUgcG9pbnQtcHJvbXB0IGJ1dHRvbiksIG9yIG51bGwuICovXG4gIEBJbnB1dCgpIGFjdGl2ZURyYWdNb2RlOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgLyoqIFNBTSBtb2RlbCBwaWNrZXIgb3B0aW9ucyArIGN1cnJlbnQgc2VsZWN0aW9uIChqaXQtdWkjOTAgUDEpLiAqL1xuICBASW5wdXQoKSBzYW1Nb2RlbHM6IHsgaWQ6IHN0cmluZzsgbGFiZWw6IHN0cmluZyB9W10gPSBbXTtcbiAgLyoqIFRoZSBzZWxlY3RlZCBTQU0gbW9kZWwgaWQuICovXG4gIEBJbnB1dCgpIHNhbU1vZGVsSWQgPSAnJztcbiAgLyoqIENvbnRyaWJ1dGVkIG5vLXByb21wdCB0b29scywgYWxyZWFkeSBmaWx0ZXJlZCBhbmQgc29ydGVkIGJ5IHRoZSBob3N0LiAqL1xuICBASW5wdXQoKSBjb250cmlidXRlZFRvb2xzOiBUb29sYmFyVG9vbENvbnRyaWJ1dGlvbltdID0gW107XG4gIC8qKiBBY3RpdmUgY2hlY2twb2ludCBwZXIgY29udHJpYnV0ZWQgdG9vbCwga2V5ZWQgYnkgdG9vbCBpZC4gKi9cbiAgQElucHV0KCkgdG9vbE1vZGVsSWRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgLyoqIFJ1biBib3gtcHJvbXB0ZWQgU0FNIHNlZ21lbnRhdGlvbiBvbiB0aGUgZHJhd24gcmVjdGFuZ2xlcyAoaml0LXVpIzkwKS4gKi9cbiAgQE91dHB1dCgpIHNlZ21lbnRSZWdpb25zID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuICAvKiogUnVuIGNlbGxwb3NlLVNBTSAoYXV0bykgaW5zaWRlIGVhY2ggZHJhd24gcmVjdGFuZ2xlJ3MgY3JvcCAoaml0LXVpIzkwKS4gKi9cbiAgQE91dHB1dCgpIHNlZ21lbnRDZWxscG9zZSA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgLyoqIFRoZSBTQU0gcG9pbnQgdG9vbCdzIHRvZ2dsZSAoJ3NhbVBvaW50JykuICovXG4gIEBPdXRwdXQoKSB0b2dnbGVEcmFnTW9kZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuICAvKiogQSBTQU0gbW9kZWwgd2FzIHBpY2tlZCBmcm9tIHRoZSBtb2RlbCBtZW51IChpdHMgaWQpLiAqL1xuICBAT3V0cHV0KCkgc2FtTW9kZWxDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcbiAgLyoqIFJ1biBhIGNvbnRyaWJ1dGVkIHRvb2wgb3ZlciB0aGUgY3VycmVudCB2aWV3IChpdHMgaWQpLiAqL1xuICBAT3V0cHV0KCkgcnVuVG9vbCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuICAvKiogQSBjb250cmlidXRlZCB0b29sJ3MgY2hlY2twb2ludCB3YXMgcGlja2VkLiAqL1xuICBAT3V0cHV0KCkgdG9vbE1vZGVsQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjx7IHRvb2xJZDogc3RyaW5nOyBtb2RlbElkOiBzdHJpbmcgfT4oKTtcbiAgLyoqIE9wZW4gYSBjb250cmlidXRlZCB0b29sJ3MgcGFyYW1ldGVyIGRpYWxvZyAoaXRzIGlkKS4gKi9cbiAgQE91dHB1dCgpIG9wZW5Ub29sUGFyYW1zID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cbiAgLyoqIE1vZGVsIHBpY2tlciBmb3IgdGhlIFNlZ21lbnQgYnV0dG9uJ3MgZHJvcGRvd24gbWVudS4gVGhlIGFjdGl2ZSBtb2RlbFxuICAgKiAgKGBzYW1Nb2RlbElkYCkgaXMgbWFya2VkIHdpdGggYSBjaGVjazsgc2VsZWN0aW5nIGFuIGl0ZW0gZW1pdHNcbiAgICogIGBzYW1Nb2RlbENoYW5nZWAgKGppdC11aSM5MCBQMSkuXG4gICAqXG4gICAqICBIZWxkIGFzIGEgc3RhYmxlIGFycmF5IChyZWJ1aWx0IG9ubHkgd2hlbiBgc2FtTW9kZWxzYC9gc2FtTW9kZWxJZGAgY2hhbmdlKSxcbiAgICogIE5PVCBhIGdldHRlcjogYSBnZXR0ZXIgcmV0dXJucyBhIGZyZXNoIGFycmF5IHdpdGggbmV3IGBjb21tYW5kYCBjbG9zdXJlcyBvblxuICAgKiAgZXZlcnkgY2hhbmdlLWRldGVjdGlvbiB0aWNrLCB3aGljaCBtYWtlcyB0aGUgYm91bmQgYHAtbWVudWAgb3ZlcmxheSByZWJ1aWxkXG4gICAqICBpdHMgRE9NIG1pZC1pbnRlcmFjdGlvbiBhbmQgc3dhbGxvdyB0aGUgY2xpY2sgb24gYSBtZW51IGl0ZW0uXG4gICAqXG4gICAqICBgdG9vbHRpcGAgY2FycmllcyB0aGUgbW9kZWwncyBkZXNjcmlwdGlvbiBmcm9tIHtAbGluayBNT0RFTF9JTkZPfTsgdGhlXG4gICAqICBtZW51cycgc2hhcmVkIGl0ZW0gdGVtcGxhdGUgdHVybnMgaXQgaW50byB0aGUgaG92ZXIgaW5mbyBpY29uLiBwLW1lbnUncyBvd25cbiAgICogIHJlbmRlcmluZyBpZ25vcmVzIHRoZSBmaWVsZCAoaXQgcmVhZHMgYGl0ZW0udGl0bGVgKSwgc28gaXQgaXMgZnJlZSB0byB1c2UuICovXG4gIHByb3RlY3RlZCBzYW1NZW51SXRlbXM6IE1lbnVJdGVtW10gPSBbXTtcbiAgLyoqXG4gICAqIE1vZGVsIG1lbnVzIGZvciB0aGUgY29udHJpYnV0ZWQgdG9vbHMsIGtleWVkIGJ5IHRvb2wgaWQuIFNhbWUgc3RhYmxlLWFycmF5XG4gICAqIHJlYXNvbmluZyBhcyB7QGxpbmsgc2FtTWVudUl0ZW1zfSDigJQgYW5kIGl0IGlzIHdoeSB0aGlzIGlzIGEgbWFwIHJlYnVpbHQgaW5cbiAgICogYG5nT25DaGFuZ2VzYCByYXRoZXIgdGhhbiBhIG1ldGhvZCBjYWxsZWQgZnJvbSB0aGUgdGVtcGxhdGUsIHdoaWNoIHdvdWxkXG4gICAqIGhhbmQgYHAtbWVudWAgYSBuZXcgYXJyYXkgZXZlcnkgdGljay5cbiAgICpcbiAgICogQSBjb250cmlidXRlZCB0b29sIHN1cHBsaWVzIGl0cyBvd24gcGVyLW1vZGVsIGRlc2NyaXB0aW9uLCBzbyB1bmxpa2UgdGhlXG4gICAqIFNBTSBtZW51IHRoZXNlIGRvIG5vdCBjb25zdWx0IHtAbGluayBNT0RFTF9JTkZPfTogdGhpcyBsaWJyYXJ5IGhhcyBub1xuICAgKiBjb3B5IGZvciBjaGVja3BvaW50cyBpdCBkb2VzIG5vdCBrbm93IGFib3V0LlxuICAgKi9cbiAgcHJvdGVjdGVkIHRvb2xNZW51SXRlbXM6IFJlY29yZDxzdHJpbmcsIE1lbnVJdGVtW10+ID0ge307XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzWydzYW1Nb2RlbHMnXSB8fCBjaGFuZ2VzWydzYW1Nb2RlbElkJ10pIHtcbiAgICAgIHRoaXMuc2FtTWVudUl0ZW1zID0gdGhpcy5zYW1Nb2RlbHMubWFwKChtKSA9PiAoe1xuICAgICAgICBsYWJlbDogbS5sYWJlbCxcbiAgICAgICAgaWNvbjogbS5pZCA9PT0gdGhpcy5zYW1Nb2RlbElkID8gJ3BpIHBpLWNoZWNrJyA6ICdwaSBwaS1mdycsXG4gICAgICAgIHRvb2x0aXA6IE1PREVMX0lORk9bbS5pZF0sXG4gICAgICAgIGluZm9MYWJlbDogdGhpcy5pbmZvTGFiZWwobS5sYWJlbCwgTU9ERUxfSU5GT1ttLmlkXSksXG4gICAgICAgIGNvbW1hbmQ6ICgpID0+IHRoaXMuc2FtTW9kZWxDaGFuZ2UuZW1pdChtLmlkKSxcbiAgICAgIH0pKTtcbiAgICB9XG4gICAgaWYgKGNoYW5nZXNbJ2NvbnRyaWJ1dGVkVG9vbHMnXSB8fCBjaGFuZ2VzWyd0b29sTW9kZWxJZHMnXSkge1xuICAgICAgdGhpcy50b29sTWVudUl0ZW1zID0ge307XG4gICAgICBmb3IgKGNvbnN0IHRvb2wgb2YgdGhpcy5jb250cmlidXRlZFRvb2xzKSB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZSA9IHRoaXMudG9vbE1vZGVsSWRzW3Rvb2wuaWRdID8/IHRvb2wuZGVmYXVsdE1vZGVsSWQoKTtcbiAgICAgICAgdGhpcy50b29sTWVudUl0ZW1zW3Rvb2wuaWRdID0gdG9vbC5tb2RlbHMoKS5tYXAoKG0pID0+ICh7XG4gICAgICAgICAgbGFiZWw6IG0ubGFiZWwsXG4gICAgICAgICAgaWNvbjogbS5pZCA9PT0gYWN0aXZlID8gJ3BpIHBpLWNoZWNrJyA6ICdwaSBwaS1mdycsXG4gICAgICAgICAgdG9vbHRpcDogbS5pbmZvLFxuICAgICAgICAgIGluZm9MYWJlbDogdGhpcy5pbmZvTGFiZWwobS5sYWJlbCwgbS5pbmZvKSxcbiAgICAgICAgICBjb21tYW5kOiAoKSA9PiB0aGlzLnRvb2xNb2RlbENoYW5nZS5lbWl0KHsgdG9vbElkOiB0b29sLmlkLCBtb2RlbElkOiBtLmlkIH0pLFxuICAgICAgICB9KSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFN0cmlwIG1hcmt1cCBmcm9tIGEgbW9kZWwgZGVzY3JpcHRpb24gc28gaXQgY2FuIGJlIHJlYWQgYWxvdWQuXG4gICAqXG4gICAqIFRoZSBjb3B5IGluIE1PREVMX0lORk8gYW5kIGluIGEgY29udHJpYnV0aW9uJ3MgYFRvb2xNb2RlbE9wdGlvbi5pbmZvYCBpc1xuICAgKiB3cml0dGVuIGZvciBhIHZpc3VhbCB0b29sdGlwIHJlbmRlcmVkIHdpdGggYFtlc2NhcGVdPVwiZmFsc2VcImAsIHNvIGl0IGNhcnJpZXNcbiAgICogYDxiPmAgYW5kIGA8YnI+YC4gUGFzc2VkIHRvIGBhcmlhLWxhYmVsYCB2ZXJiYXRpbSBhIHNjcmVlbiByZWFkZXIgYW5ub3VuY2VzXG4gICAqIHRoZSB0YWdzLCBzbyB0aGV5IGFyZSByZW1vdmVkIGFuZCBgPGJyPmAgYmVjb21lcyBhIHNlbnRlbmNlIGJyZWFrLiBFbnRpdGllc1xuICAgKiB1c2VkIGluIHRoYXQgY29weSAoYCZuYnNwO2AsIGAmdGltZXM7YCwgYCZhbXA7YCkgYXJlIGRlY29kZWQgZm9yIHRoZSBzYW1lXG4gICAqIHJlYXNvbi5cbiAgICovXG4gIHByb3RlY3RlZCBwbGFpblRleHQoaHRtbDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gKGh0bWwgPz8gJycpXG4gICAgICAucmVwbGFjZSgvPGJyXFxzKlxcLz8+L2dpLCAnLiAnKVxuICAgICAgLnJlcGxhY2UoLzxbXj5dKz4vZywgJycpXG4gICAgICAucmVwbGFjZSgvJm5ic3A7L2csICcgJylcbiAgICAgIC5yZXBsYWNlKC8mdGltZXM7L2csICd4JylcbiAgICAgIC5yZXBsYWNlKC8mYW1wOy9nLCAnJicpXG4gICAgICAucmVwbGFjZSgvXFxzKy9nLCAnICcpXG4gICAgICAudHJpbSgpO1xuICB9XG5cbiAgLyoqIFRoZSBpbmZvIGJ1dHRvbidzIGBhcmlhLWxhYmVsYCAoYGluZm9MYWJlbGAgb24gYSBtZW51IGl0ZW0pLCBidWlsdCBvbmNlIHdpdGggdGhlXG4gICAqICBtZW51IHJhdGhlciB0aGFuIGJ5IGEgdGVtcGxhdGUgY2FsbCBvbiBldmVyeSBjaGVjazsgbm9uZSB3aXRob3V0IGEgZGVzY3JpcHRpb24uICovXG4gIHByaXZhdGUgaW5mb0xhYmVsKGxhYmVsOiBzdHJpbmcsIGluZm86IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIGluZm8gPyBgQWJvdXQgJHtsYWJlbH06ICR7dGhpcy5wbGFpblRleHQoaW5mbyl9YCA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKiBLZWVwcyBlYWNoIGNvbnRyaWJ1dGVkIHRvb2wncyBgcC1tZW51YCBvdmVybGF5IGFsaXZlIGFjcm9zcyBDRCB0aWNrcyDigJRcbiAgICogIHJlLWNyZWF0aW5nIGl0IG1pZC1pbnRlcmFjdGlvbiBzd2FsbG93cyB0aGUgY2xpY2sgb24gYSBtZW51IGl0ZW0uICovXG4gIHByb3RlY3RlZCB0cmFja1Rvb2xCeUlkKF9pbmRleDogbnVtYmVyLCB0b29sOiB7IGlkOiBzdHJpbmcgfSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRvb2wuaWQ7XG4gIH1cbn1cbiIsIjwhLS0gU0FNIChqaXQtdWkjOTApOiBib3gtcHJvbXB0IHNlZ21lbnQsIGludGVyYWN0aXZlIHBvaW50IHByb21wdHMsIGFuZCBhXG4gICAgIG1vZGVsIHBpY2tlci4gLS0+XG48c3BhbiBjbGFzcz1cInRvb2xiYXItc2VwYXJhdG9yXCI+PC9zcGFuPlxuPCEtLSBTQU0gY29udHJvbHMgZ3JvdXBlZDogYm94LXByb21wdCBTZWdtZW50LCB0aGVuIHRoZSBwb2ludC1wcm9tcHQgdG9vbCxcbiAgICAgdGhlbiB0aGUgbW9kZWwtcGlja2VyIGRyb3Bkb3duICh0aGUgY2hldnJvbikgd2hpY2ggZ292ZXJucyBCT1RIIHRvb2xzLlxuICAgICBGYWxscyBiYWNrIHRvIFNlZ21lbnQgKyBwb2ludCB3aXRoIG5vIG1vZGVsIHBpY2tlciB3aGVuIG5vbmUgYXJlIHNldC4gLS0+XG48c3BhbiAqbmdJZj1cInNhbU1vZGVscy5sZW5ndGg7IGVsc2Ugc2VnbWVudFBsYWluXCIgY2xhc3M9XCJwLWJ1dHRvbnNldCBzZWdtZW50LXNwbGl0XCI+XG4gIDxwLWJ1dHRvblxuICAgIHNpemU9XCJzbWFsbFwiXG4gICAgW3RleHRdPVwidHJ1ZVwiXG4gICAgYXJpYUxhYmVsPVwiU2VnbWVudCB3aXRoIFNBTSAoYm94IHByb21wdClcIlxuICAgIHBUb29sdGlwPVwiU2VnbWVudCB0aGUgZHJhd24gcmVjdGFuZ2xlcyB3aXRoIFNBTSAoYm94IHByb21wdClcIlxuICAgIHRvb2x0aXBQb3NpdGlvbj1cImJvdHRvbVwiXG4gICAgKG9uQ2xpY2spPVwic2VnbWVudFJlZ2lvbnMuZW1pdCgpXCJcbiAgPlxuICAgIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3NhbS1ib3gtcHJvbXB0LnN2Z1wiIGNsYXNzPVwidG9vbGJhci1pY29uLWRhcmtcIiBzdHlsZT1cIndpZHRoOiAxcmVtXCIgLz5cbiAgPC9wLWJ1dHRvbj5cbiAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJzYW1Qb2ludEJ0blwiPjwvbmctY29udGFpbmVyPlxuICA8cC1idXR0b25cbiAgICBpY29uPVwicGkgcGktY2hldnJvbi1kb3duXCJcbiAgICBzaXplPVwic21hbGxcIlxuICAgIFt0ZXh0XT1cInRydWVcIlxuICAgIGFyaWFMYWJlbD1cIlBpY2sgdGhlIFNBTSBtb2RlbFwiXG4gICAgcFRvb2x0aXA9XCJQaWNrIHRoZSBTQU0gbW9kZWwgKHVzZWQgYnkgYm90aCBzZWdtZW50IHRvb2xzKVwiXG4gICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICAob25DbGljayk9XCJzYW1Nb2RlbE1lbnUudG9nZ2xlKCRldmVudClcIlxuICA+XG4gIDwvcC1idXR0b24+XG48L3NwYW4+XG48bmctdGVtcGxhdGUgI3NlZ21lbnRQbGFpbj5cbiAgPHNwYW4gY2xhc3M9XCJwLWJ1dHRvbnNldCBzZWdtZW50LXNwbGl0XCI+XG4gICAgPHAtYnV0dG9uXG4gICAgICBzaXplPVwic21hbGxcIlxuICAgICAgW3RleHRdPVwidHJ1ZVwiXG4gICAgICBhcmlhTGFiZWw9XCJTZWdtZW50IHdpdGggU0FNIChib3ggcHJvbXB0KVwiXG4gICAgICBwVG9vbHRpcD1cIlNlZ21lbnQgdGhlIGRyYXduIHJlY3RhbmdsZXMgd2l0aCBTQU0gKGJveCBwcm9tcHQpXCJcbiAgICAgIHRvb2x0aXBQb3NpdGlvbj1cImJvdHRvbVwiXG4gICAgICAob25DbGljayk9XCJzZWdtZW50UmVnaW9ucy5lbWl0KClcIlxuICAgID5cbiAgICAgIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL3NhbS1ib3gtcHJvbXB0LnN2Z1wiIGNsYXNzPVwidG9vbGJhci1pY29uLWRhcmtcIiBzdHlsZT1cIndpZHRoOiAxcmVtXCIgLz5cbiAgICA8L3AtYnV0dG9uPlxuICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwic2FtUG9pbnRCdG5cIj48L25nLWNvbnRhaW5lcj5cbiAgPC9zcGFuPlxuPC9uZy10ZW1wbGF0ZT5cbjwhLS0gUG9pbnQtcHJvbXB0IHRvb2wg4oCUIHNoYXJlZCBiZXR3ZWVuIHRoZSBtb2RlbHMgLyBuby1tb2RlbHMgbGF5b3V0cyBzbyBpdFxuICAgICBhbHdheXMgc2l0cyBqdXN0IGxlZnQgb2YgdGhlIG1vZGVsIGRyb3Bkb3duLiAtLT5cbjxuZy10ZW1wbGF0ZSAjc2FtUG9pbnRCdG4+XG4gIDxwLWJ1dHRvblxuICAgIHNpemU9XCJzbWFsbFwiXG4gICAgYXJpYUxhYmVsPVwiU0FNIHBvaW50IHByb21wdHNcIlxuICAgIFt0ZXh0XT1cImFjdGl2ZURyYWdNb2RlICE9PSAnc2FtUG9pbnQnXCJcbiAgICBwVG9vbHRpcD1cIlNBTSBwb2ludCBwcm9tcHRzOiBjbGljayBhIGZpYmVyIHRvIHNlZ21lbnQgaXQgYXMgYSBuZXcgcmVnaW9uO1xuICAgICAgICAgICAgU2hpZnQvQWx0LWNsaWNrIHRvIHJlZmluZSAoZXhjbHVkZSkgdGhlIGN1cnJlbnQgb25lLjxicj5Fc2MgdW5kb2VzIGl0LlwiXG4gICAgW2VzY2FwZV09XCJmYWxzZVwiXG4gICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICAob25DbGljayk9XCJ0b2dnbGVEcmFnTW9kZS5lbWl0KCdzYW1Qb2ludCcpXCJcbiAgPlxuICAgIDxpbWdcbiAgICAgIHNyYz1cImFzc2V0cy9wbG90dGluZy9zYW0tcG9pbnQtcHJvbXB0LnN2Z1wiXG4gICAgICBbY2xhc3NdPVwiYWN0aXZlRHJhZ01vZGUgPT09ICdzYW1Qb2ludCcgPyAndG9vbGJhci1pY29uLWFjdGl2ZScgOiAndG9vbGJhci1pY29uLWRhcmsnXCJcbiAgICAgIHN0eWxlPVwid2lkdGg6IDFyZW1cIlxuICAgIC8+XG4gIDwvcC1idXR0b24+XG48L25nLXRlbXBsYXRlPlxuPHAtbWVudSAjc2FtTW9kZWxNZW51IHN0eWxlQ2xhc3M9XCJtb2RlbC1tZW51XCIgW21vZGVsXT1cInNhbU1lbnVJdGVtc1wiIFtwb3B1cF09XCJ0cnVlXCIgYXBwZW5kVG89XCJib2R5XCI+XG4gIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJpdGVtXCIgbGV0LWl0ZW0+XG4gICAgPG5nLWNvbnRhaW5lclxuICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwibW9kZWxNZW51SXRlbVwiXG4gICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IGl0ZW0gfVwiXG4gICAgPjwvbmctY29udGFpbmVyPlxuICA8L25nLXRlbXBsYXRlPlxuPC9wLW1lbnU+XG5cbjwhLS0gU2hhcmVkIGl0ZW0gYm9keSBmb3IgYWxsIHRocmVlIG1vZGVsIHBpY2tlcnMgKFNBTSAvIFlPTE8gLyByZXRpbmFsKTpcbiAgICAgdGhlIHN0YW5kYXJkIGNoZWNrLW9yLWJsYW5rIGljb24gYW5kIGxhYmVsLCBwbHVzIGFuIGluZm8gaWNvbiBjYXJyeWluZ1xuICAgICB0aGUgbW9kZWwncyBkZXNjcmlwdGlvbiBhcyBhIGhvdmVyIHRvb2x0aXAuIFRoaXMgcmVwbGFjZWQgYSBzaW5nbGVcbiAgICAgXCJBYm91dCB0aGUgU0FNIG1vZGVsc1wiIG92ZXJsYXkgcGFuZWwg4oCUIHBlci1tb2RlbCB0ZXh0IHNpdHMgbmV4dCB0byB0aGVcbiAgICAgbW9kZWwgaXQgZGVzY3JpYmVzLCBhbmQgWU9MTy9yZXRpbmFsIGdldCB0aGUgc2FtZSBhZmZvcmRhbmNlLlxuXG4gICAgIHAtbWVudSBwdXRzIGl0cyBjbGljayBoYW5kbGVyIG9uIHRoZSB3cmFwcGluZyBgLnAtbWVudWl0ZW0tY29udGVudGAsXG4gICAgIG91dHNpZGUgdGhpcyB0ZW1wbGF0ZSwgc28gYGNvbW1hbmRgIHN0aWxsIGZpcmVzIGFuZCB0aGUgd2hvbGUgcm93IHN0YXlzXG4gICAgIGNsaWNrYWJsZSDigJQgd2hpY2ggaXMgYWxzbyB3aHkgdGhlIGluZm8gaWNvbiBoYXMgdG8gc3RvcCBwcm9wYWdhdGlvbiwgb3JcbiAgICAgcmVhZGluZyBhYm91dCBhIG1vZGVsIHdvdWxkIHN3aXRjaCB0byBpdC4gLS0+XG48bmctdGVtcGxhdGUgI21vZGVsTWVudUl0ZW0gbGV0LWl0ZW0+XG4gIDxhIGNsYXNzPVwicC1tZW51aXRlbS1saW5rIG1vZGVsLW1lbnUtaXRlbVwiPlxuICAgIDxzcGFuIGNsYXNzPVwicC1tZW51aXRlbS1pY29uXCIgW25nQ2xhc3NdPVwiaXRlbS5pY29uXCI+PC9zcGFuPlxuICAgIDxzcGFuIGNsYXNzPVwicC1tZW51aXRlbS10ZXh0XCI+e3sgaXRlbS5sYWJlbCB9fTwvc3Bhbj5cbiAgICA8IS0tIGBib3R0b21gIGxpa2UgZXZlcnkgb3RoZXIgdG9vbHRpcCBpbiB0aGlzIHRvb2xiYXIsIGFuZCBmb3Igcm9vbTpcbiAgICAgICAgIHRoZXNlIG1lbnVzIG9wZW4gdW5kZXIgYnV0dG9ucyB0aGF0IGNhbiBzaXQgbmVhciB0aGUgcmlnaHQgZWRnZSxcbiAgICAgICAgIHdoZXJlIGEgYHJpZ2h0YCB0b29sdGlwIGhhcyBhIGZldyBodW5kcmVkIHB4IGFuZCBzcXVlZXplcyBpdHMgdGV4dFxuICAgICAgICAgaW50byBhIG5hcnJvdyBjb2x1bW4gaW5zdGVhZCBvZiB1c2luZyBpdHMgbWF4LXdpZHRoLiAtLT5cbiAgICA8IS0tIEEgZm9jdXNhYmxlIDxidXR0b24+LCBub3QgYSBiYXJlIDxpPi4gQXMgYW4gPGk+IHRoZSBkZXNjcmlwdGlvblxuICAgICAgICAgd2FzIHJlYWNoYWJsZSBvbmx5IGJ5IGhvdmVyaW5nIGEgbW91c2U6IG5vdCB0YWJiYWJsZSwgbm9cbiAgICAgICAgIGFjY2Vzc2libGUgbmFtZSwgbm90aGluZyBmb3IgYSBzY3JlZW4gcmVhZGVyIHRvIGFubm91bmNlIOKAlCBzb1xuICAgICAgICAga2V5Ym9hcmQgYW5kIEFUIHVzZXJzIGNvdWxkIHBpY2sgYSBjaGVja3BvaW50IGJ1dCBuZXZlciByZWFkIHdoYXRcbiAgICAgICAgIGl0IHdhcy4gUHJpbWVORydzIHRvb2x0aXAgc2hvd3Mgb24gZm9jdXMgYXMgd2VsbCBhcyBob3Zlciwgc29cbiAgICAgICAgIG1ha2luZyBpdCBhIGJ1dHRvbiByZXN0b3JlcyBpdCBmb3IgZnJlZS5cblxuICAgICAgICAgYGFyaWEtZGVzY3JpYmVkYnlgIGlzIGRlbGliZXJhdGVseSBub3QgdXNlZDogdGhlIHRvb2x0aXAgaXNcbiAgICAgICAgIHJlbmRlcmVkIGludG8gYGJvZHlgIG9uIGRlbWFuZCBhbmQgaGFzIG5vIHN0YWJsZSBpZCB0byBwb2ludCBhdC5cbiAgICAgICAgIFRoZSBkZXNjcmlwdGlvbiBpcyBjYXJyaWVkIG9uIGBhcmlhLWxhYmVsYCBpbnN0ZWFkLCB3aGljaCBpc1xuICAgICAgICAgYW5ub3VuY2VkIHdoZXRoZXIgb3Igbm90IHRoZSB0b29sdGlwIGlzIHNob3dpbmcuIEl0IGlzIHN0cmlwcGVkIG9mXG4gICAgICAgICBtYXJrdXAgZmlyc3QsIHNpbmNlIHRoZSBjb3B5IGNvbnRhaW5zIGA8Yj5gL2A8YnI+YCBmb3IgdGhlIHZpc3VhbFxuICAgICAgICAgdG9vbHRpcCBhbmQgdGhvc2Ugd291bGQgb3RoZXJ3aXNlIGJlIHJlYWQgb3V0IGxpdGVyYWxseS4gLS0+XG4gICAgPGJ1dHRvblxuICAgICAgKm5nSWY9XCJpdGVtLnRvb2x0aXBcIlxuICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICBjbGFzcz1cInBpIHBpLWluZm8tY2lyY2xlIG1vZGVsLWluZm8taWNvblwiXG4gICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIml0ZW0uaW5mb0xhYmVsXCJcbiAgICAgIFtwVG9vbHRpcF09XCJpdGVtLnRvb2x0aXBcIlxuICAgICAgW2VzY2FwZV09XCJmYWxzZVwiXG4gICAgICB0b29sdGlwUG9zaXRpb249XCJib3R0b21cIlxuICAgICAgYXBwZW5kVG89XCJib2R5XCJcbiAgICAgIHRvb2x0aXBTdHlsZUNsYXNzPVwibW9kZWwtaW5mby10b29sdGlwXCJcbiAgICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgKGtleWRvd24uZW50ZXIpPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcbiAgICAgIChrZXlkb3duLnNwYWNlKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgPjwvYnV0dG9uPlxuICA8L2E+XG48L25nLXRlbXBsYXRlPlxuPHAtYnV0dG9uXG4gIHNpemU9XCJzbWFsbFwiXG4gIFt0ZXh0XT1cInRydWVcIlxuICBhcmlhTGFiZWw9XCJTZWdtZW50IGNlbGxzIChjZWxscG9zZS1TQU0pXCJcbiAgcFRvb2x0aXA9XCJBdXRvLXNlZ21lbnQgY2VsbHMgaW5zaWRlIGVhY2ggZHJhd24gcmVjdGFuZ2xlIChjZWxscG9zZS1TQU0pXCJcbiAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgKG9uQ2xpY2spPVwic2VnbWVudENlbGxwb3NlLmVtaXQoKVwiXG4+XG4gIDxpbWcgc3JjPVwiYXNzZXRzL3Bsb3R0aW5nL2NlbGxzLnN2Z1wiIGNsYXNzPVwidG9vbGJhci1pY29uLWRhcmtcIiBzdHlsZT1cIndpZHRoOiAxcmVtXCIgLz5cbjwvcC1idXR0b24+XG5cbjwhLS0gQ29udHJpYnV0ZWQgbm8tcHJvbXB0IHRvb2xzIChUT09MQkFSX1RPT0xTKS4gVW5saWtlIHRoZSBTQU0gYW5kXG4gICAgIGNlbGxwb3NlIHRvb2xzIHRoZXNlIHRha2Ugbm8gcHJvbXB0IOKAlCB0aGV5IHN3ZWVwIHRoZSB3aG9sZSBjdXJyZW50XG4gICAgIHZpZXcgcmF0aGVyIHRoYW4gYmVpbmcgcG9pbnRlZCBhdCBzb21ldGhpbmcg4oCUIHNvIHRoZXJlIGlzIG5vdGhpbmcgdG9cbiAgICAgZHJhdyBmaXJzdC4gRWFjaCByZW5kZXJzIHRoZSBzYW1lIHNwbGl0IGJ1dHRvbjogcnVuLCBwaWNrIGNoZWNrcG9pbnQsXG4gICAgIG9wZW4gcGFyYW1ldGVycy5cblxuICAgICBOb3RoaW5nIGhlcmUgbmFtZXMgYSBzcGVjaWZpYyB0b29sLiBUaGUgbGlicmFyeSBzaGlwcyBub25lOyBhIGhvc3RcbiAgICAgcmVnaXN0ZXJzIHRoZW0sIHdoaWNoIGlzIHdoYXQgbGV0cyB0aGlzIHBhY2thZ2UgYmUgcHVibGlzaGVkIHdpdGhvdXRcbiAgICAgdGhlIGNsb3NlZCBtb2RlbCBkZXBlbmRlbmNpZXMuIC0tPlxuPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgdG9vbCBvZiBjb250cmlidXRlZFRvb2xzOyB0cmFja0J5OiB0cmFja1Rvb2xCeUlkXCI+XG4gIDxzcGFuIGNsYXNzPVwicC1idXR0b25zZXQgc2VnbWVudC1zcGxpdFwiPlxuICAgIDxwLWJ1dHRvblxuICAgICAgc2l6ZT1cInNtYWxsXCJcbiAgICAgIFt0ZXh0XT1cInRydWVcIlxuICAgICAgW2FyaWFMYWJlbF09XCJ0b29sLmxhYmVsXCJcbiAgICAgIFtwVG9vbHRpcF09XCJ0b29sLnJ1blRvb2x0aXBcIlxuICAgICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICAgIChvbkNsaWNrKT1cInJ1blRvb2wuZW1pdCh0b29sLmlkKVwiXG4gICAgPlxuICAgICAgPCEtLSBgdG9vbGJhci1pY29uLWRhcmtgIGlzIGhhcmRjb2RlZCByYXRoZXIgdGhhbiBib3VuZCwgdW5saWtlIHRoZVxuICAgICAgICAgICB0b2dnbGUgdG9vbHM6IHRoZXNlIGZpcmUgYSBydW4gYW5kIGhhdmUgbm8gYWN0aXZlIHN0YXRlLiAtLT5cbiAgICAgIDxpbWdcbiAgICAgICAgKm5nSWY9XCJ0b29sLmljb24uc3JjXCJcbiAgICAgICAgW3NyY109XCJ0b29sLmljb24uc3JjXCJcbiAgICAgICAgY2xhc3M9XCJ0b29sYmFyLWljb24tZGFya1wiXG4gICAgICAgIHN0eWxlPVwid2lkdGg6IDFyZW1cIlxuICAgICAgICBbYWx0XT1cInRvb2wubGFiZWxcIlxuICAgICAgLz5cbiAgICAgIDxpICpuZ0lmPVwidG9vbC5pY29uLnBpXCIgY2xhc3M9XCJwaSB7eyB0b29sLmljb24ucGkgfX1cIj48L2k+XG4gICAgPC9wLWJ1dHRvbj5cbiAgICA8cC1idXR0b25cbiAgICAgIGljb249XCJwaSBwaS1jaGV2cm9uLWRvd25cIlxuICAgICAgc2l6ZT1cInNtYWxsXCJcbiAgICAgIFt0ZXh0XT1cInRydWVcIlxuICAgICAgW2FyaWFMYWJlbF09XCInUGljayB0aGUgbW9kZWwgZm9yICcgKyB0b29sLmxhYmVsXCJcbiAgICAgIFtwVG9vbHRpcF09XCJ0b29sLm1vZGVsVG9vbHRpcCB8fCAnUGljayB0aGUgbW9kZWwnXCJcbiAgICAgIHRvb2x0aXBQb3NpdGlvbj1cImJvdHRvbVwiXG4gICAgICAob25DbGljayk9XCJ0b29sTWVudS50b2dnbGUoJGV2ZW50KVwiXG4gICAgPlxuICAgIDwvcC1idXR0b24+XG4gICAgPHAtYnV0dG9uXG4gICAgICAqbmdJZj1cInRvb2wucGFyYW1zLmxlbmd0aFwiXG4gICAgICBpY29uPVwicGkgcGktc2xpZGVycy1oXCJcbiAgICAgIHNpemU9XCJzbWFsbFwiXG4gICAgICBbdGV4dF09XCJ0cnVlXCJcbiAgICAgIFthcmlhTGFiZWxdPVwiJ1BhcmFtZXRlcnMgZm9yICcgKyB0b29sLmxhYmVsXCJcbiAgICAgIFtwVG9vbHRpcF09XCJ0b29sLnBhcmFtc1Rvb2x0aXAgfHwgJ1BhcmFtZXRlcnMnXCJcbiAgICAgIHRvb2x0aXBQb3NpdGlvbj1cImJvdHRvbVwiXG4gICAgICAob25DbGljayk9XCJvcGVuVG9vbFBhcmFtcy5lbWl0KHRvb2wuaWQpXCJcbiAgICA+XG4gICAgPC9wLWJ1dHRvbj5cbiAgPC9zcGFuPlxuICA8cC1tZW51ICN0b29sTWVudSBzdHlsZUNsYXNzPVwibW9kZWwtbWVudVwiIFttb2RlbF09XCJ0b29sTWVudUl0ZW1zW3Rvb2wuaWRdIHx8IFtdXCIgW3BvcHVwXT1cInRydWVcIiBhcHBlbmRUbz1cImJvZHlcIj5cbiAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiaXRlbVwiIGxldC1pdGVtPlxuICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJtb2RlbE1lbnVJdGVtXCJcbiAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiBpdGVtIH1cIlxuICAgICAgPjwvbmctY29udGFpbmVyPlxuICAgIDwvbmctdGVtcGxhdGU+XG4gIDwvcC1tZW51PlxuPC9uZy1jb250YWluZXI+XG4iXX0=
@@ -0,0 +1,121 @@
1
+ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { ButtonModule } from 'primeng/button';
5
+ import { SliderModule } from 'primeng/slider';
6
+ import { TooltipModule } from 'primeng/tooltip';
7
+ import * as i0 from "@angular/core";
8
+ import * as i1 from "@angular/common";
9
+ import * as i2 from "@angular/forms";
10
+ import * as i3 from "primeng/button";
11
+ import * as i4 from "primeng/slider";
12
+ import * as i5 from "primeng/tooltip";
13
+ /**
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`.
17
+ */
18
+ export class StackControlsComponent {
19
+ constructor() {
20
+ /** Show the live slice scrubber. */
21
+ this.liveScrubber = false;
22
+ /** Show the single-image / stack toggle (Plotly heatmap). */
23
+ this.stackToggle = false;
24
+ /** Stack mode is on (the toggle's state). */
25
+ this.showStack = false;
26
+ /** The two stack-mode choices of the toggle. */
27
+ this.stackOptions = [
28
+ { name: 'Single image', val: 'false' },
29
+ { name: 'Stack', val: 'true' },
30
+ ];
31
+ /** The current slice (0-based). */
32
+ this.zIndex = 0;
33
+ /** The last slice index. */
34
+ this.maxIndex = 0;
35
+ /** The live scrubber moved (fires while dragging). */
36
+ this.zScrub = new EventEmitter();
37
+ /** The live scrubber was released on a slice. */
38
+ this.zSlide = new EventEmitter();
39
+ /** A stack-mode choice was picked. */
40
+ this.selectStackOption = new EventEmitter();
41
+ /** The heatmap's slice bar moved to a slice (the host shows its number). */
42
+ this.zIndexInput = new EventEmitter();
43
+ /** The heatmap's slice bar settled: re-plot at that slice. */
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;
48
+ }
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();
91
+ }
92
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: StackControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
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 }); }
94
+ }
95
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: StackControlsComponent, decorators: [{
96
+ type: Component,
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"] }]
98
+ }], propDecorators: { liveScrubber: [{
99
+ type: Input
100
+ }], stackToggle: [{
101
+ type: Input
102
+ }], showStack: [{
103
+ type: Input
104
+ }], stackOptions: [{
105
+ type: Input
106
+ }], zIndex: [{
107
+ type: Input
108
+ }], maxIndex: [{
109
+ type: Input
110
+ }], zScrub: [{
111
+ type: Output
112
+ }], zSlide: [{
113
+ type: Output
114
+ }], selectStackOption: [{
115
+ type: Output
116
+ }], zIndexInput: [{
117
+ type: Output
118
+ }], reloadAndPlot: [{
119
+ type: Output
120
+ }] } });
121
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stY29udHJvbHMuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi90b29sYmFyL3N0YWNrLWNvbnRyb2xzL3N0YWNrLWNvbnRyb2xzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci9zdGFjay1jb250cm9scy9zdGFjay1jb250cm9scy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQWEsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNHLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7Ozs7Ozs7QUFRaEQ7Ozs7R0FJRztBQVNILE1BQU0sT0FBTyxzQkFBc0I7SUFSbkM7UUFTRSxvQ0FBb0M7UUFDM0IsaUJBQVksR0FBRyxLQUFLLENBQUM7UUFDOUIsNkRBQTZEO1FBQ3BELGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBQzdCLDZDQUE2QztRQUNwQyxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBQzNCLGdEQUFnRDtRQUN2QyxpQkFBWSxHQUFrQjtZQUNyQyxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRTtZQUN0QyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRTtTQUMvQixDQUFDO1FBQ0YsbUNBQW1DO1FBQzFCLFdBQU0sR0FBRyxDQUFDLENBQUM7UUFDcEIsNEJBQTRCO1FBQ25CLGFBQVEsR0FBRyxDQUFDLENBQUM7UUFFdEIsc0RBQXNEO1FBQzVDLFdBQU0sR0FBRyxJQUFJLFlBQVksRUFBc0IsQ0FBQztRQUMxRCxpREFBaUQ7UUFDdkMsV0FBTSxHQUFHLElBQUksWUFBWSxFQUFzQixDQUFDO1FBQzFELHNDQUFzQztRQUM1QixzQkFBaUIsR0FBRyxJQUFJLFlBQVksRUFBZSxDQUFDO1FBQzlELDRFQUE0RTtRQUNsRSxnQkFBVyxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFDbkQsOERBQThEO1FBQ3BELGtCQUFhLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztRQUtuRCxvRkFBb0Y7UUFDMUUsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUNuQixXQUFNLEdBQXlDLElBQUksQ0FBQztLQTJDN0Q7SUFoREMsb0ZBQW9GO2FBQ3BFLG9CQUFlLEdBQUcsR0FBRyxBQUFOLENBQU87SUFNdEMsa0ZBQWtGO0lBQ2xGLElBQWMsV0FBVztRQUN2QixPQUFPLElBQUksQ0FBQyxXQUFXLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQzdDLENBQUM7SUFFRCwrR0FBK0c7SUFDckcsYUFBYSxDQUFDLENBQXFCO1FBQzNDLElBQUksQ0FBQyxLQUFLLFNBQVM7WUFBRSxPQUFPO1FBQzVCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3RCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3BCLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDekIsSUFBSSxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU87UUFDMUIsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUM1QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztZQUNuQixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzVCLENBQUMsRUFBRSxzQkFBc0IsQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQsa0VBQWtFO0lBQ3hELFVBQVUsQ0FBQyxDQUFxQjtRQUN4QyxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztRQUN0QixJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN0QixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNwQixPQUFPO1FBQ1QsQ0FBQztRQUNELElBQUksQ0FBQyxLQUFLLFNBQVM7WUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBRU8sWUFBWTtRQUNsQixJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssSUFBSTtZQUFFLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDcEQsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7SUFDckIsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDdEIsQ0FBQzs4R0EzRVUsc0JBQXNCO2tHQUF0QixzQkFBc0IsMllDMUJuQyw2NkRBOENBLHdlRHpCWSxZQUFZLGtJQUFFLFdBQVcsOFZBQUUsWUFBWSw2WEFBRSxZQUFZLCtSQUFFLGFBQWE7OzJGQUtuRSxzQkFBc0I7a0JBUmxDLFNBQVM7K0JBQ0Usd0JBQXdCLGNBQ3RCLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxhQUFhLENBQUMsbUJBRzlELHVCQUF1QixDQUFDLE1BQU07OEJBSXRDLFlBQVk7c0JBQXBCLEtBQUs7Z0JBRUcsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBS0csTUFBTTtzQkFBZCxLQUFLO2dCQUVHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBR0ksTUFBTTtzQkFBZixNQUFNO2dCQUVHLE1BQU07c0JBQWYsTUFBTTtnQkFFRyxpQkFBaUI7c0JBQTFCLE1BQU07Z0JBRUcsV0FBVztzQkFBcEIsTUFBTTtnQkFFRyxhQUFhO3NCQUF0QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25EZXN0cm95LCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEJ1dHRvbk1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvYnV0dG9uJztcbmltcG9ydCB7IFNsaWRlck1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvc2xpZGVyJztcbmltcG9ydCB7IFRvb2x0aXBNb2R1bGUgfSBmcm9tICdwcmltZW5nL3Rvb2x0aXAnO1xuXG4vKiogQSBzdGFjay1tb2RlIGNob2ljZSAoYHZhbGAgJ2ZhbHNlJyA9IHNpbmdsZSBpbWFnZSwgJ3RydWUnID0gc3RhY2spLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdGFja09wdGlvbiB7XG4gIG5hbWU6IHN0cmluZztcbiAgdmFsOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIHRvb2xiYXIncyB6LXN0YWNrIGdyb3VwOiB0aGUgc2xpY2UgYmFyLCBhbmQgKFBsb3RseSBoZWF0bWFwKSB0aGUgc2luZ2xlLWltYWdlIC8gc3RhY2tcbiAqIHRvZ2dsZS4gVGhlIHZpZXdzIHRoYXQgc3dhcCBzbGljZXMgaW4gcGxhY2UgZm9sbG93IHRoZSBiYXIgYXMgaXQgbW92ZXM7IHRoZSBoZWF0bWFwJ3Mgc2luZ2xlXG4gKiBpbWFnZSBpcyByZS1wbG90dGVkIGF0IHRoZSBzbGljZSBpdCBzZXR0bGVzIG9uLiBQcmVzZW50YXRpb25hbDogdGhlIGhvc3Qgb3ducyBgekluZGV4YC5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9vbGJhci1zdGFjay1jb250cm9scycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIEZvcm1zTW9kdWxlLCBCdXR0b25Nb2R1bGUsIFNsaWRlck1vZHVsZSwgVG9vbHRpcE1vZHVsZV0sXG4gIHRlbXBsYXRlVXJsOiAnLi9zdGFjay1jb250cm9scy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3N0YWNrLWNvbnRyb2xzLmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBTdGFja0NvbnRyb2xzQ29tcG9uZW50IGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgLyoqIFNob3cgdGhlIGxpdmUgc2xpY2Ugc2NydWJiZXIuICovXG4gIEBJbnB1dCgpIGxpdmVTY3J1YmJlciA9IGZhbHNlO1xuICAvKiogU2hvdyB0aGUgc2luZ2xlLWltYWdlIC8gc3RhY2sgdG9nZ2xlIChQbG90bHkgaGVhdG1hcCkuICovXG4gIEBJbnB1dCgpIHN0YWNrVG9nZ2xlID0gZmFsc2U7XG4gIC8qKiBTdGFjayBtb2RlIGlzIG9uICh0aGUgdG9nZ2xlJ3Mgc3RhdGUpLiAqL1xuICBASW5wdXQoKSBzaG93U3RhY2sgPSBmYWxzZTtcbiAgLyoqIFRoZSB0d28gc3RhY2stbW9kZSBjaG9pY2VzIG9mIHRoZSB0b2dnbGUuICovXG4gIEBJbnB1dCgpIHN0YWNrT3B0aW9uczogU3RhY2tPcHRpb25bXSA9IFtcbiAgICB7IG5hbWU6ICdTaW5nbGUgaW1hZ2UnLCB2YWw6ICdmYWxzZScgfSxcbiAgICB7IG5hbWU6ICdTdGFjaycsIHZhbDogJ3RydWUnIH0sXG4gIF07XG4gIC8qKiBUaGUgY3VycmVudCBzbGljZSAoMC1iYXNlZCkuICovXG4gIEBJbnB1dCgpIHpJbmRleCA9IDA7XG4gIC8qKiBUaGUgbGFzdCBzbGljZSBpbmRleC4gKi9cbiAgQElucHV0KCkgbWF4SW5kZXggPSAwO1xuXG4gIC8qKiBUaGUgbGl2ZSBzY3J1YmJlciBtb3ZlZCAoZmlyZXMgd2hpbGUgZHJhZ2dpbmcpLiAqL1xuICBAT3V0cHV0KCkgelNjcnViID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXIgfCB1bmRlZmluZWQ+KCk7XG4gIC8qKiBUaGUgbGl2ZSBzY3J1YmJlciB3YXMgcmVsZWFzZWQgb24gYSBzbGljZS4gKi9cbiAgQE91dHB1dCgpIHpTbGlkZSA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyIHwgdW5kZWZpbmVkPigpO1xuICAvKiogQSBzdGFjay1tb2RlIGNob2ljZSB3YXMgcGlja2VkLiAqL1xuICBAT3V0cHV0KCkgc2VsZWN0U3RhY2tPcHRpb24gPSBuZXcgRXZlbnRFbWl0dGVyPFN0YWNrT3B0aW9uPigpO1xuICAvKiogVGhlIGhlYXRtYXAncyBzbGljZSBiYXIgbW92ZWQgdG8gYSBzbGljZSAodGhlIGhvc3Qgc2hvd3MgaXRzIG51bWJlcikuICovXG4gIEBPdXRwdXQoKSB6SW5kZXhJbnB1dCA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xuICAvKiogVGhlIGhlYXRtYXAncyBzbGljZSBiYXIgc2V0dGxlZDogcmUtcGxvdCBhdCB0aGF0IHNsaWNlLiAqL1xuICBAT3V0cHV0KCkgcmVsb2FkQW5kUGxvdCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAvKiogSG93IGxvbmcga2V5IHN0ZXBzIG9uIHRoZSBoZWF0bWFwJ3MgYmFyIHBhdXNlIGJlZm9yZSB0aGUgc2xpY2UgaXMgcmUtcGxvdHRlZC4gKi9cbiAgc3RhdGljIHJlYWRvbmx5IFJFUExPVF9ERUxBWV9NUyA9IDQwMDtcblxuICAvKiogQSBkcmFnIG9mIHRoZSBiYXIgaXMgdW5kZXIgd2F5IChpdHMgZW5kIHJlLXBsb3RzIHRoZSBoZWF0bWFwLCBub3QgZWFjaCBzdGVwKS4gKi9cbiAgcHJvdGVjdGVkIGRyYWdnaW5nID0gZmFsc2U7XG4gIHByaXZhdGUgcmVwbG90OiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBUaGUgaGVhdG1hcCBpbiBzaW5nbGUtaW1hZ2UgbW9kZTogaXRzIGJhciByZS1wbG90cyB0aGUgc2xpY2UgaXQgc2V0dGxlcyBvbi4gKi9cbiAgcHJvdGVjdGVkIGdldCBzaW5nbGVJbWFnZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zdGFja1RvZ2dsZSAmJiAhdGhpcy5zaG93U3RhY2s7XG4gIH1cblxuICAvKiogVGhlIGJhciBtb3ZlZDogYSBsaXZlIHZpZXcgZm9sbG93cyBpdDsgdGhlIGhlYXRtYXAgc2hvd3MgdGhlIG51bWJlciwgYW5kIHJlLXBsb3RzIGFmdGVyIGtleSBzdGVwcyBwYXVzZS4gKi9cbiAgcHJvdGVjdGVkIG9uU2xpY2VDaGFuZ2UoejogbnVtYmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgaWYgKHogPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICAgIGlmICh0aGlzLmxpdmVTY3J1YmJlcikge1xuICAgICAgdGhpcy56U2NydWIuZW1pdCh6KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy56SW5kZXhJbnB1dC5lbWl0KHopO1xuICAgIGlmICh0aGlzLmRyYWdnaW5nKSByZXR1cm47XG4gICAgdGhpcy5jYW5jZWxSZXBsb3QoKTtcbiAgICB0aGlzLnJlcGxvdCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5yZXBsb3QgPSBudWxsO1xuICAgICAgdGhpcy5yZWxvYWRBbmRQbG90LmVtaXQoKTtcbiAgICB9LCBTdGFja0NvbnRyb2xzQ29tcG9uZW50LlJFUExPVF9ERUxBWV9NUyk7XG4gIH1cblxuICAvKiogVGhlIGJhciB3YXMgbGV0IGdvIChhIGRyYWcncyBlbmQsIG9yIGEgY2xpY2sgb24gaXRzIHRyYWNrKS4gKi9cbiAgcHJvdGVjdGVkIG9uU2xpY2VFbmQoejogbnVtYmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgdGhpcy5kcmFnZ2luZyA9IGZhbHNlO1xuICAgIGlmICh0aGlzLmxpdmVTY3J1YmJlcikge1xuICAgICAgdGhpcy56U2xpZGUuZW1pdCh6KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHogIT09IHVuZGVmaW5lZCkgdGhpcy56SW5kZXhJbnB1dC5lbWl0KHopO1xuICAgIHRoaXMuY2FuY2VsUmVwbG90KCk7XG4gICAgdGhpcy5yZWxvYWRBbmRQbG90LmVtaXQoKTtcbiAgfVxuXG4gIHByaXZhdGUgY2FuY2VsUmVwbG90KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnJlcGxvdCAhPT0gbnVsbCkgY2xlYXJUaW1lb3V0KHRoaXMucmVwbG90KTtcbiAgICB0aGlzLnJlcGxvdCA9IG51bGw7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmNhbmNlbFJlcGxvdCgpO1xuICB9XG59XG4iLCI8c3BhbiBjbGFzcz1cInRvb2xiYXItc2VwYXJhdG9yXCI+PC9zcGFuPlxuPCEtLSBIZWF0bWFwIHZpZXc6IHNpbmdsZS1pbWFnZSAoaGlnaC1kZWYgem9vbSkgdnMgc3RhY2sgKGZyYW1lIHNsaWRlcikuIFBsb3RseS1vbmx5IOKAlFxuICAgICBoaWRkZW4gZm9yIG5hcGFyaSwgd2hpY2ggaGFzIG5vIHNpbmdsZS9zdGFjayB0b2dnbGUgb3IgcGVyLWZyYW1lIGZldGNoLCBhbmQgZm9yIHRoZVxuICAgICBzcGF0aWFsLW9taWNzIG1vZGVzOiBhIDNEIG9taWNzIGRhdGFzZXQgcHVibGlzaGVzIGl0cyByZWZlcmVuY2Ugdm9sdW1lIGFzIGEgei1zdGFja1xuICAgICBpbWFnZSwgYW5kIHRoZXNlIG1vZGVzIGRyYXcgb2JzZXJ2YXRpb25zLCBub3Qgb25lIG9mIGl0cyBzbGljZXMuIC0tPlxuPG5nLWNvbnRhaW5lciAqbmdJZj1cInN0YWNrVG9nZ2xlXCI+XG4gIDxwLWJ1dHRvblxuICAgIGljb249XCJwaSBwaS1pbWFnZVwiXG4gICAgc2l6ZT1cInNtYWxsXCJcbiAgICBhcmlhTGFiZWw9XCJTaW5nbGUgaW1hZ2UgbW9kZVwiXG4gICAgW3RleHRdPVwic2hvd1N0YWNrXCJcbiAgICBwVG9vbHRpcD1cIlNpbmdsZSBpbWFnZSBtb2RlOiBlbmFibGVzIGhpZ2gtZGVmIHpvb21cIlxuICAgIHRvb2x0aXBQb3NpdGlvbj1cImJvdHRvbVwiXG4gICAgKG9uQ2xpY2spPVwic2VsZWN0U3RhY2tPcHRpb24uZW1pdChzdGFja09wdGlvbnNbMF0pXCJcbiAgPlxuICA8L3AtYnV0dG9uPlxuICA8cC1idXR0b25cbiAgICBpY29uPVwicGkgcGktaW1hZ2VzXCJcbiAgICBzaXplPVwic21hbGxcIlxuICAgIGFyaWFMYWJlbD1cIlN0YWNrIG1vZGVcIlxuICAgIFt0ZXh0XT1cIiFzaG93U3RhY2tcIlxuICAgIHBUb29sdGlwPVwiU3RhY2sgbW9kZSwgZW5hYmxlcyBzbGljaW5nIHRocm91Z2ggaW1hZ2UgZnJhbWVzXCJcbiAgICB0b29sdGlwUG9zaXRpb249XCJib3R0b21cIlxuICAgIChvbkNsaWNrKT1cInNlbGVjdFN0YWNrT3B0aW9uLmVtaXQoc3RhY2tPcHRpb25zWzFdKVwiXG4gID5cbiAgPC9wLWJ1dHRvbj5cbjwvbmctY29udGFpbmVyPlxuPCEtLSBUaGUgc2xpY2UgYmFyLiBMaXZlIHZpZXdzIHN3YXAgdGhlIHNsaWNlIGluIHBsYWNlIGFzIGl0IG1vdmVzOyB0aGUgaGVhdG1hcCdzIHNpbmdsZSBpbWFnZVxuICAgICBpcyByZS1wbG90dGVkIGF0IHRoZSBzbGljZSB0aGUgYmFyIHNldHRsZXMgb24gKGEgZHJhZyBsZXQgZ28sIG9yIGEgcGF1c2UgaW4ga2V5IHN0ZXBzKS4gLS0+XG48bmctY29udGFpbmVyICpuZ0lmPVwibGl2ZVNjcnViYmVyIHx8IHNpbmdsZUltYWdlXCI+XG4gIDxzcGFuIGNsYXNzPVwiZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgbXgtMSB0b29sYmFyLXRleHRcIj5TbGljZTwvc3Bhbj5cbiAgPHAtc2xpZGVyXG4gICAgW25nTW9kZWxdPVwiekluZGV4XCJcbiAgICBbbWluXT1cIjBcIlxuICAgIFttYXhdPVwibWF4SW5kZXhcIlxuICAgIGFyaWFMYWJlbD1cIlNsaWNlXCJcbiAgICAocG9pbnRlcmRvd24pPVwiZHJhZ2dpbmcgPSB0cnVlXCJcbiAgICAob25DaGFuZ2UpPVwib25TbGljZUNoYW5nZSgkZXZlbnQudmFsdWUpXCJcbiAgICAob25TbGlkZUVuZCk9XCJvblNsaWNlRW5kKCRldmVudC52YWx1ZSlcIlxuICAgIFtwVG9vbHRpcF09XCJsaXZlU2NydWJiZXIgPyAnU2xpY2UgdGhyb3VnaCB0aGUgc3RhY2sgKOKGkCAvIOKGkiBrZXlzKScgOiAnU2xpY2UgdG8gcGxvdCAo4oaQIC8g4oaSIGtleXMpJ1wiXG4gICAgdG9vbHRpcFBvc2l0aW9uPVwiYm90dG9tXCJcbiAgICBbc3R5bGVdPVwieyB3aWR0aDogJzE2cmVtJyB9XCJcbiAgICBzdHlsZUNsYXNzPVwid2FuZC1zZW5zaXRpdml0eS1zbGlkZXJcIlxuICA+PC9wLXNsaWRlcj5cbiAgPHNwYW4gY2xhc3M9XCJmbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBteC0xIHRvb2xiYXItdGV4dFwiPnt7IHpJbmRleCB9fSBvZiB7eyBtYXhJbmRleCB9fTwvc3Bhbj5cbjwvbmctY29udGFpbmVyPlxuIl19
@@ -0,0 +1,37 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ /**
3
+ * Status, busy flag and progress of a long-running (download / inference) tool,
4
+ * plus the re-entrancy guard that goes with them.
5
+ */
6
+ export class AsyncToolStatus {
7
+ constructor() {
8
+ /** Status text for a toast / spinner label. */
9
+ this.status$ = new BehaviorSubject('');
10
+ /** True from the start of a run until it settles. */
11
+ this.busy$ = new BehaviorSubject(false);
12
+ /** Download progress: -1 = not downloading, 0..1 = downloading. */
13
+ this.progress$ = new BehaviorSubject(-1);
14
+ }
15
+ get busy() {
16
+ return this.busy$.value;
17
+ }
18
+ /**
19
+ * Run `job` unless a run is already in flight (then resolve `undefined` at
20
+ * once). Busy is set *before* the first await — a model download is exactly
21
+ * the window a second press must not start another run in — and busy and
22
+ * progress are reset however the job ends.
23
+ */
24
+ async run(job) {
25
+ if (this.busy$.value)
26
+ return undefined;
27
+ this.busy$.next(true);
28
+ try {
29
+ return await job();
30
+ }
31
+ finally {
32
+ this.busy$.next(false);
33
+ this.progress$.next(-1);
34
+ }
35
+ }
36
+ }
37
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmMtdG9vbC1zdGF0dXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL3Rvb2xiYXIvdG9vbC1raXQvYXN5bmMtdG9vbC1zdGF0dXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUV2Qzs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQUE1QjtRQUNFLCtDQUErQztRQUN0QyxZQUFPLEdBQUcsSUFBSSxlQUFlLENBQVMsRUFBRSxDQUFDLENBQUM7UUFDbkQscURBQXFEO1FBQzVDLFVBQUssR0FBRyxJQUFJLGVBQWUsQ0FBVSxLQUFLLENBQUMsQ0FBQztRQUNyRCxtRUFBbUU7UUFDMUQsY0FBUyxHQUFHLElBQUksZUFBZSxDQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFzQnZELENBQUM7SUFwQkMsSUFBSSxJQUFJO1FBQ04sT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQztJQUMxQixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsR0FBRyxDQUFJLEdBQXFCO1FBQ2hDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLO1lBQUUsT0FBTyxTQUFTLENBQUM7UUFDdkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdEIsSUFBSSxDQUFDO1lBQ0gsT0FBTyxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ3JCLENBQUM7Z0JBQVMsQ0FBQztZQUNULElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUIsQ0FBQztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuXG4vKipcbiAqIFN0YXR1cywgYnVzeSBmbGFnIGFuZCBwcm9ncmVzcyBvZiBhIGxvbmctcnVubmluZyAoZG93bmxvYWQgLyBpbmZlcmVuY2UpIHRvb2wsXG4gKiBwbHVzIHRoZSByZS1lbnRyYW5jeSBndWFyZCB0aGF0IGdvZXMgd2l0aCB0aGVtLlxuICovXG5leHBvcnQgY2xhc3MgQXN5bmNUb29sU3RhdHVzIHtcbiAgLyoqIFN0YXR1cyB0ZXh0IGZvciBhIHRvYXN0IC8gc3Bpbm5lciBsYWJlbC4gKi9cbiAgcmVhZG9ubHkgc3RhdHVzJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nPignJyk7XG4gIC8qKiBUcnVlIGZyb20gdGhlIHN0YXJ0IG9mIGEgcnVuIHVudGlsIGl0IHNldHRsZXMuICovXG4gIHJlYWRvbmx5IGJ1c3kkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG4gIC8qKiBEb3dubG9hZCBwcm9ncmVzczogLTEgPSBub3QgZG93bmxvYWRpbmcsIDAuLjEgPSBkb3dubG9hZGluZy4gKi9cbiAgcmVhZG9ubHkgcHJvZ3Jlc3MkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxudW1iZXI+KC0xKTtcblxuICBnZXQgYnVzeSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5idXN5JC52YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW4gYGpvYmAgdW5sZXNzIGEgcnVuIGlzIGFscmVhZHkgaW4gZmxpZ2h0ICh0aGVuIHJlc29sdmUgYHVuZGVmaW5lZGAgYXRcbiAgICogb25jZSkuIEJ1c3kgaXMgc2V0ICpiZWZvcmUqIHRoZSBmaXJzdCBhd2FpdCDigJQgYSBtb2RlbCBkb3dubG9hZCBpcyBleGFjdGx5XG4gICAqIHRoZSB3aW5kb3cgYSBzZWNvbmQgcHJlc3MgbXVzdCBub3Qgc3RhcnQgYW5vdGhlciBydW4gaW4g4oCUIGFuZCBidXN5IGFuZFxuICAgKiBwcm9ncmVzcyBhcmUgcmVzZXQgaG93ZXZlciB0aGUgam9iIGVuZHMuXG4gICAqL1xuICBhc3luYyBydW48VD4oam9iOiAoKSA9PiBQcm9taXNlPFQ+KTogUHJvbWlzZTxUIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKHRoaXMuYnVzeSQudmFsdWUpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgdGhpcy5idXN5JC5uZXh0KHRydWUpO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgam9iKCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuYnVzeSQubmV4dChmYWxzZSk7XG4gICAgICB0aGlzLnByb2dyZXNzJC5uZXh0KC0xKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==