@jax-data-science/sci-image-visualizer 0.8.3 → 0.9.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 (525) hide show
  1. package/README.md +201 -460
  2. package/esm2022/index.mjs +28 -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/instance-segmenter.contract.mjs +1 -1
  12. package/esm2022/lib/contracts/intensity.mjs +48 -5
  13. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  14. package/esm2022/lib/contracts/plot-type.mjs +134 -17
  15. package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
  16. package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
  17. package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
  18. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
  19. package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
  20. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  21. package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
  22. package/esm2022/lib/contracts/sam.contract.mjs +1 -1
  23. package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
  24. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  25. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
  26. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  27. package/esm2022/lib/contracts/viz-config.mjs +2 -1
  28. package/esm2022/lib/geometry/contour.mjs +63 -0
  29. package/esm2022/lib/geometry/raster.mjs +98 -0
  30. package/esm2022/lib/geometry/ring.mjs +201 -0
  31. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
  32. package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
  33. package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
  34. package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
  35. package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
  36. package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
  37. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +3 -4
  38. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +66 -0
  39. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +157 -591
  40. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
  41. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
  42. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
  43. package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
  44. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +263 -0
  45. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
  46. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
  47. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
  48. package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
  49. package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
  50. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +344 -0
  51. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +358 -4218
  52. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +439 -0
  53. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
  54. package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
  55. package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
  56. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +182 -0
  57. package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
  58. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
  59. package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
  60. package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
  61. package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
  62. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
  63. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
  64. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
  65. package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
  66. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
  67. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
  68. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
  69. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
  70. package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
  71. package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
  72. package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
  73. package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
  74. package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
  75. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +153 -0
  76. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +185 -718
  77. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
  78. package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
  79. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
  80. package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
  81. package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
  82. package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
  83. package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
  84. package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
  85. package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
  86. package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
  87. package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
  88. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
  89. package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
  90. package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
  91. package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
  92. package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
  93. package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
  94. package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
  95. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
  96. package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
  97. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
  98. package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
  99. package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
  100. package/esm2022/lib/implementations/region-centroids.mjs +47 -0
  101. package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
  102. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
  103. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
  104. package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
  105. package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
  106. package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
  107. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
  108. package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
  109. package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
  110. package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
  111. package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
  112. package/esm2022/lib/models/bezier.mjs +1 -11
  113. package/esm2022/lib/models/class-preset.mjs +41 -3
  114. package/esm2022/lib/models/geometry.mjs +27 -164
  115. package/esm2022/lib/models/polygon-edit.mjs +254 -0
  116. package/esm2022/lib/models/polygon-factory.mjs +118 -0
  117. package/esm2022/lib/models/region-clone.mjs +68 -0
  118. package/esm2022/lib/models/region-geojson.mjs +373 -0
  119. package/esm2022/lib/models/region.mjs +34 -33
  120. package/esm2022/lib/models/shape.mjs +18 -16
  121. package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
  122. package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
  123. package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
  124. package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
  125. package/esm2022/lib/plot.utilities.mjs +296 -473
  126. package/esm2022/lib/processing/image-crop.mjs +1 -1
  127. package/esm2022/lib/processing/processing-image.mjs +28 -15
  128. package/esm2022/lib/provide-visualization.mjs +40 -14
  129. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +99 -0
  130. package/esm2022/lib/region-editor/file-stem.mjs +13 -0
  131. package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
  132. package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
  133. package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
  134. package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
  135. package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
  136. package/esm2022/lib/region-editor/region-editor.component.mjs +402 -651
  137. package/esm2022/lib/region-editor/region-metrics.mjs +68 -0
  138. package/esm2022/lib/region-editor/region-persistence.service.mjs +134 -0
  139. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +153 -0
  140. package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
  141. package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
  142. package/esm2022/lib/region-ops.service.mjs +28 -70
  143. package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
  144. package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
  145. package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
  146. package/esm2022/lib/render-orchestrator.mjs +14 -11
  147. package/esm2022/lib/render-session.mjs +207 -0
  148. package/esm2022/lib/routing-visualizer.service.mjs +459 -411
  149. package/esm2022/lib/spatial/density-raster.mjs +14 -0
  150. package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
  151. package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
  152. package/esm2022/lib/spatial/gene-search.mjs +1 -1
  153. package/esm2022/lib/spatial/glyphs.mjs +97 -0
  154. package/esm2022/lib/spatial/lod.mjs +187 -0
  155. package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
  156. package/esm2022/lib/spatial/spatial-density.mjs +25 -16
  157. package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
  158. package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
  159. package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
  160. package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
  161. package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
  162. package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
  163. package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
  164. package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
  165. package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
  166. package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
  167. package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
  168. package/esm2022/lib/spatial/stats.mjs +71 -0
  169. package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
  170. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
  171. package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
  172. package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
  173. package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
  174. package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
  175. package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
  176. package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
  177. package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
  178. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
  179. package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
  180. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
  181. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
  182. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
  183. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
  184. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
  185. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
  186. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
  187. package/esm2022/lib/store/class-color.util.mjs +46 -3
  188. package/esm2022/lib/store/region-history.mjs +146 -0
  189. package/esm2022/lib/store/region-scope-cache.mjs +140 -0
  190. package/esm2022/lib/store/region-selection.mjs +82 -0
  191. package/esm2022/lib/store/region-store.service.mjs +279 -675
  192. package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
  193. package/esm2022/lib/store/visualizer-store.service.mjs +49 -71
  194. package/esm2022/lib/toast-outlets.mjs +5 -4
  195. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
  196. package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
  197. package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
  198. package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
  199. package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
  200. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +114 -0
  201. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
  202. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
  203. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
  204. package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
  205. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
  206. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
  207. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
  208. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
  209. package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
  210. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
  211. package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
  212. package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
  213. package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
  214. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +81 -0
  215. package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
  216. package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
  217. package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
  218. package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
  219. package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
  220. package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
  221. package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
  222. package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
  223. package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
  224. package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
  225. package/esm2022/lib/toolbar/toolbar.component.mjs +68 -117
  226. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
  227. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
  228. package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
  229. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
  230. package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
  231. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
  232. package/esm2022/lib/util/mark-for-check.mjs +17 -0
  233. package/esm2022/lib/util/supersede.mjs +56 -0
  234. package/esm2022/lib/visualization.module.mjs +39 -141
  235. package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
  236. package/esm2022/lib/visualizer/region-actions.mjs +149 -0
  237. package/esm2022/lib/visualizer/region-load.mjs +60 -0
  238. package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
  239. package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
  240. package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
  241. package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
  242. package/esm2022/lib/visualizer.component.mjs +480 -1902
  243. package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
  244. package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
  245. package/esm2022/lib/workers/spatial-math.mjs +190 -0
  246. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs +41083 -0
  247. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +1 -0
  248. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs +238 -0
  249. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map +1 -0
  250. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
  251. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
  252. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34467
  253. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  254. package/fesm2022/mask.worker.js +36 -917
  255. package/fesm2022/onnx-sam.worker.js +52 -16
  256. package/fesm2022/spatial-math.worker.js +471 -0
  257. package/fesm2022/tsne.worker.js +32 -15
  258. package/index.d.ts +13 -10
  259. package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
  260. package/lib/contracts/capabilities.contract.d.ts +4 -2
  261. package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
  262. package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
  263. package/lib/contracts/color.d.ts +27 -0
  264. package/lib/contracts/colormap-lut.d.ts +19 -4
  265. package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
  266. package/lib/contracts/display-types.d.ts +21 -0
  267. package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
  268. package/lib/contracts/intensity.d.ts +13 -2
  269. package/lib/contracts/plot-type.d.ts +3 -1
  270. package/lib/contracts/ports/image-state.port.d.ts +6 -2
  271. package/lib/contracts/ports/preferences.port.d.ts +4 -0
  272. package/lib/contracts/ports/region-io.port.d.ts +1 -0
  273. package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
  274. package/lib/contracts/ports/tile-access.port.d.ts +1 -0
  275. package/lib/contracts/region-editor-api.contract.d.ts +1 -1
  276. package/lib/contracts/region-overlay.contract.d.ts +5 -0
  277. package/lib/contracts/sam.contract.d.ts +7 -0
  278. package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
  279. package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
  280. package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
  281. package/lib/contracts/visualizer.contract.d.ts +221 -54
  282. package/lib/contracts/viz-config.d.ts +1 -0
  283. package/lib/geometry/contour.d.ts +24 -0
  284. package/lib/geometry/raster.d.ts +42 -0
  285. package/lib/geometry/ring.d.ts +67 -0
  286. package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
  287. package/lib/implementations/base-store-visualizer.d.ts +61 -15
  288. package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
  289. package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
  290. package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
  291. package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
  292. package/lib/implementations/napari-js/napari-loading-badge.d.ts +0 -1
  293. package/lib/implementations/napari-js/napari-loading-state.d.ts +30 -0
  294. package/lib/implementations/napari-js/napari-region-overlay.d.ts +62 -70
  295. package/lib/implementations/napari-js/napari-scene.d.ts +93 -0
  296. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
  297. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
  298. package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
  299. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +89 -0
  300. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
  301. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
  302. package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
  303. package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
  304. package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
  305. package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
  306. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +121 -883
  307. package/lib/implementations/napari-js/napari-volume-scene.d.ts +104 -0
  308. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
  309. package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
  310. package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
  311. package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
  312. package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
  313. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
  314. package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
  315. package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
  316. package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
  317. package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
  318. package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
  319. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
  320. package/lib/implementations/osd/display-pipeline.d.ts +38 -9
  321. package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
  322. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
  323. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
  324. package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
  325. package/lib/implementations/osd/osd-coords.d.ts +6 -4
  326. package/lib/implementations/osd/osd-export.d.ts +36 -0
  327. package/lib/implementations/osd/osd-lib.d.ts +7 -0
  328. package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
  329. package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
  330. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +37 -0
  331. package/lib/implementations/osd/osd-region-overlay.d.ts +36 -48
  332. package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
  333. package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
  334. package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
  335. package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
  336. package/lib/implementations/osd/osd-viewport.d.ts +77 -0
  337. package/lib/implementations/osd/osd-zoom.d.ts +6 -0
  338. package/lib/implementations/osd/simple-source.d.ts +161 -0
  339. package/lib/implementations/osd/slice-cache.d.ts +12 -3
  340. package/lib/implementations/osd/tile-client.d.ts +11 -14
  341. package/lib/implementations/osd/tile-recolor.d.ts +141 -0
  342. package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
  343. package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
  344. package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
  345. package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
  346. package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
  347. package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
  348. package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
  349. package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
  350. package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
  351. package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
  352. package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
  353. package/lib/implementations/plotly/plotly.service.d.ts +136 -401
  354. package/lib/implementations/region-centroids.d.ts +14 -0
  355. package/lib/implementations/simple-slice-access.service.d.ts +7 -4
  356. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
  357. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
  358. package/lib/implementations/tile-server/index.d.ts +5 -0
  359. package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
  360. package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
  361. package/lib/implementations/tile-server/tile-protocol.d.ts +80 -0
  362. package/lib/implementations/tile-server/transport.d.ts +62 -0
  363. package/lib/intensity/intensity-profile.d.ts +66 -0
  364. package/lib/intensity/intensity-profile.service.d.ts +108 -0
  365. package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
  366. package/lib/models/bezier.d.ts +0 -5
  367. package/lib/models/class-preset.d.ts +18 -0
  368. package/lib/models/geometry.d.ts +14 -48
  369. package/lib/models/polygon-edit.d.ts +72 -0
  370. package/lib/models/polygon-factory.d.ts +40 -0
  371. package/lib/models/region-clone.d.ts +20 -0
  372. package/lib/models/region-geojson.d.ts +17 -0
  373. package/lib/models/region.d.ts +40 -4
  374. package/lib/models/shape.d.ts +8 -0
  375. package/lib/plot-mode/contribution-host.d.ts +125 -0
  376. package/lib/plot-mode/plot-type-menu.d.ts +60 -0
  377. package/lib/plot-mode/tool-params-model.d.ts +49 -0
  378. package/lib/plot.utilities.d.ts +19 -30
  379. package/lib/processing/processing-image.d.ts +5 -2
  380. package/lib/provide-visualization.d.ts +19 -2
  381. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +56 -0
  382. package/lib/region-editor/file-stem.d.ts +7 -0
  383. package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
  384. package/lib/region-editor/mask-export.service.d.ts +54 -0
  385. package/lib/region-editor/mask-raster.d.ts +2 -8
  386. package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
  387. package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
  388. package/lib/region-editor/region-editor.component.d.ts +166 -199
  389. package/lib/region-editor/region-metrics.d.ts +26 -0
  390. package/lib/region-editor/region-persistence.service.d.ts +69 -0
  391. package/lib/region-editor/region-table/region-table.component.d.ts +83 -0
  392. package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
  393. package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
  394. package/lib/region-ops.service.d.ts +1 -7
  395. package/lib/region-overlay/region-geometry.d.ts +157 -0
  396. package/lib/region-overlay/region-hit-test.d.ts +38 -0
  397. package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
  398. package/lib/render-orchestrator.d.ts +6 -2
  399. package/lib/render-session.d.ts +75 -0
  400. package/lib/routing-visualizer.service.d.ts +110 -58
  401. package/lib/spatial/density-raster.d.ts +6 -0
  402. package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
  403. package/lib/spatial/embedding-compute.d.ts +21 -2
  404. package/lib/spatial/glyphs.d.ts +16 -0
  405. package/lib/spatial/lod.d.ts +94 -0
  406. package/lib/spatial/spatial-controls.facade.d.ts +64 -0
  407. package/lib/spatial/spatial-density.d.ts +15 -5
  408. package/lib/spatial/spatial-encoding.d.ts +11 -44
  409. package/lib/spatial/spatial-expression.d.ts +40 -22
  410. package/lib/spatial/spatial-framing.d.ts +1 -0
  411. package/lib/spatial/spatial-heatmap.d.ts +2 -0
  412. package/lib/spatial/spatial-hover.d.ts +4 -16
  413. package/lib/spatial/spatial-panel-model.d.ts +135 -0
  414. package/lib/spatial/spatial-selection.d.ts +21 -26
  415. package/lib/spatial/spatial-tile-merge.d.ts +41 -0
  416. package/lib/spatial/spatial-tiles.d.ts +9 -256
  417. package/lib/spatial/stats.d.ts +38 -0
  418. package/lib/spatial/transcript-grouping.d.ts +119 -0
  419. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
  420. package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
  421. package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
  422. package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
  423. package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
  424. package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
  425. package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
  426. package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
  427. package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
  428. package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
  429. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
  430. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
  431. package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
  432. package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
  433. package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
  434. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
  435. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
  436. package/lib/store/class-color.util.d.ts +35 -1
  437. package/lib/store/region-history.d.ts +66 -0
  438. package/lib/store/region-scope-cache.d.ts +63 -0
  439. package/lib/store/region-selection.d.ts +36 -0
  440. package/lib/store/region-store.service.d.ts +104 -112
  441. package/lib/store/visualizer-store.service.d.ts +22 -33
  442. package/lib/toast-outlets.d.ts +4 -3
  443. package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
  444. package/lib/toolbar/canvas-tools.d.ts +20 -0
  445. package/lib/toolbar/crop/slide-crop.d.ts +10 -4
  446. package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
  447. package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
  448. package/lib/toolbar/region-tools/region-tools.component.d.ts +60 -0
  449. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
  450. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
  451. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
  452. package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
  453. package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
  454. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
  455. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
  456. package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
  457. package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
  458. package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
  459. package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
  460. package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
  461. package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
  462. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +40 -0
  463. package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
  464. package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
  465. package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
  466. package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
  467. package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
  468. package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
  469. package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
  470. package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
  471. package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
  472. package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
  473. package/lib/toolbar/toolbar.component.d.ts +47 -83
  474. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
  475. package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
  476. package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
  477. package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
  478. package/lib/toolbar/wand/wand.service.d.ts +22 -116
  479. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
  480. package/lib/util/mark-for-check.d.ts +11 -0
  481. package/lib/util/supersede.d.ts +53 -0
  482. package/lib/visualization.module.d.ts +18 -39
  483. package/lib/visualizer/floating-drag.directive.d.ts +30 -0
  484. package/lib/visualizer/region-actions.d.ts +54 -0
  485. package/lib/visualizer/region-load.d.ts +27 -0
  486. package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
  487. package/lib/visualizer/tool-modes.d.ts +49 -0
  488. package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
  489. package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
  490. package/lib/visualizer.component.d.ts +201 -447
  491. package/lib/workers/spatial-math-ops.d.ts +65 -0
  492. package/lib/workers/spatial-math-worker.d.ts +7 -0
  493. package/lib/workers/spatial-math.d.ts +74 -0
  494. package/package.json +12 -3
  495. package/src/lib/styles/_viz-icons-rules.scss +73 -0
  496. package/src/lib/styles/viz-icons.scss +14 -0
  497. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
  498. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
  499. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
  500. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
  501. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
  502. package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
  503. package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
  504. package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
  505. package/src/lib/assets/cell-detection.svg +0 -37
  506. package/src/lib/assets/click.svg +0 -1
  507. package/src/lib/assets/colormap-luts.json +0 -1
  508. package/src/lib/assets/edit-selection-white.svg +0 -47
  509. package/src/lib/assets/icons/colormap-earth.png +0 -0
  510. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  511. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  512. package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
  513. package/src/lib/assets/picture-segmentation.svg +0 -43
  514. package/src/lib/assets/test/download-379.svg +0 -1
  515. package/src/lib/assets/test/download-98.svg +0 -1
  516. package/src/lib/assets/test/json-1.svg +0 -1
  517. package/src/lib/assets/test/load-53.svg +0 -1
  518. package/src/lib/assets/test/mask-44.svg +0 -1
  519. package/src/lib/assets/test/mask-download-44.svg +0 -15
  520. package/src/lib/assets/test/mask-save-44.svg +0 -11
  521. package/src/lib/assets/test/overlay-1.svg +0 -1
  522. package/src/lib/assets/test/overlay-4.svg +0 -1
  523. package/src/lib/assets/test/region-26.svg +0 -1
  524. package/src/lib/assets/test/save-56.svg +0 -1
  525. package/src/lib/assets/test/upload-43.svg +0 -1
@@ -0,0 +1,113 @@
1
+ /** Region draw/select/edit modes, routed through the backend's region overlay. The vertex
2
+ * tools (drawpolygon/addpoint/deletepoint/move) are handled by the OpenSeadragon overlay;
3
+ * Plotly's overlay maps them to no-op. */
4
+ const REGION_MODES = new Set([
5
+ 'drawrect',
6
+ 'drawclosedpath',
7
+ 'drawopenpath',
8
+ 'select',
9
+ 'drawpolygon',
10
+ 'addpoint',
11
+ 'deletepoint',
12
+ 'move',
13
+ ]);
14
+ /**
15
+ * The armed tool mode (one at a time across the region overlay, the viewport drag
16
+ * modes and the on-canvas tools) and the toolbar's tool settings it arms them with.
17
+ */
18
+ export class ToolModes {
19
+ constructor(target, record, zone,
20
+ /** Runs after every arm/disarm with the newly armed mode. */
21
+ armed, markForCheck) {
22
+ this.target = target;
23
+ this.record = record;
24
+ this.armed = armed;
25
+ /** The armed mode, or null. */
26
+ this.active = null;
27
+ /** Wand sensitivity — higher = stricter (smaller selection). Matches QuPath default. */
28
+ this.wandSensitivity = 2.0;
29
+ /** Brush diameter in image-pixel coordinates (drives the painted disc size). */
30
+ this.brushSize = 40;
31
+ /** Vertex eraser radius in image-pixel coordinates. */
32
+ this.vertexEraserRadius = 20;
33
+ /** Class the brush paints while a plot mode armed it; null = plain brush. */
34
+ this.brushClass = null;
35
+ this.plotModeTools = {
36
+ armBrush: (brushClass) => zone.run(() => {
37
+ this.brushClass = { label: brushClass?.label, color: brushClass?.color };
38
+ if (this.active === 'brush')
39
+ this.target.setBrushOptions({ size: this.brushSize, ...this.brushClass });
40
+ else
41
+ this.apply('brush');
42
+ markForCheck();
43
+ }),
44
+ disarm: () => zone.run(() => {
45
+ this.brushClass = null;
46
+ if (this.active !== null)
47
+ this.apply(null);
48
+ markForCheck();
49
+ }),
50
+ activeTool$: record.getActiveTool$(),
51
+ };
52
+ }
53
+ /** A tool picked by the user (always the plain tool, never a plot mode's brush class);
54
+ * re-picking the armed one disarms it. */
55
+ toggle(mode) {
56
+ this.brushClass = null;
57
+ this.apply(this.active === mode ? null : mode);
58
+ }
59
+ /** Arm `mode` (or nothing) across every tool. */
60
+ apply(mode) {
61
+ this.active = mode;
62
+ this.record.setActiveTool(mode);
63
+ const regionMode = mode !== null && REGION_MODES.has(mode);
64
+ this.target.getRegionOverlay()?.setMode(regionMode ? mode : 'none');
65
+ // Viewport drag modes (pan/box-zoom). Region modes own the drag mode via the overlay.
66
+ if (!regionMode)
67
+ this.target.setDragMode(mode === 'pan' || mode === 'zoom' ? mode : false);
68
+ // On-canvas tools: arm the one this mode names (none for a region or viewport mode).
69
+ this.target.setActiveTool(mode, this.options(mode));
70
+ this.armed(mode);
71
+ }
72
+ /** Disarm whatever is armed and clear every tool mode (a plot-type switch). */
73
+ deactivate() {
74
+ this.brushClass = null;
75
+ this.active = null;
76
+ this.record.setActiveTool(null);
77
+ this.target.getRegionOverlay()?.setMode('none');
78
+ this.target.setDragMode(false);
79
+ this.target.setActiveTool(null);
80
+ }
81
+ setWandSensitivity(value) {
82
+ if (value === undefined || !Number.isFinite(value))
83
+ return;
84
+ this.wandSensitivity = value;
85
+ this.target.setWandOptions({ sensitivity: value });
86
+ }
87
+ setBrushSize(value) {
88
+ if (value === undefined || !Number.isFinite(value))
89
+ return;
90
+ this.brushSize = value;
91
+ this.target.setBrushOptions({ size: value });
92
+ }
93
+ setVertexEraserRadius(value) {
94
+ if (value === undefined || !Number.isFinite(value))
95
+ return;
96
+ this.vertexEraserRadius = value;
97
+ this.target.setVertexEraserRadius(value);
98
+ }
99
+ /** The options a canvas tool is armed with, from the toolbar's settings. */
100
+ options(mode) {
101
+ switch (mode) {
102
+ case 'wand':
103
+ return { sensitivity: this.wandSensitivity };
104
+ case 'brush':
105
+ return { size: this.brushSize, ...this.brushClass };
106
+ case 'eraseVertex':
107
+ return { radius: this.vertexEraserRadius };
108
+ default:
109
+ return undefined;
110
+ }
111
+ }
112
+ }
113
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbC1tb2Rlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdmlzdWFsaXplci90b29sLW1vZGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQXlCQTs7MkNBRTJDO0FBQzNDLE1BQU0sWUFBWSxHQUF3QixJQUFJLEdBQUcsQ0FBQztJQUNoRCxVQUFVO0lBQ1YsZ0JBQWdCO0lBQ2hCLGNBQWM7SUFDZCxRQUFRO0lBQ1IsYUFBYTtJQUNiLFVBQVU7SUFDVixhQUFhO0lBQ2IsTUFBTTtDQUNQLENBQUMsQ0FBQztBQUVIOzs7R0FHRztBQUNILE1BQU0sT0FBTyxTQUFTO0lBZXBCLFlBQ21CLE1BQXVCLEVBQ3ZCLE1BQXdCLEVBQ3pDLElBQVk7SUFDWiw2REFBNkQ7SUFDNUMsS0FBb0MsRUFDckQsWUFBd0I7UUFMUCxXQUFNLEdBQU4sTUFBTSxDQUFpQjtRQUN2QixXQUFNLEdBQU4sTUFBTSxDQUFrQjtRQUd4QixVQUFLLEdBQUwsS0FBSyxDQUErQjtRQW5CdkQsK0JBQStCO1FBQy9CLFdBQU0sR0FBa0IsSUFBSSxDQUFDO1FBQzdCLHdGQUF3RjtRQUN4RixvQkFBZSxHQUFHLEdBQUcsQ0FBQztRQUN0QixnRkFBZ0Y7UUFDaEYsY0FBUyxHQUFHLEVBQUUsQ0FBQztRQUNmLHVEQUF1RDtRQUN2RCx1QkFBa0IsR0FBRyxFQUFFLENBQUM7UUFJeEIsNkVBQTZFO1FBQ3JFLGVBQVUsR0FBOEIsSUFBSSxDQUFDO1FBVW5ELElBQUksQ0FBQyxhQUFhLEdBQUc7WUFDbkIsUUFBUSxFQUFFLENBQUMsVUFBK0IsRUFBRSxFQUFFLENBQzVDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFO2dCQUNaLElBQUksQ0FBQyxVQUFVLEdBQUcsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxDQUFDO2dCQUN6RSxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUss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WUFBWSxDQUFDLEtBQXlCO1FBQ3BDLElBQUksS0FBSyxLQUFLLFNBQVMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDO1lBQUUsT0FBTztRQUMzRCxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFFRCxxQkFBcUIsQ0FBQyxLQUF5QjtRQUM3QyxJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU87UUFDM0QsSUFBSSxDQUFDLGtCQUFrQixHQUFHLEtBQUssQ0FBQztRQUNoQyxJQUFJLENBQUMsTUFBTSxDQUFDLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFRCw0RUFBNEU7SUFDcEUsT0FBTyxDQUFDLElBQW1CO1FBQ2pDLFFBQVEsSUFBSSxFQUFFLENBQUM7WUFDYixLQUFLLE1BQU07Z0JBQ1QsT0FBTyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDL0MsS0FBSyxPQUFPO2dCQUNWLE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUN0RCxLQUFLLGFBQWE7Z0JBQ2hCLE9BQU8sRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDN0M7Z0JBQ0UsT0FBTyxTQUFTLENBQUM7UUFDckIsQ0FBQztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5nWm9uZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBDYW52YXNUb29sT3B0aW9ucyB9IGZyb20gJy4uL2NvbnRyYWN0cy9kaXNwbGF5LXR5cGVzJztcbmltcG9ydCB7IFBsb3RNb2RlQnJ1c2hDbGFzcywgUGxvdE1vZGVUb29scyB9IGZyb20gJy4uL2NvbnRyYWN0cy9wbG90LXR5cGUtY29udHJpYnV0aW9uLmNvbnRyYWN0JztcbmltcG9ydCB7IFJlZ2lvblRvb2xNb2RlIH0gZnJvbSAnLi4vY29udHJhY3RzL3JlZ2lvbi1vdmVybGF5LmNvbnRyYWN0JztcbmltcG9ydCB7IElWaXN1YWxpemVyIH0gZnJvbSAnLi4vY29udHJhY3RzL3Zpc3VhbGl6ZXIuY29udHJhY3QnO1xuXG4vKiogVGhlIGJhY2tlbmQgbWVtYmVycyB0b29sIGFybWluZyBkcml2ZXMuICovXG5leHBvcnQgdHlwZSBUb29sTW9kZXNUYXJnZXQgPSBQaWNrPFxuICBJVmlzdWFsaXplcixcbiAgfCAnZ2V0UmVnaW9uT3ZlcmxheSdcbiAgfCAnc2V0RHJhZ01vZGUnXG4gIHwgJ3NldEFjdGl2ZVRvb2wnXG4gIHwgJ3NldFdhbmRPcHRpb25zJ1xuICB8ICdzZXRCcnVzaE9wdGlvbnMnXG4gIHwgJ3NldFZlcnRleEVyYXNlclJhZGl1cydcbj47XG5cbi8qKiBXaGVyZSB0aGUgYXJtZWQgdG9vbCBpcyByZWNvcmRlZCBmb3IgZXZlcnlvbmUgZWxzZSAodGhlIHNoYXJlZCBzZXNzaW9uIHN0b3JlKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWN0aXZlVG9vbFJlY29yZCB7XG4gIHNldEFjdGl2ZVRvb2woaWQ6IHN0cmluZyB8IG51bGwpOiB2b2lkO1xuICBnZXRBY3RpdmVUb29sJCgpOiBPYnNlcnZhYmxlPHN0cmluZyB8IG51bGw+O1xufVxuXG4vKiogUmVnaW9uIGRyYXcvc2VsZWN0L2VkaXQgbW9kZXMsIHJvdXRlZCB0aHJvdWdoIHRoZSBiYWNrZW5kJ3MgcmVnaW9uIG92ZXJsYXkuIFRoZSB2ZXJ0ZXhcbiAqICB0b29scyAoZHJhd3BvbHlnb24vYWRkcG9pbnQvZGVsZXRlcG9pbnQvbW92ZSkgYXJlIGhhbmRsZWQgYnkgdGhlIE9wZW5TZWFkcmFnb24gb3ZlcmxheTtcbiAqICBQbG90bHkncyBvdmVybGF5IG1hcHMgdGhlbSB0byBuby1vcC4gKi9cbmNvbnN0IFJFR0lPTl9NT0RFUzogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoW1xuICAnZHJhd3JlY3QnLFxuICAnZHJhd2Nsb3NlZHBhdGgnLFxuICAnZHJhd29wZW5wYXRoJyxcbiAgJ3NlbGVjdCcsXG4gICdkcmF3cG9seWdvbicsXG4gICdhZGRwb2ludCcsXG4gICdkZWxldGVwb2ludCcsXG4gICdtb3ZlJyxcbl0pO1xuXG4vKipcbiAqIFRoZSBhcm1lZCB0b29sIG1vZGUgKG9uZSBhdCBhIHRpbWUgYWNyb3NzIHRoZSByZWdpb24gb3ZlcmxheSwgdGhlIHZpZXdwb3J0IGRyYWdcbiAqIG1vZGVzIGFuZCB0aGUgb24tY2FudmFzIHRvb2xzKSBhbmQgdGhlIHRvb2xiYXIncyB0b29sIHNldHRpbmdzIGl0IGFybXMgdGhlbSB3aXRoLlxuICovXG5leHBvcnQgY2xhc3MgVG9vbE1vZGVzIHtcbiAgLyoqIFRoZSBhcm1lZCBtb2RlLCBvciBudWxsLiAqL1xuICBhY3RpdmU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAvKiogV2FuZCBzZW5zaXRpdml0eSDigJQgaGlnaGVyID0gc3RyaWN0ZXIgKHNtYWxsZXIgc2VsZWN0aW9uKS4gTWF0Y2hlcyBRdVBhdGggZGVmYXVsdC4gKi9cbiAgd2FuZFNlbnNpdGl2aXR5ID0gMi4wO1xuICAvKiogQnJ1c2ggZGlhbWV0ZXIgaW4gaW1hZ2UtcGl4ZWwgY29vcmRpbmF0ZXMgKGRyaXZlcyB0aGUgcGFpbnRlZCBkaXNjIHNpemUpLiAqL1xuICBicnVzaFNpemUgPSA0MDtcbiAgLyoqIFZlcnRleCBlcmFzZXIgcmFkaXVzIGluIGltYWdlLXBpeGVsIGNvb3JkaW5hdGVzLiAqL1xuICB2ZXJ0ZXhFcmFzZXJSYWRpdXMgPSAyMDtcbiAgLyoqIFRoZSB0b29sYmFyIHRvb2xzIGEgY29udHJpYnV0ZWQgcGxvdCBtb2RlIG1heSBhcm0uIENhbGxzIGNhbiBjb21lIGZyb20gb3V0c2lkZVxuICAgKiAgQW5ndWxhciwgaGVuY2UgdGhlIHpvbmUuICovXG4gIHJlYWRvbmx5IHBsb3RNb2RlVG9vbHM6IFBsb3RNb2RlVG9vbHM7XG4gIC8qKiBDbGFzcyB0aGUgYnJ1c2ggcGFpbnRzIHdoaWxlIGEgcGxvdCBtb2RlIGFybWVkIGl0OyBudWxsID0gcGxhaW4gYnJ1c2guICovXG4gIHByaXZhdGUgYnJ1c2hDbGFzczogUGxvdE1vZGVCcnVzaENsYXNzIHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSB0YXJnZXQ6IFRvb2xNb2Rlc1RhcmdldCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlY29yZDogQWN0aXZlVG9vbFJlY29yZCxcbiAgICB6b25lOiBOZ1pvbmUsXG4gICAgLyoqIFJ1bnMgYWZ0ZXIgZXZlcnkgYXJtL2Rpc2FybSB3aXRoIHRoZSBuZXdseSBhcm1lZCBtb2RlLiAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgYXJtZWQ6IChtb2RlOiBzdHJpbmcgfCBudWxsKSA9PiB2b2lkLFxuICAgIG1hcmtGb3JDaGVjazogKCkgPT4gdm9pZCxcbiAgKSB7XG4gICAgdGhpcy5wbG90TW9kZVRvb2xzID0ge1xuICAgICAgYXJtQnJ1c2g6IChicnVzaENsYXNzPzogUGxvdE1vZGVCcnVzaENsYXNzKSA9PlxuICAgICAgICB6b25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgdGhpcy5icnVzaENsYXNzID0geyBsYWJlbDogYnJ1c2hDbGFzcz8ubGFiZWwsIGNvbG9yOiBicnVzaENsYXNzPy5jb2xvciB9O1xuICAgICAgICAgIGlmICh0aGlzLmFjdGl2ZSA9PT0gJ2JydXNoJykgdGhpcy50YXJnZXQuc2V0QnJ1c2hPcHRpb25zKHsgc2l6ZTogdGhpcy5icnVzaFNpemUsIC4uLnRoaXMuYnJ1c2hDbGFzcyB9KTtcbiAgICAgICAgICBlbHNlIHRoaXMuYXBwbHkoJ2JydXNoJyk7XG4gICAgICAgICAgbWFya0ZvckNoZWNrKCk7XG4gICAgICAgIH0pLFxuICAgICAgZGlzYXJtOiAoKSA9PlxuICAgICAgICB6b25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgdGhpcy5icnVzaENsYXNzID0gbnVsbDtcbiAgICAgICAgICBpZiAodGhpcy5hY3RpdmUgIT09IG51bGwpIHRoaXMuYXBwbHkobnVsbCk7XG4gICAgICAgICAgbWFya0ZvckNoZWNrKCk7XG4gICAgICAgIH0pLFxuICAgICAgYWN0aXZlVG9vbCQ6IHJlY29yZC5nZXRBY3RpdmVUb29sJCgpLFxuICAgIH07XG4gIH1cblxuICAvKiogQSB0b29sIHBpY2tlZCBieSB0aGUgdXNlciAoYWx3YXlzIHRoZSBwbGFpbiB0b29sLCBuZXZlciBhIHBsb3QgbW9kZSdzIGJydXNoIGNsYXNzKTtcbiAgICogIHJlLXBpY2tpbmcgdGhlIGFybWVkIG9uZSBkaXNhcm1zIGl0LiAqL1xuICB0b2dnbGUobW9kZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5icnVzaENsYXNzID0gbnVsbDtcbiAgICB0aGlzLmFwcGx5KHRoaXMuYWN0aXZlID09PSBtb2RlID8gbnVsbCA6IG1vZGUpO1xuICB9XG5cbiAgLyoqIEFybSBgbW9kZWAgKG9yIG5vdGhpbmcpIGFjcm9zcyBldmVyeSB0b29sLiAqL1xuICBhcHBseShtb2RlOiBzdHJpbmcgfCBudWxsKTogdm9pZCB7XG4gICAgdGhpcy5hY3RpdmUgPSBtb2RlO1xuICAgIHRoaXMucmVjb3JkLnNldEFjdGl2ZVRvb2wobW9kZSk7XG4gICAgY29uc3QgcmVnaW9uTW9kZSA9IG1vZGUgIT09IG51bGwgJiYgUkVHSU9OX01PREVTLmhhcyhtb2RlKTtcbiAgICB0aGlzLnRhcmdldC5nZXRSZWdpb25PdmVybGF5KCk/LnNldE1vZGUocmVnaW9uTW9kZSA/IChtb2RlIGFzIFJlZ2lvblRvb2xNb2RlKSA6ICdub25lJyk7XG4gICAgLy8gVmlld3BvcnQgZHJhZyBtb2RlcyAocGFuL2JveC16b29tKS4gUmVnaW9uIG1vZGVzIG93biB0aGUgZHJhZyBtb2RlIHZpYSB0aGUgb3ZlcmxheS5cbiAgICBpZiAoIXJlZ2lvbk1vZGUpIHRoaXMudGFyZ2V0LnNldERyYWdNb2RlKG1vZGUgPT09ICdwYW4nIHx8IG1vZGUgPT09ICd6b29tJyA/IG1vZGUgOiBmYWxzZSk7XG4gICAgLy8gT24tY2FudmFzIHRvb2xzOiBhcm0gdGhlIG9uZSB0aGlzIG1vZGUgbmFtZXMgKG5vbmUgZm9yIGEgcmVnaW9uIG9yIHZpZXdwb3J0IG1vZGUpLlxuICAgIHRoaXMudGFyZ2V0LnNldEFjdGl2ZVRvb2wobW9kZSwgdGhpcy5vcHRpb25zKG1vZGUpKTtcbiAgICB0aGlzLmFybWVkKG1vZGUpO1xuICB9XG5cbiAgLyoqIERpc2FybSB3aGF0ZXZlciBpcyBhcm1lZCBhbmQgY2xlYXIgZXZlcnkgdG9vbCBtb2RlIChhIHBsb3QtdHlwZSBzd2l0Y2gpLiAqL1xuICBkZWFjdGl2YXRlKCk6IHZvaWQge1xuICAgIHRoaXMuYnJ1c2hDbGFzcyA9IG51bGw7XG4gICAgdGhpcy5hY3RpdmUgPSBudWxsO1xuICAgIHRoaXMucmVjb3JkLnNldEFjdGl2ZVRvb2wobnVsbCk7XG4gICAgdGhpcy50YXJnZXQuZ2V0UmVnaW9uT3ZlcmxheSgpPy5zZXRNb2RlKCdub25lJyk7XG4gICAgdGhpcy50YXJnZXQuc2V0RHJhZ01vZGUoZmFsc2UpO1xuICAgIHRoaXMudGFyZ2V0LnNldEFjdGl2ZVRvb2wobnVsbCk7XG4gIH1cblxuICBzZXRXYW5kU2Vuc2l0aXZpdHkodmFsdWU6IG51bWJlciB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8ICFOdW1iZXIuaXNGaW5pdGUodmFsdWUpKSByZXR1cm47XG4gICAgdGhpcy53YW5kU2Vuc2l0aXZpdHkgPSB2YWx1ZTtcbiAgICB0aGlzLnRhcmdldC5zZXRXYW5kT3B0aW9ucyh7IHNlbnNpdGl2aXR5OiB2YWx1ZSB9KTtcbiAgfVxuXG4gIHNldEJydXNoU2l6ZSh2YWx1ZTogbnVtYmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgfHwgIU51bWJlci5pc0Zpbml0ZSh2YWx1ZSkpIHJldHVybjtcbiAgICB0aGlzLmJydXNoU2l6ZSA9IHZhbHVlO1xuICAgIHRoaXMudGFyZ2V0LnNldEJydXNoT3B0aW9ucyh7IHNpemU6IHZhbHVlIH0pO1xuICB9XG5cbiAgc2V0VmVydGV4RXJhc2VyUmFkaXVzKHZhbHVlOiBudW1iZXIgfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCB8fCAhTnVtYmVyLmlzRmluaXRlKHZhbHVlKSkgcmV0dXJuO1xuICAgIHRoaXMudmVydGV4RXJhc2VyUmFkaXVzID0gdmFsdWU7XG4gICAgdGhpcy50YXJnZXQuc2V0VmVydGV4RXJhc2VyUmFkaXVzKHZhbHVlKTtcbiAgfVxuXG4gIC8qKiBUaGUgb3B0aW9ucyBhIGNhbnZhcyB0b29sIGlzIGFybWVkIHdpdGgsIGZyb20gdGhlIHRvb2xiYXIncyBzZXR0aW5ncy4gKi9cbiAgcHJpdmF0ZSBvcHRpb25zKG1vZGU6IHN0cmluZyB8IG51bGwpOiBDYW52YXNUb29sT3B0aW9ucyB8IHVuZGVmaW5lZCB7XG4gICAgc3dpdGNoIChtb2RlKSB7XG4gICAgICBjYXNlICd3YW5kJzpcbiAgICAgICAgcmV0dXJuIHsgc2Vuc2l0aXZpdHk6IHRoaXMud2FuZFNlbnNpdGl2aXR5IH07XG4gICAgICBjYXNlICdicnVzaCc6XG4gICAgICAgIHJldHVybiB7IHNpemU6IHRoaXMuYnJ1c2hTaXplLCAuLi50aGlzLmJydXNoQ2xhc3MgfTtcbiAgICAgIGNhc2UgJ2VyYXNlVmVydGV4JzpcbiAgICAgICAgcmV0dXJuIHsgcmFkaXVzOiB0aGlzLnZlcnRleEVyYXNlclJhZGl1cyB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,167 @@
1
+ /** Bare keys that toggle a tool mode. */
2
+ const TOOL_KEYS = new Map([
3
+ ['p', 'pan'],
4
+ ['b', 'zoomToBox'],
5
+ ['r', 'drawrect'],
6
+ ['f', 'drawclosedpath'],
7
+ ['w', 'wand'],
8
+ ['e', 'eraseVertex'],
9
+ ['s', 'select'],
10
+ ['l', 'drawopenpath'],
11
+ ]);
12
+ /** A field the user types into: its keys are never shortcuts. */
13
+ function isTextField(t) {
14
+ return !!t && (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.isContentEditable);
15
+ }
16
+ /**
17
+ * The viewer's keyboard, wheel and context-menu handling: one window listener each,
18
+ * registered OUTSIDE the Angular zone (zone-patched, every event anywhere in the host
19
+ * app ran app-wide change detection) and re-entering it only to act.
20
+ *
21
+ * Keys: ←/→ step the slice; Enter/Escape resolve a SAM point prompt; Ctrl/Cmd+Z undo,
22
+ * Ctrl/Cmd+Shift+Z or +Y redo; bare Delete/Backspace/d delete the selected region,
23
+ * +/= and -/_ zoom, and single letters toggle tools (`TOOL_KEYS`). Any other
24
+ * modified key is left to the browser (Cmd/Ctrl+D must not delete a region).
25
+ *
26
+ * Keys are per viewer: with two live viewers (a main view and a pipeline preview)
27
+ * one Delete must not delete in both. A key goes to the viewer that holds focus, or
28
+ * — focus elsewhere — to the viewer the pointer last moved over; any other viewer
29
+ * ignores it (review CORE-2).
30
+ */
31
+ export class ViewerShortcuts {
32
+ /** Every attached instance, to find the one holding focus. */
33
+ static { this.live = new Set(); }
34
+ /** The viewer the pointer last moved over. */
35
+ static { this.lastHovered = null; }
36
+ constructor(host, zone) {
37
+ this.host = host;
38
+ this.zone = zone;
39
+ this.listeners = [];
40
+ }
41
+ /** Register the window listeners (outside the zone). */
42
+ attach() {
43
+ this.zone.runOutsideAngular(() => {
44
+ this.listen('contextmenu', (e) => this.onContextMenu(e), true);
45
+ this.listen('keydown', (e) => this.onKeydown(e), false);
46
+ this.listen('wheel', (e) => this.onWheel(e), { capture: true, passive: false });
47
+ // `pointerover` fires on element transitions only, not on every move.
48
+ this.listen('pointerover', (e) => {
49
+ if (this.contains(e.target))
50
+ ViewerShortcuts.lastHovered = this;
51
+ }, true);
52
+ });
53
+ ViewerShortcuts.live.add(this);
54
+ }
55
+ /** Remove every listener {@link attach} added. */
56
+ detach() {
57
+ ViewerShortcuts.live.delete(this);
58
+ if (ViewerShortcuts.lastHovered === this)
59
+ ViewerShortcuts.lastHovered = null;
60
+ for (const [type, listener, options] of this.listeners.splice(0)) {
61
+ window.removeEventListener(type, listener, options);
62
+ }
63
+ }
64
+ listen(type, listener, options) {
65
+ window.addEventListener(type, listener, options);
66
+ this.listeners.push([type, listener, options]);
67
+ }
68
+ contains(node) {
69
+ const el = this.host.hostElement ?? document.getElementById(this.host.plotDivName);
70
+ return !!node && !!el?.contains(node);
71
+ }
72
+ /** Whether this viewer takes keys now: it holds focus, or nothing does and the
73
+ * pointer was last over it. */
74
+ ownsKeys() {
75
+ const active = document.activeElement;
76
+ const focused = active && active !== document.body ? [...ViewerShortcuts.live].find((s) => s.contains(active)) : undefined;
77
+ return (focused ?? ViewerShortcuts.lastHovered) === this;
78
+ }
79
+ overPlot(event) {
80
+ return !!document.getElementById(this.host.plotDivName)?.contains(event.target);
81
+ }
82
+ run(fn) {
83
+ this.zone.run(fn);
84
+ }
85
+ onContextMenu(event) {
86
+ if (!this.overPlot(event))
87
+ return;
88
+ event.preventDefault();
89
+ event.stopImmediatePropagation();
90
+ this.run(() => this.host.openContextMenu(event));
91
+ }
92
+ onWheel(event) {
93
+ if (!this.overPlot(event))
94
+ return;
95
+ // A renderer that reads the scroll delta (napari, 3D scenes) keeps its own wheel:
96
+ // a FIXED zoom step per wheel event is far too sensitive there.
97
+ if (!this.host.wheelZooms())
98
+ return;
99
+ event.preventDefault();
100
+ event.stopImmediatePropagation();
101
+ if (event.deltaY < 0)
102
+ this.run(() => this.host.zoomIn());
103
+ else if (event.deltaY > 0)
104
+ this.run(() => this.host.zoomOut());
105
+ }
106
+ onKeydown(event) {
107
+ if (!this.ownsKeys())
108
+ return;
109
+ const host = this.host;
110
+ const target = event.target;
111
+ if (this.isSliceStepKey(event, target)) {
112
+ event.preventDefault();
113
+ this.run(() => host.stepSlice(event.key === 'ArrowRight' ? 1 : -1));
114
+ return;
115
+ }
116
+ if (isTextField(target))
117
+ return;
118
+ if (host.activeDragMode() === 'samPoint' && (event.key === 'Enter' || event.key === 'Escape')) {
119
+ this.run(() => host.resolveSamPrompt(event.key === 'Enter'));
120
+ return;
121
+ }
122
+ if (event.ctrlKey || event.metaKey) {
123
+ const k = event.key.toLowerCase();
124
+ if (k === 'z' && !event.shiftKey) {
125
+ event.preventDefault();
126
+ this.run(() => host.undo());
127
+ return;
128
+ }
129
+ if ((k === 'z' && event.shiftKey) || k === 'y') {
130
+ event.preventDefault();
131
+ this.run(() => host.redo());
132
+ return;
133
+ }
134
+ }
135
+ // The bare-key shortcuts must not fire on browser/OS shortcuts.
136
+ if (event.ctrlKey || event.metaKey || event.altKey)
137
+ return;
138
+ const key = event.key;
139
+ if (key === 'Delete' || key === 'Backspace' || key === 'd' || key === 'D')
140
+ this.run(() => host.deleteRegion());
141
+ else if (key === '+' || key === '=')
142
+ this.run(() => host.zoomIn());
143
+ else if (key === '-' || key === '_')
144
+ this.run(() => host.zoomOut());
145
+ else {
146
+ const mode = TOOL_KEYS.get(key);
147
+ if (mode)
148
+ this.run(() => host.toggleDragMode(mode));
149
+ }
150
+ }
151
+ /**
152
+ * ←/→ step the slice in the Image view, the same way the slider does — only for a
153
+ * loaded stack, and not while a form field or the slider itself has focus (it
154
+ * handles arrows natively; stepping here too would double-step). Up/Down are left
155
+ * to OpenSeadragon (panning).
156
+ */
157
+ isSliceStepKey(e, t) {
158
+ if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight')
159
+ return false;
160
+ if (!this.host.canStepSlice())
161
+ return false;
162
+ if (t && (/^(INPUT|TEXTAREA|SELECT)$/.test(t.tagName) || t.isContentEditable))
163
+ return false;
164
+ return !(t && (t.getAttribute('role') === 'slider' || t.closest('.p-slider')));
165
+ }
166
+ }
167
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlld2VyLXNob3J0Y3V0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdmlzdWFsaXplci92aWV3ZXItc2hvcnRjdXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQTJCQSx5Q0FBeUM7QUFDekMsTUFBTSxTQUFTLEdBQWdDLElBQUksR0FBRyxDQUFDO0lBQ3JELENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQztJQUNaLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQztJQUNsQixDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUM7SUFDakIsQ0FBQyxHQUFHLEVBQUUsZ0JBQWdCLENBQUM7SUFDdkIsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDO0lBQ2IsQ0FBQyxHQUFHLEVBQUUsYUFBYSxDQUFDO0lBQ3BCLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQztJQUNmLENBQUMsR0FBRyxFQUFFLGNBQWMsQ0FBQztDQUN0QixDQUFDLENBQUM7QUFFSCxpRUFBaUU7QUFDakUsU0FBUyxXQUFXLENBQUMsQ0FBcUI7SUFDeEMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxPQUFPLElBQUksQ0FBQyxDQUFDLE9BQU8sS0FBSyxVQUFVLElBQUksQ0FBQyxDQUFDLGlCQUFpQixDQUFDLENBQUM7QUFDM0YsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ0gsTUFBTSxPQUFPLGVBQWU7SUFDMUIsOERBQThEO2FBQ3RDLFNBQUksR0FBRyxJQUFJLEdBQUcsRUFBbUIsQUFBN0IsQ0FBOEI7SUFDMUQsOENBQThDO2FBQy9CLGdCQUFXLEdBQTJCLElBQUksQUFBL0IsQ0FBZ0M7SUFHMUQsWUFDbUIsSUFBa0IsRUFDbEIsSUFBWTtRQURaLFNBQUksR0FBSixJQUFJLENBQWM7UUFDbEIsU0FBSSxHQUFKLElBQUksQ0FBUTtRQUpkLGNBQVMsR0FBaUUsRUFBRSxDQUFDO0lBSzNGLENBQUM7SUFF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QUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2hDLElBQUksSUFBSTtnQkFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN0RCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssY0FBYyxDQUFDLENBQWdCLEVBQUUsQ0FBcUI7UUFDNUQsSUFBSSxDQUFDLENBQUMsR0FBRyxLQUFLLFdBQVcsSUFBSSxDQUFDLENBQUMsR0FBRyxLQUFLLFlBQVk7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUNsRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUM1QyxJQUFJLENBQUMsSUFBSSxDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLGlCQUFpQixDQUFDO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFDNUYsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxRQUFRLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5nWm9uZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG4vKiogV2hhdCB0aGUgc2hvcnRjdXRzIGRyaXZlOiB0aGUgdmlld2VyJ3MgYWN0aW9ucyBhbmQgdGhlIHN0YXRlIHRoZXkgZ2F0ZSBvbi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2hvcnRjdXRIb3N0IHtcbiAgLyoqIElkIG9mIHRoZSBwbG90IGRpdjsgdGhlIHdoZWVsIGFuZCB0aGUgY29udGV4dCBtZW51IGFjdCBvbmx5IG92ZXIgaXQuICovXG4gIHJlYWRvbmx5IHBsb3REaXZOYW1lOiBzdHJpbmc7XG4gIC8qKiBUaGUgdmlld2VyJ3Mgb3duIGVsZW1lbnQgKHRvb2xiYXIgKyBwbG90KTsgaXRzIGtleXMgYXJlIHNjb3BlZCB0byBpdC4gRmFsbHMgYmFja1xuICAgKiAgdG8gdGhlIHBsb3QgZGl2IHdoZW4gYWJzZW50LiAqL1xuICByZWFkb25seSBob3N0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgbnVsbDtcbiAgLyoqIFRoZSBhcm1lZCB0b29sIOKAlCBTQU0gcG9pbnQgbW9kZSB0YWtlcyBFbnRlciAvIEVzY2FwZS4gKi9cbiAgYWN0aXZlRHJhZ01vZGUoKTogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIOKGkC/ihpIgc3RlcCB0aGUgc2xpY2U6IGEgbG9hZGVkIHN0YWNrIGluIHRoZSBJbWFnZSB2aWV3LiAqL1xuICBjYW5TdGVwU2xpY2UoKTogYm9vbGVhbjtcbiAgLyoqIFRoZSB3aGVlbCBzdGVwcyB0aGUgem9vbTogYSAyRCB2aWV3IHdob3NlIHJlbmRlcmVyIGRvZXMgbm90IHJlYWQgdGhlIHdoZWVsIGl0c2VsZi4gKi9cbiAgd2hlZWxab29tcygpOiBib29sZWFuO1xuICBzdGVwU2xpY2UoZGVsdGE6IG51bWJlcik6IHZvaWQ7XG4gIC8qKiBTQU0gcG9pbnQgbW9kZTogY29tbWl0IChFbnRlcikgb3IgZGlzY2FyZCAoRXNjYXBlKSB0aGUgcHJvbXB0LiAqL1xuICByZXNvbHZlU2FtUHJvbXB0KGNvbW1pdDogYm9vbGVhbik6IHZvaWQ7XG4gIHVuZG8oKTogdm9pZDtcbiAgcmVkbygpOiB2b2lkO1xuICBkZWxldGVSZWdpb24oKTogdm9pZDtcbiAgem9vbUluKCk6IHZvaWQ7XG4gIHpvb21PdXQoKTogdm9pZDtcbiAgdG9nZ2xlRHJhZ01vZGUobW9kZTogc3RyaW5nKTogdm9pZDtcbiAgb3BlbkNvbnRleHRNZW51KGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZDtcbn1cblxuLyoqIEJhcmUga2V5cyB0aGF0IHRvZ2dsZSBhIHRvb2wgbW9kZS4gKi9cbmNvbnN0IFRPT0xfS0VZUzogUmVhZG9ubHlNYXA8c3RyaW5nLCBzdHJpbmc+ID0gbmV3IE1hcChbXG4gIFsncCcsICdwYW4nXSxcbiAgWydiJywgJ3pvb21Ub0JveCddLFxuICBbJ3InLCAnZHJhd3JlY3QnXSxcbiAgWydmJywgJ2RyYXdjbG9zZWRwYXRoJ10sXG4gIFsndycsICd3YW5kJ10sXG4gIFsnZScsICdlcmFzZVZlcnRleCddLFxuICBbJ3MnLCAnc2VsZWN0J10sXG4gIFsnbCcsICdkcmF3b3BlbnBhdGgnXSxcbl0pO1xuXG4vKiogQSBmaWVsZCB0aGUgdXNlciB0eXBlcyBpbnRvOiBpdHMga2V5cyBhcmUgbmV2ZXIgc2hvcnRjdXRzLiAqL1xuZnVuY3Rpb24gaXNUZXh0RmllbGQodDogSFRNTEVsZW1lbnQgfCBudWxsKTogYm9vbGVhbiB7XG4gIHJldHVybiAhIXQgJiYgKHQudGFnTmFtZSA9PT0gJ0lOUFVUJyB8fCB0LnRhZ05hbWUgPT09ICdURVhUQVJFQScgfHwgdC5pc0NvbnRlbnRFZGl0YWJsZSk7XG59XG5cbi8qKlxuICogVGhlIHZpZXdlcidzIGtleWJvYXJkLCB3aGVlbCBhbmQgY29udGV4dC1tZW51IGhhbmRsaW5nOiBvbmUgd2luZG93IGxpc3RlbmVyIGVhY2gsXG4gKiByZWdpc3RlcmVkIE9VVFNJREUgdGhlIEFuZ3VsYXIgem9uZSAoem9uZS1wYXRjaGVkLCBldmVyeSBldmVudCBhbnl3aGVyZSBpbiB0aGUgaG9zdFxuICogYXBwIHJhbiBhcHAtd2lkZSBjaGFuZ2UgZGV0ZWN0aW9uKSBhbmQgcmUtZW50ZXJpbmcgaXQgb25seSB0byBhY3QuXG4gKlxuICogS2V5czog4oaQL+KGkiBzdGVwIHRoZSBzbGljZTsgRW50ZXIvRXNjYXBlIHJlc29sdmUgYSBTQU0gcG9pbnQgcHJvbXB0OyBDdHJsL0NtZCtaIHVuZG8sXG4gKiBDdHJsL0NtZCtTaGlmdCtaIG9yICtZIHJlZG87IGJhcmUgRGVsZXRlL0JhY2tzcGFjZS9kIGRlbGV0ZSB0aGUgc2VsZWN0ZWQgcmVnaW9uLFxuICogKy89IGFuZCAtL18gem9vbSwgYW5kIHNpbmdsZSBsZXR0ZXJzIHRvZ2dsZSB0b29scyAoYFRPT0xfS0VZU2ApLiBBbnkgb3RoZXJcbiAqIG1vZGlmaWVkIGtleSBpcyBsZWZ0IHRvIHRoZSBicm93c2VyIChDbWQvQ3RybCtEIG11c3Qgbm90IGRlbGV0ZSBhIHJlZ2lvbikuXG4gKlxuICogS2V5cyBhcmUgcGVyIHZpZXdlcjogd2l0aCB0d28gbGl2ZSB2aWV3ZXJzIChhIG1haW4gdmlldyBhbmQgYSBwaXBlbGluZSBwcmV2aWV3KVxuICogb25lIERlbGV0ZSBtdXN0IG5vdCBkZWxldGUgaW4gYm90aC4gQSBrZXkgZ29lcyB0byB0aGUgdmlld2VyIHRoYXQgaG9sZHMgZm9jdXMsIG9yXG4gKiDigJQgZm9jdXMgZWxzZXdoZXJlIOKAlCB0byB0aGUgdmlld2VyIHRoZSBwb2ludGVyIGxhc3QgbW92ZWQgb3ZlcjsgYW55IG90aGVyIHZpZXdlclxuICogaWdub3JlcyBpdCAocmV2aWV3IENPUkUtMikuXG4gKi9cbmV4cG9ydCBjbGFzcyBWaWV3ZXJTaG9ydGN1dHMge1xuICAvKiogRXZlcnkgYXR0YWNoZWQgaW5zdGFuY2UsIHRvIGZpbmQgdGhlIG9uZSBob2xkaW5nIGZvY3VzLiAqL1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBsaXZlID0gbmV3IFNldDxWaWV3ZXJTaG9ydGN1dHM+KCk7XG4gIC8qKiBUaGUgdmlld2VyIHRoZSBwb2ludGVyIGxhc3QgbW92ZWQgb3Zlci4gKi9cbiAgcHJpdmF0ZSBzdGF0aWMgbGFzdEhvdmVyZWQ6IFZpZXdlclNob3J0Y3V0cyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHJlYWRvbmx5IGxpc3RlbmVyczogW3N0cmluZywgRXZlbnRMaXN0ZW5lciwgYm9vbGVhbiB8IEFkZEV2ZW50TGlzdGVuZXJPcHRpb25zXVtdID0gW107XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBob3N0OiBTaG9ydGN1dEhvc3QsXG4gICAgcHJpdmF0ZSByZWFkb25seSB6b25lOiBOZ1pvbmUsXG4gICkge31cblxuICAvKiogUmVnaXN0ZXIgdGhlIHdpbmRvdyBsaXN0ZW5lcnMgKG91dHNpZGUgdGhlIHpvbmUpLiAqL1xuICBhdHRhY2goKTogdm9pZCB7XG4gICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgIHRoaXMubGlzdGVuKCdjb250ZXh0bWVudScsIChlKSA9PiB0aGlzLm9uQ29udGV4dE1lbnUoZSBhcyBNb3VzZUV2ZW50KSwgdHJ1ZSk7XG4gICAgICB0aGlzLmxpc3Rlbigna2V5ZG93bicsIChlKSA9PiB0aGlzLm9uS2V5ZG93bihlIGFzIEtleWJvYXJkRXZlbnQpLCBmYWxzZSk7XG4gICAgICB0aGlzLmxpc3Rlbignd2hlZWwnLCAoZSkgPT4gdGhpcy5vbldoZWVsKGUgYXMgV2hlZWxFdmVudCksIHsgY2FwdHVyZTogdHJ1ZSwgcGFzc2l2ZTogZmFsc2UgfSk7XG4gICAgICAvLyBgcG9pbnRlcm92ZXJgIGZpcmVzIG9uIGVsZW1lbnQgdHJhbnNpdGlvbnMgb25seSwgbm90IG9uIGV2ZXJ5IG1vdmUuXG4gICAgICB0aGlzLmxpc3RlbihcbiAgICAgICAgJ3BvaW50ZXJvdmVyJyxcbiAgICAgICAgKGUpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5jb250YWlucyhlLnRhcmdldCBhcyBOb2RlKSkgVmlld2VyU2hvcnRjdXRzLmxhc3RIb3ZlcmVkID0gdGhpcztcbiAgICAgICAgfSxcbiAgICAgICAgdHJ1ZSxcbiAgICAgICk7XG4gICAgfSk7XG4gICAgVmlld2VyU2hvcnRjdXRzLmxpdmUuYWRkKHRoaXMpO1xuICB9XG5cbiAgLyoqIFJlbW92ZSBldmVyeSBsaXN0ZW5lciB7QGxpbmsgYXR0YWNofSBhZGRlZC4gKi9cbiAgZGV0YWNoKCk6IHZvaWQge1xuICAgIFZpZXdlclNob3J0Y3V0cy5saXZlLmRlbGV0ZSh0aGlzKTtcbiAgICBpZiAoVmlld2VyU2hvcnRjdXRzLmxhc3RIb3ZlcmVkID09PSB0aGlzKSBWaWV3ZXJTaG9ydGN1dHMubGFzdEhvdmVyZWQgPSBudWxsO1xuICAgIGZvciAoY29uc3QgW3R5cGUsIGxpc3RlbmVyLCBvcHRpb25zXSBvZiB0aGlzLmxpc3RlbmVycy5zcGxpY2UoMCkpIHtcbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGxpc3Rlbih0eXBlOiBzdHJpbmcsIGxpc3RlbmVyOiBFdmVudExpc3RlbmVyLCBvcHRpb25zOiBib29sZWFuIHwgQWRkRXZlbnRMaXN0ZW5lck9wdGlvbnMpOiB2b2lkIHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lciwgb3B0aW9ucyk7XG4gICAgdGhpcy5saXN0ZW5lcnMucHVzaChbdHlwZSwgbGlzdGVuZXIsIG9wdGlvbnNdKTtcbiAgfVxuXG4gIHByaXZhdGUgY29udGFpbnMobm9kZTogTm9kZSB8IG51bGwpOiBib29sZWFuIHtcbiAgICBjb25zdCBlbCA9IHRoaXMuaG9zdC5ob3N0RWxlbWVudCA/PyBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmhvc3QucGxvdERpdk5hbWUpO1xuICAgIHJldHVybiAhIW5vZGUgJiYgISFlbD8uY29udGFpbnMobm9kZSk7XG4gIH1cblxuICAvKiogV2hldGhlciB0aGlzIHZpZXdlciB0YWtlcyBrZXlzIG5vdzogaXQgaG9sZHMgZm9jdXMsIG9yIG5vdGhpbmcgZG9lcyBhbmQgdGhlXG4gICAqICBwb2ludGVyIHdhcyBsYXN0IG92ZXIgaXQuICovXG4gIHByaXZhdGUgb3duc0tleXMoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgYWN0aXZlID0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcbiAgICBjb25zdCBmb2N1c2VkID1cbiAgICAgIGFjdGl2ZSAmJiBhY3RpdmUgIT09IGRvY3VtZW50LmJvZHkgPyBbLi4uVmlld2VyU2hvcnRjdXRzLmxpdmVdLmZpbmQoKHMpID0+IHMuY29udGFpbnMoYWN0aXZlKSkgOiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIChmb2N1c2VkID8/IFZpZXdlclNob3J0Y3V0cy5sYXN0SG92ZXJlZCkgPT09IHRoaXM7XG4gIH1cblxuICBwcml2YXRlIG92ZXJQbG90KGV2ZW50OiBFdmVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuaG9zdC5wbG90RGl2TmFtZSk/LmNvbnRhaW5zKGV2ZW50LnRhcmdldCBhcyBOb2RlKTtcbiAgfVxuXG4gIHByaXZhdGUgcnVuKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy56b25lLnJ1bihmbik7XG4gIH1cblxuICBwcml2YXRlIG9uQ29udGV4dE1lbnUoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMub3ZlclBsb3QoZXZlbnQpKSByZXR1cm47XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLnJ1bigoKSA9PiB0aGlzLmhvc3Qub3BlbkNvbnRleHRNZW51KGV2ZW50KSk7XG4gIH1cblxuICBwcml2YXRlIG9uV2hlZWwoZXZlbnQ6IFdoZWVsRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMub3ZlclBsb3QoZXZlbnQpKSByZXR1cm47XG4gICAgLy8gQSByZW5kZXJlciB0aGF0IHJlYWRzIHRoZSBzY3JvbGwgZGVsdGEgKG5hcGFyaSwgM0Qgc2NlbmVzKSBrZWVwcyBpdHMgb3duIHdoZWVsOlxuICAgIC8vIGEgRklYRUQgem9vbSBzdGVwIHBlciB3aGVlbCBldmVudCBpcyBmYXIgdG9vIHNlbnNpdGl2ZSB0aGVyZS5cbiAgICBpZiAoIXRoaXMuaG9zdC53aGVlbFpvb21zKCkpIHJldHVybjtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgIGlmIChldmVudC5kZWx0YVkgPCAwKSB0aGlzLnJ1bigoKSA9PiB0aGlzLmhvc3Quem9vbUluKCkpO1xuICAgIGVsc2UgaWYgKGV2ZW50LmRlbHRhWSA+IDApIHRoaXMucnVuKCgpID0+IHRoaXMuaG9zdC56b29tT3V0KCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBvbktleWRvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMub3duc0tleXMoKSkgcmV0dXJuO1xuICAgIGNvbnN0IGhvc3QgPSB0aGlzLmhvc3Q7XG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50IHwgbnVsbDtcbiAgICBpZiAodGhpcy5pc1NsaWNlU3RlcEtleShldmVudCwgdGFyZ2V0KSkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHRoaXMucnVuKCgpID0+IGhvc3Quc3RlcFNsaWNlKGV2ZW50LmtleSA9PT0gJ0Fycm93UmlnaHQnID8gMSA6IC0xKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChpc1RleHRGaWVsZCh0YXJnZXQpKSByZXR1cm47XG4gICAgaWYgKGhvc3QuYWN0aXZlRHJhZ01vZGUoKSA9PT0gJ3NhbVBvaW50JyAmJiAoZXZlbnQua2V5ID09PSAnRW50ZXInIHx8IGV2ZW50LmtleSA9PT0gJ0VzY2FwZScpKSB7XG4gICAgICB0aGlzLnJ1bigoKSA9PiBob3N0LnJlc29sdmVTYW1Qcm9tcHQoZXZlbnQua2V5ID09PSAnRW50ZXInKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChldmVudC5jdHJsS2V5IHx8IGV2ZW50Lm1ldGFLZXkpIHtcbiAgICAgIGNvbnN0IGsgPSBldmVudC5rZXkudG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmIChrID09PSAneicgJiYgIWV2ZW50LnNoaWZ0S2V5KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMucnVuKCgpID0+IGhvc3QudW5kbygpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKChrID09PSAneicgJiYgZXZlbnQuc2hpZnRLZXkpIHx8IGsgPT09ICd5Jykge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLnJ1bigoKSA9PiBob3N0LnJlZG8oKSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gVGhlIGJhcmUta2V5IHNob3J0Y3V0cyBtdXN0IG5vdCBmaXJlIG9uIGJyb3dzZXIvT1Mgc2hvcnRjdXRzLlxuICAgIGlmIChldmVudC5jdHJsS2V5IHx8IGV2ZW50Lm1ldGFLZXkgfHwgZXZlbnQuYWx0S2V5KSByZXR1cm47XG4gICAgY29uc3Qga2V5ID0gZXZlbnQua2V5O1xuICAgIGlmIChrZXkgPT09ICdEZWxldGUnIHx8IGtleSA9PT0gJ0JhY2tzcGFjZScgfHwga2V5ID09PSAnZCcgfHwga2V5ID09PSAnRCcpIHRoaXMucnVuKCgpID0+IGhvc3QuZGVsZXRlUmVnaW9uKCkpO1xuICAgIGVsc2UgaWYgKGtleSA9PT0gJysnIHx8IGtleSA9PT0gJz0nKSB0aGlzLnJ1bigoKSA9PiBob3N0Lnpvb21JbigpKTtcbiAgICBlbHNlIGlmIChrZXkgPT09ICctJyB8fCBrZXkgPT09ICdfJykgdGhpcy5ydW4oKCkgPT4gaG9zdC56b29tT3V0KCkpO1xuICAgIGVsc2Uge1xuICAgICAgY29uc3QgbW9kZSA9IFRPT0xfS0VZUy5nZXQoa2V5KTtcbiAgICAgIGlmIChtb2RlKSB0aGlzLnJ1bigoKSA9PiBob3N0LnRvZ2dsZURyYWdNb2RlKG1vZGUpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog4oaQL+KGkiBzdGVwIHRoZSBzbGljZSBpbiB0aGUgSW1hZ2UgdmlldywgdGhlIHNhbWUgd2F5IHRoZSBzbGlkZXIgZG9lcyDigJQgb25seSBmb3IgYVxuICAgKiBsb2FkZWQgc3RhY2ssIGFuZCBub3Qgd2hpbGUgYSBmb3JtIGZpZWxkIG9yIHRoZSBzbGlkZXIgaXRzZWxmIGhhcyBmb2N1cyAoaXRcbiAgICogaGFuZGxlcyBhcnJvd3MgbmF0aXZlbHk7IHN0ZXBwaW5nIGhlcmUgdG9vIHdvdWxkIGRvdWJsZS1zdGVwKS4gVXAvRG93biBhcmUgbGVmdFxuICAgKiB0byBPcGVuU2VhZHJhZ29uIChwYW5uaW5nKS5cbiAgICovXG4gIHByaXZhdGUgaXNTbGljZVN0ZXBLZXkoZTogS2V5Ym9hcmRFdmVudCwgdDogSFRNTEVsZW1lbnQgfCBudWxsKTogYm9vbGVhbiB7XG4gICAgaWYgKGUua2V5ICE9PSAnQXJyb3dMZWZ0JyAmJiBlLmtleSAhPT0gJ0Fycm93UmlnaHQnKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKCF0aGlzLmhvc3QuY2FuU3RlcFNsaWNlKCkpIHJldHVybiBmYWxzZTtcbiAgICBpZiAodCAmJiAoL14oSU5QVVR8VEVYVEFSRUF8U0VMRUNUKSQvLnRlc3QodC50YWdOYW1lKSB8fCB0LmlzQ29udGVudEVkaXRhYmxlKSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiAhKHQgJiYgKHQuZ2V0QXR0cmlidXRlKCdyb2xlJykgPT09ICdzbGlkZXInIHx8IHQuY2xvc2VzdCgnLnAtc2xpZGVyJykpKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,119 @@
1
+ import { PlotType } from '../contracts/plot-type';
2
+ import { MultiPolygon, Polygon, Rectangle } from '../models/region';
3
+ const ACTIVE = 'context-menu-active';
4
+ /** The live regions at `indices` (stale indices dropped). */
5
+ export function regionsAt(regions, indices) {
6
+ return indices.map((i) => regions[i]).filter((r) => !!r);
7
+ }
8
+ /** Regions eligible for set-ops: closed areas (rect / closed polygon / multi-polygon),
9
+ * excluding intensity-profile lines. */
10
+ export function opEligible(regions) {
11
+ return regions.filter((r) => r.kind !== 'profile' &&
12
+ (r.bounds instanceof Rectangle ||
13
+ r.bounds instanceof MultiPolygon ||
14
+ (r.bounds instanceof Polygon && r.bounds.closed !== false)));
15
+ }
16
+ /**
17
+ * The right-click menu: the selected-region actions lead (2D only), then the
18
+ * viewport and tool toggles for a 2D view, or the camera modes for a 3D scene. The
19
+ * armed mode is highlighted.
20
+ */
21
+ export function buildContextMenu(state, actions) {
22
+ if (!state.isHeatmap)
23
+ return surface3dItems(state, actions);
24
+ const active = state.activeDragMode;
25
+ const toggle = (label, icon, mode) => ({
26
+ label,
27
+ icon,
28
+ styleClass: active === mode ? ACTIVE : '',
29
+ command: () => actions.toggleDragMode(mode),
30
+ });
31
+ const isImageView = state.basePlotType === PlotType.IMAGE;
32
+ const items = [];
33
+ const regionActions = buildRegionActionItems(state, actions);
34
+ if (regionActions.length)
35
+ items.push(...regionActions, { separator: true });
36
+ items.push({ label: 'Autoscale', icon: 'pi pi-window-maximize', command: () => actions.autoscaleImage() }, { separator: true });
37
+ // 'Zoom selection' is Plotly's rubber-band zoom; it doesn't apply to the
38
+ // OpenSeadragon-backed Image view (use 'Zoom to box' there instead).
39
+ if (!isImageView)
40
+ items.push(toggle('Zoom selection', 'pi pi-search', 'zoom'));
41
+ items.push(toggle('Zoom to box', 'zoom-box-off-icon', 'zoomToBox'), toggle('Pan', 'pi pi-arrows-alt', 'pan'), { label: 'Zoom in', icon: 'pi pi-search-plus', command: () => actions.zoomIn() }, { label: 'Zoom out', icon: 'pi pi-search-minus', command: () => actions.zoomOut() }, { separator: true }, toggle('Select', 'pi pi-arrow-up-right', 'select'), toggle('Freeform', 'pi pi-pencil', 'drawclosedpath'), toggle('Brush', 'brush-icon', 'brush'), toggle('Polyline', 'polyline-icon', 'drawopenpath'), toggle('Rectangle', 'pi pi-stop', 'drawrect'), toggle('Wand', 'wand-icon', 'wand'), toggle('Vertex eraser', 'pi pi-eraser', 'eraseVertex'));
42
+ // Vertex editing runs on the OpenSeadragon overlay, which backs the Image plot
43
+ // type. Hidden for other 2D types (Plotly), where these modes are no-ops.
44
+ if (isImageView) {
45
+ items.push(toggle('Polygon (click vertices)', 'polygon-vertices-icon', 'drawpolygon'), toggle('Add vertex', 'vertex-add-icon', 'addpoint'), toggle('Delete vertex', 'vertex-delete-icon', 'deletepoint'));
46
+ }
47
+ return items;
48
+ }
49
+ /** A 3D scene's camera modes and reset. */
50
+ function surface3dItems(state, actions) {
51
+ const mode = (label, icon, m) => ({
52
+ label,
53
+ icon,
54
+ styleClass: state.activeSurface3dMode === m ? ACTIVE : '',
55
+ command: () => actions.toggleSurface3dMode(m),
56
+ });
57
+ return [
58
+ mode('Zoom', 'pi pi-search', 'zoom'),
59
+ mode('Pan', 'pi pi-arrows-alt', 'pan'),
60
+ mode('Orbital rotation', 'pi pi-globe', 'orbit'),
61
+ mode('Turntable rotation', 'pi pi-sync', 'turntable'),
62
+ { separator: true },
63
+ { label: 'Reset camera', icon: 'pi pi-home', command: () => actions.resetSurfaceCamera() },
64
+ ];
65
+ }
66
+ /**
67
+ * Immediate region actions on the current selection (jit-ui#85): merge, ungroup,
68
+ * inverse, simplify, the Bézier conversions, and delete — the one-shot geometry
69
+ * transforms, grouped apart from the tool/mode toggles and shown only when something
70
+ * is selected. Each item is gated on what the selection supports. "Select all" leads
71
+ * whenever the image has regions.
72
+ */
73
+ export function buildRegionActionItems(state, actions) {
74
+ if (!state.regions.some((r) => r.kind !== 'profile'))
75
+ return [];
76
+ const items = [
77
+ { label: 'Select all regions', icon: 'pi pi-check-square', command: () => actions.selectAllRegions() },
78
+ ];
79
+ const selected = regionsAt(state.regions, state.selectedIndices);
80
+ if (selected.length === 0)
81
+ return items;
82
+ const eligible = opEligible(selected);
83
+ if (eligible.length >= 2) {
84
+ items.push({ label: 'Merge / group', icon: 'pi pi-link', command: () => actions.mergeRegions() });
85
+ }
86
+ if (selected.some((r) => state.canUngroup(r))) {
87
+ items.push({ label: 'Ungroup', icon: 'pi pi-sitemap', command: () => actions.ungroupRegions() });
88
+ }
89
+ if (eligible.length >= 1) {
90
+ items.push({ label: 'Inverse', icon: 'pi pi-clone', command: () => actions.inverseRegions() }, {
91
+ label: 'Simplify',
92
+ icon: 'pi pi-chart-line',
93
+ items: [
94
+ { label: 'Light (1 px)', command: () => actions.simplifyRegions(1) },
95
+ { label: 'Medium (3 px)', command: () => actions.simplifyRegions(3) },
96
+ { label: 'Strong (8 px)', command: () => actions.simplifyRegions(8) },
97
+ { separator: true },
98
+ { label: 'Custom…', command: () => actions.openSimplifyDialog() },
99
+ ],
100
+ });
101
+ }
102
+ // Bézier conversions are vertex-level edits — Image (OpenSeadragon) view only —
103
+ // gated on the selection's current form.
104
+ if (state.basePlotType === PlotType.IMAGE) {
105
+ if (selected.some((r) => (r.bounds instanceof Polygon && !r.bounds.bezier) || r.bounds instanceof Rectangle)) {
106
+ items.push({ label: 'Convert to Bézier', icon: 'to-bezier-icon', command: () => actions.toBezierRegion() });
107
+ }
108
+ if (selected.some((r) => r.bounds instanceof Polygon && r.bounds.bezier)) {
109
+ items.push({
110
+ label: 'Convert to polygon',
111
+ icon: 'to-polygon-icon',
112
+ command: () => actions.toPolygonRegion(),
113
+ });
114
+ }
115
+ }
116
+ items.push({ label: 'Delete region', icon: 'pi pi-trash', command: () => actions.deleteRegion() });
117
+ return items;
118
+ }
119
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlzdWFsaXplci1jb250ZXh0LW1lbnUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Zpc3VhbGl6ZXIvdmlzdWFsaXplci1jb250ZXh0LW1lbnUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBVSxNQUFNLGtCQUFrQixDQUFDO0FBcUM1RSxNQUFNLE1BQU0sR0FBRyxxQkFBcUIsQ0FBQztBQUVyQyw2REFBNkQ7QUFDN0QsTUFBTSxVQUFVLFNBQVMsQ0FBQyxPQUFpQixFQUFFLE9BQWlCO0lBQzVELE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDeEUsQ0FBQztBQUVEO3lDQUN5QztBQUN6QyxNQUFNLFVBQVUsVUFBVSxDQUFDLE9BQWlCO0lBQzFDLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FDbkIsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUNKLENBQUMsQ0FBQyxJQUFJLEtBQUssU0FBUztRQUNwQixDQUFDLENBQUMsQ0FBQyxNQUFNLFlBQVksU0FBUztZQUM1QixDQUFDLENBQUMsTUFBTSxZQUFZLFlBQVk7WUFDaEMsQ0FBQyxDQUFDLENBQUMsTUFBTSxZQUFZLE9BQU8sSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUNoRSxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsS0FBdUIsRUFBRSxPQUEyQjtJQUNuRixJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVM7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RUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLFlBQVksT0FBTyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUN6RSxLQUFLLENBQUMsSUFBSSxDQUFDO2dCQUNULEtBQUssRUFBRSxvQkFBb0I7Z0JBQzNCLElBQUksRUFBRSxpQkFBaUI7Z0JBQ3ZCLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsZUFBZSxFQUFFO2FBQ3pDLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0lBQ0QsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNuRyxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNZW51SXRlbSB9IGZyb20gJ3ByaW1lbmcvYXBpJztcblxuaW1wb3J0IHsgUGxvdFR5cGUgfSBmcm9tICcuLi9jb250cmFjdHMvcGxvdC10eXBlJztcbmltcG9ydCB7IE11bHRpUG9seWdvbiwgUG9seWdvbiwgUmVjdGFuZ2xlLCBSZWdpb24gfSBmcm9tICcuLi9tb2RlbHMvcmVnaW9uJztcblxuLyoqIFdoYXQgdGhlIHJpZ2h0LWNsaWNrIG1lbnUgaXMgYnVpbHQgZnJvbTogdGhlIHZpZXcsIHRoZSBhcm1lZCBtb2RlcyBhbmQgdGhlIHJlZ2lvbnMuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbnRleHRNZW51U3RhdGUge1xuICAvKiogMkQgdmlldyAocmVnaW9uIHRvb2xzLCBzdGVwIHpvb20pIHZzIGEgM0Qgc2NlbmUgKGNhbWVyYSBtb2RlcykuICovXG4gIGlzSGVhdG1hcDogYm9vbGVhbjtcbiAgLyoqIFRoZSBidWlsdC1pbiB0eXBlIG9uIHNjcmVlbjsgdGhlIEltYWdlIHZpZXcgYWRkcyB0aGUgdmVydGV4IGFuZCBCw6l6aWVyIGl0ZW1zLiAqL1xuICBiYXNlUGxvdFR5cGU6IFBsb3RUeXBlO1xuICBhY3RpdmVEcmFnTW9kZTogc3RyaW5nIHwgbnVsbDtcbiAgYWN0aXZlU3VyZmFjZTNkTW9kZTogc3RyaW5nO1xuICAvKiogRXZlcnkgcmVnaW9uIG9uIHRoZSBpbWFnZSAoaW50ZW5zaXR5LXByb2ZpbGUgbGluZXMgaW5jbHVkZWQpLiAqL1xuICByZWdpb25zOiBSZWdpb25bXTtcbiAgLyoqIFRoZSBzZWxlY3Rpb24sIGFzIGluZGljZXMgaW50byB7QGxpbmsgcmVnaW9uc30uICovXG4gIHNlbGVjdGVkSW5kaWNlczogbnVtYmVyW107XG4gIC8qKiBXaGV0aGVyIGEgcmVnaW9uIGlzIGEgbXVsdGktcGFydCByZWdpb24gdGhhdCBjYW4gYmUgc3BsaXQgYmFjayBpbnRvIHBhcnRzLiAqL1xuICBjYW5Vbmdyb3VwKHJlZ2lvbjogUmVnaW9uKTogYm9vbGVhbjtcbn1cblxuLyoqIFdoYXQgdGhlIG1lbnUncyBpdGVtcyBkbyAodGhlIHZpZXdlcidzIG93biB0b29sYmFyIGhhbmRsZXJzKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29udGV4dE1lbnVBY3Rpb25zIHtcbiAgYXV0b3NjYWxlSW1hZ2UoKTogdm9pZDtcbiAgem9vbUluKCk6IHZvaWQ7XG4gIHpvb21PdXQoKTogdm9pZDtcbiAgdG9nZ2xlRHJhZ01vZGUobW9kZTogc3RyaW5nKTogdm9pZDtcbiAgdG9nZ2xlU3VyZmFjZTNkTW9kZShtb2RlOiBzdHJpbmcpOiB2b2lkO1xuICByZXNldFN1cmZhY2VDYW1lcmEoKTogdm9pZDtcbiAgc2VsZWN0QWxsUmVnaW9ucygpOiB2b2lkO1xuICBtZXJnZVJlZ2lvbnMoKTogdm9pZDtcbiAgdW5ncm91cFJlZ2lvbnMoKTogdm9pZDtcbiAgaW52ZXJzZVJlZ2lvbnMoKTogdm9pZDtcbiAgc2ltcGxpZnlSZWdpb25zKHRocmVzaG9sZFB4OiBudW1iZXIpOiB2b2lkO1xuICBvcGVuU2ltcGxpZnlEaWFsb2coKTogdm9pZDtcbiAgdG9CZXppZXJSZWdpb24oKTogdm9pZDtcbiAgdG9Qb2x5Z29uUmVnaW9uKCk6IHZvaWQ7XG4gIGRlbGV0ZVJlZ2lvbigpOiB2b2lkO1xufVxuXG5jb25zdCBBQ1RJVkUgPSAnY29udGV4dC1tZW51LWFjdGl2ZSc7XG5cbi8qKiBUaGUgbGl2ZSByZWdpb25zIGF0IGBpbmRpY2VzYCAoc3RhbGUgaW5kaWNlcyBkcm9wcGVkKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpb25zQXQocmVnaW9uczogUmVnaW9uW10sIGluZGljZXM6IG51bWJlcltdKTogUmVnaW9uW10ge1xuICByZXR1cm4gaW5kaWNlcy5tYXAoKGkpID0+IHJlZ2lvbnNbaV0pLmZpbHRlcigocik6IHIgaXMgUmVnaW9uID0+ICEhcik7XG59XG5cbi8qKiBSZWdpb25zIGVsaWdpYmxlIGZvciBzZXQtb3BzOiBjbG9zZWQgYXJlYXMgKHJlY3QgLyBjbG9zZWQgcG9seWdvbiAvIG11bHRpLXBvbHlnb24pLFxuICogIGV4Y2x1ZGluZyBpbnRlbnNpdHktcHJvZmlsZSBsaW5lcy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvcEVsaWdpYmxlKHJlZ2lvbnM6IFJlZ2lvbltdKTogUmVnaW9uW10ge1xuICByZXR1cm4gcmVnaW9ucy5maWx0ZXIoXG4gICAgKHIpID0+XG4gICAgICByLmtpbmQgIT09ICdwcm9maWxlJyAmJlxuICAgICAgKHIuYm91bmRzIGluc3RhbmNlb2YgUmVjdGFuZ2xlIHx8XG4gICAgICAgIHIuYm91bmRzIGluc3RhbmNlb2YgTXVsdGlQb2x5Z29uIHx8XG4gICAgICAgIChyLmJvdW5kcyBpbnN0YW5jZW9mIFBvbHlnb24gJiYgci5ib3VuZHMuY2xvc2VkICE9PSBmYWxzZSkpLFxuICApO1xufVxuXG4vKipcbiAqIFRoZSByaWdodC1jbGljayBtZW51OiB0aGUgc2VsZWN0ZWQtcmVnaW9uIGFjdGlvbnMgbGVhZCAoMkQgb25seSksIHRoZW4gdGhlXG4gKiB2aWV3cG9ydCBhbmQgdG9vbCB0b2dnbGVzIGZvciBhIDJEIHZpZXcsIG9yIHRoZSBjYW1lcmEgbW9kZXMgZm9yIGEgM0Qgc2NlbmUuIFRoZVxuICogYXJtZWQgbW9kZSBpcyBoaWdobGlnaHRlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkQ29udGV4dE1lbnUoc3RhdGU6IENvbnRleHRNZW51U3RhdGUsIGFjdGlvbnM6IENvbnRleHRNZW51QWN0aW9ucyk6IE1lbnVJdGVtW10ge1xuICBpZiAoIXN0YXRlLmlzSGVhdG1hcCkgcmV0dXJuIHN1cmZhY2UzZEl0ZW1zKHN0YXRlLCBhY3Rpb25zKTtcbiAgY29uc3QgYWN0aXZlID0gc3RhdGUuYWN0aXZlRHJhZ01vZGU7XG4gIGNvbnN0IHRvZ2dsZSA9IChsYWJlbDogc3RyaW5nLCBpY29uOiBzdHJpbmcsIG1vZGU6IHN0cmluZyk6IE1lbnVJdGVtID0+ICh7XG4gICAgbGFiZWwsXG4gICAgaWNvbixcbiAgICBzdHlsZUNsYXNzOiBhY3RpdmUgPT09IG1vZGUgPyBBQ1RJVkUgOiAnJyxcbiAgICBjb21tYW5kOiAoKSA9PiBhY3Rpb25zLnRvZ2dsZURyYWdNb2RlKG1vZGUpLFxuICB9KTtcbiAgY29uc3QgaXNJbWFnZVZpZXcgPSBzdGF0ZS5iYXNlUGxvdFR5cGUgPT09IFBsb3RUeXBlLklNQUdFO1xuICBjb25zdCBpdGVtczogTWVudUl0ZW1bXSA9IFtdO1xuICBjb25zdCByZWdpb25BY3Rpb25zID0gYnVpbGRSZWdpb25BY3Rpb25JdGVtcyhzdGF0ZSwgYWN0aW9ucyk7XG4gIGlmIChyZWdpb25BY3Rpb25zLmxlbmd0aCkgaXRlbXMucHVzaCguLi5yZWdpb25BY3Rpb25zLCB7IHNlcGFyYXRvcjogdHJ1ZSB9KTtcbiAgaXRlbXMucHVzaChcbiAgICB7IGxhYmVsOiAnQXV0b3NjYWxlJywgaWNvbjogJ3BpIHBpLXdpbmRvdy1tYXhpbWl6ZScsIGNvbW1hbmQ6ICgpID0+IGFjdGlvbnMuYXV0b3NjYWxlSW1hZ2UoKSB9LFxuICAgIHsgc2VwYXJhdG9yOiB0cnVlIH0sXG4gICk7XG4gIC8vICdab29tIHNlbGVjdGlvbicgaXMgUGxvdGx5J3MgcnViYmVyLWJhbmQgem9vbTsgaXQgZG9lc24ndCBhcHBseSB0byB0aGVcbiAgLy8gT3BlblNlYWRyYWdvbi1iYWNrZWQgSW1hZ2UgdmlldyAodXNlICdab29tIHRvIGJveCcgdGhlcmUgaW5zdGVhZCkuXG4gIGlmICghaXNJbWFnZVZpZXcpIGl0ZW1zLnB1c2godG9nZ2xlKCdab29tIHNlbGVjdGlvbicsICdwaSBwaS1zZWFyY2gnLCAnem9vbScpKTtcbiAgaXRlbXMucHVzaChcbiAgICB0b2dnbGUoJ1pvb20gdG8gYm94JywgJ3pvb20tYm94LW9mZi1pY29uJywgJ3pvb21Ub0JveCcpLFxuICAgIHRvZ2dsZSgnUGFuJywgJ3BpIHBpLWFycm93cy1hbHQnLCAncGFuJyksXG4gICAgeyBsYWJlbDogJ1pvb20gaW4nLCBpY29uOiAncGkgcGktc2VhcmNoLXBsdXMnLCBjb21tYW5kOiAoKSA9PiBhY3Rpb25zLnpvb21JbigpIH0sXG4gICAgeyBsYWJlbDogJ1pvb20gb3V0JywgaWNvbjogJ3BpIHBpLXNlYXJjaC1taW51cycsIGNvbW1hbmQ6ICgpID0+IGFjdGlvbnMuem9vbU91dCgpIH0sXG4gICAgeyBzZXBhcmF0b3I6IHRydWUgfSxcbiAgICB0b2dnbGUoJ1NlbGVjdCcsICdwaSBwaS1hcnJvdy11cC1yaWdodCcsICdzZWxlY3QnKSxcbiAgICB0b2dnbGUoJ0ZyZWVmb3JtJywgJ3BpIHBpLXBlbmNpbCcsICdkcmF3Y2xvc2VkcGF0aCcpLFxuICAgIHRvZ2dsZSgnQnJ1c2gnLCAnYnJ1c2gtaWNvbicsICdicnVzaCcpLFxuICAgIHRvZ2dsZSgnUG9seWxpbmUnLCAncG9seWxpbmUtaWNvbicsICdkcmF3b3BlbnBhdGgnKSxcbiAgICB0b2dnbGUoJ1JlY3RhbmdsZScsICdwaSBwaS1zdG9wJywgJ2RyYXdyZWN0JyksXG4gICAgdG9nZ2xlKCdXYW5kJywgJ3dhbmQtaWNvbicsICd3YW5kJyksXG4gICAgdG9nZ2xlKCdWZXJ0ZXggZXJhc2VyJywgJ3BpIHBpLWVyYXNlcicsICdlcmFzZVZlcnRleCcpLFxuICApO1xuICAvLyBWZXJ0ZXggZWRpdGluZyBydW5zIG9uIHRoZSBPcGVuU2VhZHJhZ29uIG92ZXJsYXksIHdoaWNoIGJhY2tzIHRoZSBJbWFnZSBwbG90XG4gIC8vIHR5cGUuIEhpZGRlbiBmb3Igb3RoZXIgMkQgdHlwZXMgKFBsb3RseSksIHdoZXJlIHRoZXNlIG1vZGVzIGFyZSBuby1vcHMuXG4gIGlmIChpc0ltYWdlVmlldykge1xuICAgIGl0ZW1zLnB1c2goXG4gICAgICB0b2dnbGUoJ1BvbHlnb24gKGNsaWNrIHZlcnRpY2VzKScsICdwb2x5Z29uLXZlcnRpY2VzLWljb24nLCAnZHJhd3BvbHlnb24nKSxcbiAgICAgIHRvZ2dsZSgnQWRkIHZlcnRleCcsICd2ZXJ0ZXgtYWRkLWljb24nLCAnYWRkcG9pbnQnKSxcbiAgICAgIHRvZ2dsZSgnRGVsZXRlIHZlcnRleCcsICd2ZXJ0ZXgtZGVsZXRlLWljb24nLCAnZGVsZXRlcG9pbnQnKSxcbiAgICApO1xuICB9XG4gIHJldHVybiBpdGVtcztcbn1cblxuLyoqIEEgM0Qgc2NlbmUncyBjYW1lcmEgbW9kZXMgYW5kIHJlc2V0LiAqL1xuZnVuY3Rpb24gc3VyZmFjZTNkSXRlbXMoc3RhdGU6IENvbnRleHRNZW51U3RhdGUsIGFjdGlvbnM6IENvbnRleHRNZW51QWN0aW9ucyk6IE1lbnVJdGVtW10ge1xuICBjb25zdCBtb2RlID0gKGxhYmVsOiBzdHJpbmcsIGljb246IHN0cmluZywgbTogc3RyaW5nKTogTWVudUl0ZW0gPT4gKHtcbiAgICBsYWJlbCxcbiAgICBpY29uLFxuICAgIHN0eWxlQ2xhc3M6IHN0YXRlLmFjdGl2ZVN1cmZhY2UzZE1vZGUgPT09IG0gPyBBQ1RJVkUgOiAnJyxcbiAgICBjb21tYW5kOiAoKSA9PiBhY3Rpb25zLnRvZ2dsZVN1cmZhY2UzZE1vZGUobSksXG4gIH0pO1xuICByZXR1cm4gW1xuICAgIG1vZGUoJ1pvb20nLCAncGkgcGktc2VhcmNoJywgJ3pvb20nKSxcbiAgICBtb2RlKCdQYW4nLCAncGkgcGktYXJyb3dzLWFsdCcsICdwYW4nKSxcbiAgICBtb2RlKCdPcmJpdGFsIHJvdGF0aW9uJywgJ3BpIHBpLWdsb2JlJywgJ29yYml0JyksXG4gICAgbW9kZSgnVHVybnRhYmxlIHJvdGF0aW9uJywgJ3BpIHBpLXN5bmMnLCAndHVybnRhYmxlJyksXG4gICAgeyBzZXBhcmF0b3I6IHRydWUgfSxcbiAgICB7IGxhYmVsOiAnUmVzZXQgY2FtZXJhJywgaWNvbjogJ3BpIHBpLWhvbWUnLCBjb21tYW5kOiAoKSA9PiBhY3Rpb25zLnJlc2V0U3VyZmFjZUNhbWVyYSgpIH0sXG4gIF07XG59XG5cbi8qKlxuICogSW1tZWRpYXRlIHJlZ2lvbiBhY3Rpb25zIG9uIHRoZSBjdXJyZW50IHNlbGVjdGlvbiAoaml0LXVpIzg1KTogbWVyZ2UsIHVuZ3JvdXAsXG4gKiBpbnZlcnNlLCBzaW1wbGlmeSwgdGhlIELDqXppZXIgY29udmVyc2lvbnMsIGFuZCBkZWxldGUg4oCUIHRoZSBvbmUtc2hvdCBnZW9tZXRyeVxuICogdHJhbnNmb3JtcywgZ3JvdXBlZCBhcGFydCBmcm9tIHRoZSB0b29sL21vZGUgdG9nZ2xlcyBhbmQgc2hvd24gb25seSB3aGVuIHNvbWV0aGluZ1xuICogaXMgc2VsZWN0ZWQuIEVhY2ggaXRlbSBpcyBnYXRlZCBvbiB3aGF0IHRoZSBzZWxlY3Rpb24gc3VwcG9ydHMuIFwiU2VsZWN0IGFsbFwiIGxlYWRzXG4gKiB3aGVuZXZlciB0aGUgaW1hZ2UgaGFzIHJlZ2lvbnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFJlZ2lvbkFjdGlvbkl0ZW1zKHN0YXRlOiBDb250ZXh0TWVudVN0YXRlLCBhY3Rpb25zOiBDb250ZXh0TWVudUFjdGlvbnMpOiBNZW51SXRlbVtdIHtcbiAgaWYgKCFzdGF0ZS5yZWdpb25zLnNvbWUoKHIpID0+IHIua2luZCAhPT0gJ3Byb2ZpbGUnKSkgcmV0dXJuIFtdO1xuICBjb25zdCBpdGVtczogTWVudUl0ZW1bXSA9IFtcbiAgICB7IGxhYmVsOiAnU2VsZWN0IGFsbCByZWdpb25zJywgaWNvbjogJ3BpIHBpLWNoZWNrLXNxdWFyZScsIGNvbW1hbmQ6ICgpID0+IGFjdGlvbnMuc2VsZWN0QWxsUmVnaW9ucygpIH0sXG4gIF07XG4gIGNvbnN0IHNlbGVjdGVkID0gcmVnaW9uc0F0KHN0YXRlLnJlZ2lvbnMsIHN0YXRlLnNlbGVjdGVkSW5kaWNlcyk7XG4gIGlmIChzZWxlY3RlZC5sZW5ndGggPT09IDApIHJldHVybiBpdGVtcztcbiAgY29uc3QgZWxpZ2libGUgPSBvcEVsaWdpYmxlKHNlbGVjdGVkKTtcbiAgaWYgKGVsaWdpYmxlLmxlbmd0aCA+PSAyKSB7XG4gICAgaXRlbXMucHVzaCh7IGxhYmVsOiAnTWVyZ2UgLyBncm91cCcsIGljb246ICdwaSBwaS1saW5rJywgY29tbWFuZDogKCkgPT4gYWN0aW9ucy5tZXJnZVJlZ2lvbnMoKSB9KTtcbiAgfVxuICBpZiAoc2VsZWN0ZWQuc29tZSgocikgPT4gc3RhdGUuY2FuVW5ncm91cChyKSkpIHtcbiAgICBpdGVtcy5wdXNoKHsgbGFiZWw6ICdVbmdyb3VwJywgaWNvbjogJ3BpIHBpLXNpdGVtYXAnLCBjb21tYW5kOiAoKSA9PiBhY3Rpb25zLnVuZ3JvdXBSZWdpb25zKCkgfSk7XG4gIH1cbiAgaWYgKGVsaWdpYmxlLmxlbmd0aCA+PSAxKSB7XG4gICAgaXRlbXMucHVzaChcbiAgICAgIHsgbGFiZWw6ICdJbnZlcnNlJywgaWNvbjogJ3BpIHBpLWNsb25lJywgY29tbWFuZDogKCkgPT4gYWN0aW9ucy5pbnZlcnNlUmVnaW9ucygpIH0sXG4gICAgICB7XG4gICAgICAgIGxhYmVsOiAnU2ltcGxpZnknLFxuICAgICAgICBpY29uOiAncGkgcGktY2hhcnQtbGluZScsXG4gICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgeyBsYWJlbDogJ0xpZ2h0ICgxIHB4KScsIGNvbW1hbmQ6ICgpID0+IGFjdGlvbnMuc2ltcGxpZnlSZWdpb25zKDEpIH0sXG4gICAgICAgICAgeyBsYWJlbDogJ01lZGl1bSAoMyBweCknLCBjb21tYW5kOiAoKSA9PiBhY3Rpb25zLnNpbXBsaWZ5UmVnaW9ucygzKSB9LFxuICAgICAgICAgIHsgbGFiZWw6ICdTdHJvbmcgKDggcHgpJywgY29tbWFuZDogKCkgPT4gYWN0aW9ucy5zaW1wbGlmeVJlZ2lvbnMoOCkgfSxcbiAgICAgICAgICB7IHNlcGFyYXRvcjogdHJ1ZSB9LFxuICAgICAgICAgIHsgbGFiZWw6ICdDdXN0b23igKYnLCBjb21tYW5kOiAoKSA9PiBhY3Rpb25zLm9wZW5TaW1wbGlmeURpYWxvZygpIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgICk7XG4gIH1cbiAgLy8gQsOpemllciBjb252ZXJzaW9ucyBhcmUgdmVydGV4LWxldmVsIGVkaXRzIOKAlCBJbWFnZSAoT3BlblNlYWRyYWdvbikgdmlldyBvbmx5IOKAlFxuICAvLyBnYXRlZCBvbiB0aGUgc2VsZWN0aW9uJ3MgY3VycmVudCBmb3JtLlxuICBpZiAoc3RhdGUuYmFzZVBsb3RUeXBlID09PSBQbG90VHlwZS5JTUFHRSkge1xuICAgIGlmIChzZWxlY3RlZC5zb21lKChyKSA9PiAoci5ib3VuZHMgaW5zdGFuY2VvZiBQb2x5Z29uICYmICFyLmJvdW5kcy5iZXppZXIpIHx8IHIuYm91bmRzIGluc3RhbmNlb2YgUmVjdGFuZ2xlKSkge1xuICAgICAgaXRlbXMucHVzaCh7IGxhYmVsOiAnQ29udmVydCB0byBCw6l6aWVyJywgaWNvbjogJ3RvLWJlemllci1pY29uJywgY29tbWFuZDogKCkgPT4gYWN0aW9ucy50b0JlemllclJlZ2lvbigpIH0pO1xuICAgIH1cbiAgICBpZiAoc2VsZWN0ZWQuc29tZSgocikgPT4gci5ib3VuZHMgaW5zdGFuY2VvZiBQb2x5Z29uICYmIHIuYm91bmRzLmJlemllcikpIHtcbiAgICAgIGl0ZW1zLnB1c2goe1xuICAgICAgICBsYWJlbDogJ0NvbnZlcnQgdG8gcG9seWdvbicsXG4gICAgICAgIGljb246ICd0by1wb2x5Z29uLWljb24nLFxuICAgICAgICBjb21tYW5kOiAoKSA9PiBhY3Rpb25zLnRvUG9seWdvblJlZ2lvbigpLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIGl0ZW1zLnB1c2goeyBsYWJlbDogJ0RlbGV0ZSByZWdpb24nLCBpY29uOiAncGkgcGktdHJhc2gnLCBjb21tYW5kOiAoKSA9PiBhY3Rpb25zLmRlbGV0ZVJlZ2lvbigpIH0pO1xuICByZXR1cm4gaXRlbXM7XG59XG4iXX0=