@jax-data-science/sci-image-visualizer 0.8.2 → 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 +361 -4184
  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 -34430
  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 -878
  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
@@ -1,58 +1,18 @@
1
- import { OSD } from './osd-lib';
2
- /** Round up to a "nice" 1/2/5 × 10ⁿ value for scale-bar lengths. */
3
- function niceLength(x) {
4
- if (x <= 0)
5
- return 1;
6
- const base = Math.pow(10, Math.floor(Math.log10(x)));
7
- const f = x / base;
8
- const nice = f < 1.5 ? 1 : f < 3.5 ? 2 : f < 7.5 ? 5 : 10;
9
- return nice * base;
10
- }
11
- /**
12
- * Format a length given in micrometres, picking the unit that suits its
13
- * magnitude. The value is always µm internally (jit-service normalises whatever
14
- * unit Bio-Formats reports — nm/µm/mm/cm/inch — to µm), so this adapts the
15
- * displayed unit to the image's actual scale rather than assuming microns.
16
- */
17
- function formatUm(um) {
18
- const trim = (n) => (n % 1 === 0 ? `${n}` : n.toFixed(1));
19
- if (um >= 1e6)
20
- return `${trim(um / 1e6)} m`;
21
- if (um >= 1e4)
22
- return `${trim(um / 1e4)} cm`;
23
- if (um >= 1e3)
24
- return `${trim(um / 1e3)} mm`;
25
- if (um >= 1)
26
- return `${trim(um)} µm`;
27
- return `${trim(um * 1000)} nm`;
28
- }
1
+ import { formatLength, scaleBarFor } from 'napari-js/overlays';
2
+ import { imageToElement } from './osd-coords';
29
3
  /**
30
- * A physical scale bar drawn over an OpenSeadragon viewer. Recomputes on every
31
- * pan/zoom from the viewport's image→screen scale and the image's µm/pixel
32
- * (`mppX`, from Bio-Formats). Hidden when the image has no physical pixel size.
4
+ * A physical scale bar drawn over an OpenSeadragon viewer. The length maths (the nice 1/2/5 × 10ⁿ
5
+ * length nearest the target, and its unit) are napari-js's `scaleBarFor` / `formatLength`, which
6
+ * also size the napari backend's `ScaleBarOverlay`, so the two bars agree; the DOM is the same
7
+ * label-over-a-bracketed-line. Recomputes on every pan/zoom from the image→screen scale and the
8
+ * image's µm/pixel (`mppX`, from Bio-Formats). Hidden when the image has no physical pixel size.
33
9
  */
34
10
  export class OsdScaleBar {
35
11
  constructor(viewer, mppX) {
36
12
  this.viewer = viewer;
37
13
  this.mppX = mppX;
38
- this.osd = OSD;
39
14
  this.redrawHandler = () => this.update();
40
- this.bar = document.createElement('div');
41
- Object.assign(this.bar.style, {
42
- position: 'absolute', left: '12px', bottom: '12px', zIndex: '30',
43
- pointerEvents: 'none', color: '#fff', font: '11px sans-serif',
44
- textShadow: '0 0 3px #000', textAlign: 'center', userSelect: 'none',
45
- });
46
- this.label = document.createElement('span');
47
- this.line = document.createElement('div');
48
- Object.assign(this.line.style, {
49
- height: '4px', marginTop: '2px', background: 'rgba(255,255,255,0.9)',
50
- borderLeft: '1px solid #fff', borderRight: '1px solid #fff',
51
- boxShadow: '0 0 3px #000',
52
- });
53
- this.bar.appendChild(this.label);
54
- this.bar.appendChild(this.line);
55
- this.viewer.canvas.appendChild(this.bar);
15
+ [this.bar, this.label, this.line] = createScaleBarElement(this.viewer.canvas);
56
16
  this.viewer.addHandler('update-viewport', this.redrawHandler);
57
17
  this.viewer.addHandler('animation', this.redrawHandler);
58
18
  this.viewer.addHandler('resize', this.redrawHandler);
@@ -63,26 +23,58 @@ export class OsdScaleBar {
63
23
  this.bar.style.display = 'none';
64
24
  return;
65
25
  }
66
- const vp = this.viewer.viewport;
67
- const a = vp.imageToViewerElementCoordinates(new this.osd.Point(0, 0));
68
- const b = vp.imageToViewerElementCoordinates(new this.osd.Point(1, 0));
69
- const pxPerImagePx = Math.abs(b.x - a.x); // screen px per image px
70
- if (!(pxPerImagePx > 0)) {
26
+ // Through osd-coords (world item 0), which stays accurate while the world
27
+ // holds several slices — the viewport's own image conversion does not.
28
+ const a = imageToElement(this.viewer, 0, 0);
29
+ const b = imageToElement(this.viewer, 1, 0);
30
+ const spec = scaleBarFor(Math.abs(b.x - a.x), this.mppX);
31
+ if (!spec) {
71
32
  this.bar.style.display = 'none';
72
33
  return;
73
34
  }
74
- const umPerScreenPx = this.mppX / pxPerImagePx;
75
- const niceUm = niceLength(120 * umPerScreenPx); // target ~120px bar
76
35
  this.bar.style.display = '';
77
- this.line.style.width = `${Math.round(niceUm / umPerScreenPx)}px`;
78
- this.label.textContent = formatUm(niceUm);
36
+ this.line.style.width = `${Math.round(spec.widthPx)}px`;
37
+ this.label.textContent = formatLength(spec.length, 'µm');
79
38
  }
80
39
  destroy() {
81
40
  this.viewer.removeHandler('update-viewport', this.redrawHandler);
82
41
  this.viewer.removeHandler('animation', this.redrawHandler);
83
42
  this.viewer.removeHandler('resize', this.redrawHandler);
84
- if (this.bar.parentNode)
85
- this.bar.parentNode.removeChild(this.bar);
43
+ this.bar.remove();
86
44
  }
87
45
  }
88
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3NkLXNjYWxlLWJhci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvaW1wbGVtZW50YXRpb25zL29zZC9vc2Qtc2NhbGUtYmFyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFaEMsb0VBQW9FO0FBQ3BFLFNBQVMsVUFBVSxDQUFDLENBQVM7SUFDM0IsSUFBSSxDQUFDLElBQUksQ0FBQztRQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3JCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUNuQixNQUFNLElBQUksR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDMUQsT0FBTyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQ3JCLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsUUFBUSxDQUFDLEVBQVU7SUFDMUIsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsRSxJQUFJLEVBQUUsSUFBSSxHQUFHO1FBQUUsT0FBTyxHQUFHLElB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Q0FBQztJQUM1QyxDQUFDO0lBRUQsT0FBTztRQUNMLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNqRSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDeEQsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVU7WUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3JFLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9TRCB9IGZyb20gJy4vb3NkLWxpYic7XG5cbi8qKiBSb3VuZCB1cCB0byBhIFwibmljZVwiIDEvMi81IMOXIDEw4oG/IHZhbHVlIGZvciBzY2FsZS1iYXIgbGVuZ3Rocy4gKi9cbmZ1bmN0aW9uIG5pY2VMZW5ndGgoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgaWYgKHggPD0gMCkgcmV0dXJuIDE7XG4gIGNvbnN0IGJhc2UgPSBNYXRoLnBvdygxMCwgTWF0aC5mbG9vcihNYXRoLmxvZzEwKHgpKSk7XG4gIGNvbnN0IGYgPSB4IC8gYmFzZTtcbiAgY29uc3QgbmljZSA9IGYgPCAxLjUgPyAxIDogZiA8IDMuNSA/IDIgOiBmIDwgNy41ID8gNSA6IDEwO1xuICByZXR1cm4gbmljZSAqIGJhc2U7XG59XG5cbi8qKlxuICogRm9ybWF0IGEgbGVuZ3RoIGdpdmVuIGluIG1pY3JvbWV0cmVzLCBwaWNraW5nIHRoZSB1bml0IHRoYXQgc3VpdHMgaXRzXG4gKiBtYWduaXR1ZGUuIFRoZSB2YWx1ZSBpcyBhbHdheXMgwrVtIGludGVybmFsbHkgKGppdC1zZXJ2aWNlIG5vcm1hbGlzZXMgd2hhdGV2ZXJcbiAqIHVuaXQgQmlvLUZvcm1hdHMgcmVwb3J0cyDigJQgbm0vwrVtL21tL2NtL2luY2gg4oCUIHRvIMK1bSksIHNvIHRoaXMgYWRhcHRzIHRoZVxuICogZGlzcGxheWVkIHVuaXQgdG8gdGhlIGltYWdlJ3MgYWN0dWFsIHNjYWxlIHJhdGhlciB0aGFuIGFzc3VtaW5nIG1pY3JvbnMuXG4gKi9cbmZ1bmN0aW9uIGZvcm1hdFVtKHVtOiBudW1iZXIpOiBzdHJpbmcge1xuICBjb25zdCB0cmltID0gKG46IG51bWJlcikgPT4gKG4gJSAxID09PSAwID8gYCR7bn1gIDogbi50b0ZpeGVkKDEpKTtcbiAgaWYgKHVtID49IDFlNikgcmV0dXJuIGAke3RyaW0odW0gLyAxZTYpfSBtYDtcbiAgaWYgKHVtID49IDFlNCkgcmV0dXJuIGAke3RyaW0odW0gLyAxZTQpfSBjbWA7XG4gIGlmICh1bSA+PSAxZTMpIHJldHVybiBgJHt0cmltKHVtIC8gMWUzKX0gbW1gO1xuICBpZiAodW0gPj0gMSkgcmV0dXJuIGAke3RyaW0odW0pfSDCtW1gO1xuICByZXR1cm4gYCR7dHJpbSh1bSAqIDEwMDApfSBubWA7XG59XG5cbi8qKlxuICogQSBwaHlzaWNhbCBzY2FsZSBiYXIgZHJhd24gb3ZlciBhbiBPcGVuU2VhZHJhZ29uIHZpZXdlci4gUmVjb21wdXRlcyBvbiBldmVyeVxuICogcGFuL3pvb20gZnJvbSB0aGUgdmlld3BvcnQncyBpbWFnZeKGknNjcmVlbiBzY2FsZSBhbmQgdGhlIGltYWdlJ3MgwrVtL3BpeGVsXG4gKiAoYG1wcFhgLCBmcm9tIEJpby1Gb3JtYXRzKS4gSGlkZGVuIHdoZW4gdGhlIGltYWdlIGhhcyBubyBwaHlzaWNhbCBwaXhlbCBzaXplLlxuICovXG5leHBvcnQgY2xhc3MgT3NkU2NhbGVCYXIge1xuICBwcml2YXRlIHJlYWRvbmx5IG9zZDogYW55ID0gT1NEO1xuICBwcml2YXRlIHJlYWRvbmx5IGJhcjogSFRNTERpdkVsZW1lbnQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgbGluZTogSFRNTERpdkVsZW1lbnQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgbGFiZWw6IEhUTUxTcGFuRWxlbWVudDtcbiAgcHJpdmF0ZSByZWFkb25seSByZWRyYXdIYW5kbGVyID0gKCkgPT4gdGhpcy51cGRhdGUoKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHZpZXdlcjogYW55LCBwcml2YXRlIG1wcFg6IG51bWJlcikge1xuICAgIHRoaXMuYmFyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgT2JqZWN0LmFzc2lnbih0aGlzLmJhci5zdHlsZSwge1xuICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsIGxlZnQ6ICcxMnB4JywgYm90dG9tOiAnMTJweCcsIHpJbmRleDogJzMwJyxcbiAgICAgIHBvaW50ZXJFdmVudHM6ICdub25lJywgY29sb3I6ICcjZmZmJywgZm9udDogJzExcHggc2Fucy1zZXJpZicsXG4gICAgICB0ZXh0U2hhZG93OiAnMCAwIDNweCAjMDAwJywgdGV4dEFsaWduOiAnY2VudGVyJywgdXNlclNlbGVjdDogJ25vbmUnLFxuICAgIH0gYXMgQ1NTU3R5bGVEZWNsYXJhdGlvbik7XG4gICAgdGhpcy5sYWJlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICB0aGlzLmxpbmUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBPYmplY3QuYXNzaWduKHRoaXMubGluZS5zdHlsZSwge1xuICAgICAgaGVpZ2h0OiAnNHB4JywgbWFyZ2luVG9wOiAnMnB4JywgYmFja2dyb3VuZDogJ3JnYmEoMjU1LDI1NSwyNTUsMC45KScsXG4gICAgICBib3JkZXJMZWZ0OiAnMXB4IHNvbGlkICNmZmYnLCBib3JkZXJSaWdodDogJzFweCBzb2xpZCAjZmZmJyxcbiAgICAgIGJveFNoYWRvdzogJzAgMCAzcHggIzAwMCcsXG4gICAgfSBhcyBDU1NTdHlsZURlY2xhcmF0aW9uKTtcbiAgICB0aGlzLmJhci5hcHBlbmRDaGlsZCh0aGlzLmxhYmVsKTtcbiAgICB0aGlzLmJhci5hcHBlbmRDaGlsZCh0aGlzLmxpbmUpO1xuICAgIHRoaXMudmlld2VyLmNhbnZhcy5hcHBlbmRDaGlsZCh0aGlzLmJhcik7XG5cbiAgICB0aGlzLnZpZXdlci5hZGRIYW5kbGVyKCd1cGRhdGUtdmlld3BvcnQnLCB0aGlzLnJlZHJhd0hhbmRsZXIpO1xuICAgIHRoaXMudmlld2VyLmFkZEhhbmRsZXIoJ2FuaW1hdGlvbicsIHRoaXMucmVkcmF3SGFuZGxlcik7XG4gICAgdGhpcy52aWV3ZXIuYWRkSGFuZGxlcigncmVzaXplJywgdGhpcy5yZWRyYXdIYW5kbGVyKTtcbiAgICB0aGlzLnVwZGF0ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGUoKTogdm9pZCB7XG4gICAgaWYgKCEodGhpcy5tcHBYID4gMCkgfHwgIXRoaXMudmlld2VyLnZpZXdwb3J0IHx8IHRoaXMudmlld2VyLndvcmxkPy5nZXRJdGVtQ291bnQoKSA9PT0gMCkge1xuICAgICAgdGhpcy5iYXIuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgdnAgPSB0aGlzLnZpZXdlci52aWV3cG9ydDtcbiAgICBjb25zdCBhID0gdnAuaW1hZ2VUb1ZpZXdlckVsZW1lbnRDb29yZGluYXRlcyhuZXcgdGhpcy5vc2QuUG9pbnQoMCwgMCkpO1xuICAgIGNvbnN0IGIgPSB2cC5pbWFnZVRvVmlld2VyRWxlbWVudENvb3JkaW5hdGVzKG5ldyB0aGlzLm9zZC5Qb2ludCgxLCAwKSk7XG4gICAgY29uc3QgcHhQZXJJbWFnZVB4ID0gTWF0aC5hYnMoYi54IC0gYS54KTsgLy8gc2NyZWVuIHB4IHBlciBpbWFnZSBweFxuICAgIGlmICghKHB4UGVySW1hZ2VQeCA+IDApKSB7IHRoaXMuYmFyLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7IHJldHVybjsgfVxuXG4gICAgY29uc3QgdW1QZXJTY3JlZW5QeCA9IHRoaXMubXBwWCAvIHB4UGVySW1hZ2VQeDtcbiAgICBjb25zdCBuaWNlVW0gPSBuaWNlTGVuZ3RoKDEyMCAqIHVtUGVyU2NyZWVuUHgpOyAvLyB0YXJnZXQgfjEyMHB4IGJhclxuICAgIHRoaXMuYmFyLnN0eWxlLmRpc3BsYXkgPSAnJztcbiAgICB0aGlzLmxpbmUuc3R5bGUud2lkdGggPSBgJHtNYXRoLnJvdW5kKG5pY2VVbSAvIHVtUGVyU2NyZWVuUHgpfXB4YDtcbiAgICB0aGlzLmxhYmVsLnRleHRDb250ZW50ID0gZm9ybWF0VW0obmljZVVtKTtcbiAgfVxuXG4gIGRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy52aWV3ZXIucmVtb3ZlSGFuZGxlcigndXBkYXRlLXZpZXdwb3J0JywgdGhpcy5yZWRyYXdIYW5kbGVyKTtcbiAgICB0aGlzLnZpZXdlci5yZW1vdmVIYW5kbGVyKCdhbmltYXRpb24nLCB0aGlzLnJlZHJhd0hhbmRsZXIpO1xuICAgIHRoaXMudmlld2VyLnJlbW92ZUhhbmRsZXIoJ3Jlc2l6ZScsIHRoaXMucmVkcmF3SGFuZGxlcik7XG4gICAgaWYgKHRoaXMuYmFyLnBhcmVudE5vZGUpIHRoaXMuYmFyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5iYXIpO1xuICB9XG59XG4iXX0=
46
+ /**
47
+ * The bar's DOM (a label over a bracketed line, bottom-left, above the canvas), styled as
48
+ * napari-js's `ScaleBarOverlay`, inside `host`, which must establish a containing block.
49
+ * Starts hidden until the first update.
50
+ */
51
+ function createScaleBarElement(host) {
52
+ const bar = document.createElement('div');
53
+ Object.assign(bar.style, {
54
+ position: 'absolute',
55
+ left: '12px',
56
+ bottom: '12px',
57
+ zIndex: '30',
58
+ pointerEvents: 'none',
59
+ color: '#fff',
60
+ font: '11px sans-serif',
61
+ textShadow: '0 0 3px #000',
62
+ textAlign: 'center',
63
+ userSelect: 'none',
64
+ display: 'none',
65
+ });
66
+ const label = document.createElement('span');
67
+ const line = document.createElement('div');
68
+ Object.assign(line.style, {
69
+ height: '4px',
70
+ marginTop: '2px',
71
+ background: 'rgba(255,255,255,0.9)',
72
+ borderLeft: '1px solid #fff',
73
+ borderRight: '1px solid #fff',
74
+ boxShadow: '0 0 3px #000',
75
+ });
76
+ bar.append(label, line);
77
+ host.appendChild(bar);
78
+ return [bar, label, line];
79
+ }
80
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3NkLXNjYWxlLWJhci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvaW1wbGVtZW50YXRpb25zL29zZC9vc2Qtc2NhbGUtYmFyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFL0QsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUc5Qzs7Ozs7O0dBTUc7QUFDSCxNQUFNLE9BQU8sV0FBVztJQU10QixZQUNVLE1BQXFCLEVBQ3JCLElBQVk7UUFEWixXQUFNLEdBQU4sTUFBTSxDQUFlO1FBQ3JCLFNBQUksR0FBSixJQUFJLENBQVE7UUFKTCxrQkFBYSxHQUFHLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQU1uRCxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcscUJBQXFCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5RSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN4RCxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3JELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNoQixDQUFDO0lBRU8sTUFBTTtRQUNaLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsSUFBSSxJQUFJ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Q0FBQyxDQUFDO0lBQ3hCLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEIsT0FBTyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDNUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGZvcm1hdExlbmd0aCwgc2NhbGVCYXJGb3IgfSBmcm9tICduYXBhcmktanMvb3ZlcmxheXMnO1xuXG5pbXBvcnQgeyBpbWFnZVRvRWxlbWVudCB9IGZyb20gJy4vb3NkLWNvb3Jkcyc7XG5pbXBvcnQgeyBPc2RWaWV3ZXJMaWtlIH0gZnJvbSAnLi9vc2Qtdmlld2VyLWxpa2UnO1xuXG4vKipcbiAqIEEgcGh5c2ljYWwgc2NhbGUgYmFyIGRyYXduIG92ZXIgYW4gT3BlblNlYWRyYWdvbiB2aWV3ZXIuIFRoZSBsZW5ndGggbWF0aHMgKHRoZSBuaWNlIDEvMi81IMOXIDEw4oG/XG4gKiBsZW5ndGggbmVhcmVzdCB0aGUgdGFyZ2V0LCBhbmQgaXRzIHVuaXQpIGFyZSBuYXBhcmktanMncyBgc2NhbGVCYXJGb3JgIC8gYGZvcm1hdExlbmd0aGAsIHdoaWNoXG4gKiBhbHNvIHNpemUgdGhlIG5hcGFyaSBiYWNrZW5kJ3MgYFNjYWxlQmFyT3ZlcmxheWAsIHNvIHRoZSB0d28gYmFycyBhZ3JlZTsgdGhlIERPTSBpcyB0aGUgc2FtZVxuICogbGFiZWwtb3Zlci1hLWJyYWNrZXRlZC1saW5lLiBSZWNvbXB1dGVzIG9uIGV2ZXJ5IHBhbi96b29tIGZyb20gdGhlIGltYWdl4oaSc2NyZWVuIHNjYWxlIGFuZCB0aGVcbiAqIGltYWdlJ3MgwrVtL3BpeGVsIChgbXBwWGAsIGZyb20gQmlvLUZvcm1hdHMpLiBIaWRkZW4gd2hlbiB0aGUgaW1hZ2UgaGFzIG5vIHBoeXNpY2FsIHBpeGVsIHNpemUuXG4gKi9cbmV4cG9ydCBjbGFzcyBPc2RTY2FsZUJhciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYmFyOiBIVE1MRGl2RWxlbWVudDtcbiAgcHJpdmF0ZSByZWFkb25seSBsYWJlbDogSFRNTFNwYW5FbGVtZW50O1xuICBwcml2YXRlIHJlYWRvbmx5IGxpbmU6IEhUTUxEaXZFbGVtZW50O1xuICBwcml2YXRlIHJlYWRvbmx5IHJlZHJhd0hhbmRsZXIgPSAoKSA9PiB0aGlzLnVwZGF0ZSgpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgdmlld2VyOiBPc2RWaWV3ZXJMaWtlLFxuICAgIHByaXZhdGUgbXBwWDogbnVtYmVyLFxuICApIHtcbiAgICBbdGhpcy5iYXIsIHRoaXMubGFiZWwsIHRoaXMubGluZV0gPSBjcmVhdGVTY2FsZUJhckVsZW1lbnQodGhpcy52aWV3ZXIuY2FudmFzKTtcbiAgICB0aGlzLnZpZXdlci5hZGRIYW5kbGVyKCd1cGRhdGUtdmlld3BvcnQnLCB0aGlzLnJlZHJhd0hhbmRsZXIpO1xuICAgIHRoaXMudmlld2VyLmFkZEhhbmRsZXIoJ2FuaW1hdGlvbicsIHRoaXMucmVkcmF3SGFuZGxlcik7XG4gICAgdGhpcy52aWV3ZXIuYWRkSGFuZGxlcigncmVzaXplJywgdGhpcy5yZWRyYXdIYW5kbGVyKTtcbiAgICB0aGlzLnVwZGF0ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGUoKTogdm9pZCB7XG4gICAgaWYgKCEodGhpcy5tcHBYID4gMCkgfHwgIXRoaXMudmlld2VyLnZpZXdwb3J0IHx8IHRoaXMudmlld2VyLndvcmxkPy5nZXRJdGVtQ291bnQoKSA9PT0gMCkge1xuICAgICAgdGhpcy5iYXIuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gVGhyb3VnaCBvc2QtY29vcmRzICh3b3JsZCBpdGVtIDApLCB3aGljaCBzdGF5cyBhY2N1cmF0ZSB3aGlsZSB0aGUgd29ybGRcbiAgICAvLyBob2xkcyBzZXZlcmFsIHNsaWNlcyDigJQgdGhlIHZpZXdwb3J0J3Mgb3duIGltYWdlIGNvbnZlcnNpb24gZG9lcyBub3QuXG4gICAgY29uc3QgYSA9IGltYWdlVG9FbGVtZW50KHRoaXMudmlld2VyLCAwLCAwKTtcbiAgICBjb25zdCBiID0gaW1hZ2VUb0VsZW1lbnQodGhpcy52aWV3ZXIsIDEsIDApO1xuICAgIGNvbnN0IHNwZWMgPSBzY2FsZUJhckZvcihNYXRoLmFicyhiLnggLSBhLngpLCB0aGlzLm1wcFgpO1xuICAgIGlmICghc3BlYykge1xuICAgICAgdGhpcy5iYXIuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5iYXIuc3R5bGUuZGlzcGxheSA9ICcnO1xuICAgIHRoaXMubGluZS5zdHlsZS53aWR0aCA9IGAke01hdGgucm91bmQoc3BlYy53aWR0aFB4KX1weGA7XG4gICAgdGhpcy5sYWJlbC50ZXh0Q29udGVudCA9IGZvcm1hdExlbmd0aChzcGVjLmxlbmd0aCwgJ8K1bScpO1xuICB9XG5cbiAgZGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnZpZXdlci5yZW1vdmVIYW5kbGVyKCd1cGRhdGUtdmlld3BvcnQnLCB0aGlzLnJlZHJhd0hhbmRsZXIpO1xuICAgIHRoaXMudmlld2VyLnJlbW92ZUhhbmRsZXIoJ2FuaW1hdGlvbicsIHRoaXMucmVkcmF3SGFuZGxlcik7XG4gICAgdGhpcy52aWV3ZXIucmVtb3ZlSGFuZGxlcigncmVzaXplJywgdGhpcy5yZWRyYXdIYW5kbGVyKTtcbiAgICB0aGlzLmJhci5yZW1vdmUoKTtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBiYXIncyBET00gKGEgbGFiZWwgb3ZlciBhIGJyYWNrZXRlZCBsaW5lLCBib3R0b20tbGVmdCwgYWJvdmUgdGhlIGNhbnZhcyksIHN0eWxlZCBhc1xuICogbmFwYXJpLWpzJ3MgYFNjYWxlQmFyT3ZlcmxheWAsIGluc2lkZSBgaG9zdGAsIHdoaWNoIG11c3QgZXN0YWJsaXNoIGEgY29udGFpbmluZyBibG9jay5cbiAqIFN0YXJ0cyBoaWRkZW4gdW50aWwgdGhlIGZpcnN0IHVwZGF0ZS5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlU2NhbGVCYXJFbGVtZW50KGhvc3Q6IEhUTUxFbGVtZW50KTogW0hUTUxEaXZFbGVtZW50LCBIVE1MU3BhbkVsZW1lbnQsIEhUTUxEaXZFbGVtZW50XSB7XG4gIGNvbnN0IGJhciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICBPYmplY3QuYXNzaWduKGJhci5zdHlsZSwge1xuICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuICAgIGxlZnQ6ICcxMnB4JyxcbiAgICBib3R0b206ICcxMnB4JyxcbiAgICB6SW5kZXg6ICczMCcsXG4gICAgcG9pbnRlckV2ZW50czogJ25vbmUnLFxuICAgIGNvbG9yOiAnI2ZmZicsXG4gICAgZm9udDogJzExcHggc2Fucy1zZXJpZicsXG4gICAgdGV4dFNoYWRvdzogJzAgMCAzcHggIzAwMCcsXG4gICAgdGV4dEFsaWduOiAnY2VudGVyJyxcbiAgICB1c2VyU2VsZWN0OiAnbm9uZScsXG4gICAgZGlzcGxheTogJ25vbmUnLFxuICB9IGFzIFBhcnRpYWw8Q1NTU3R5bGVEZWNsYXJhdGlvbj4pO1xuICBjb25zdCBsYWJlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgY29uc3QgbGluZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICBPYmplY3QuYXNzaWduKGxpbmUuc3R5bGUsIHtcbiAgICBoZWlnaHQ6ICc0cHgnLFxuICAgIG1hcmdpblRvcDogJzJweCcsXG4gICAgYmFja2dyb3VuZDogJ3JnYmEoMjU1LDI1NSwyNTUsMC45KScsXG4gICAgYm9yZGVyTGVmdDogJzFweCBzb2xpZCAjZmZmJyxcbiAgICBib3JkZXJSaWdodDogJzFweCBzb2xpZCAjZmZmJyxcbiAgICBib3hTaGFkb3c6ICcwIDAgM3B4ICMwMDAnLFxuICB9IGFzIFBhcnRpYWw8Q1NTU3R5bGVEZWNsYXJhdGlvbj4pO1xuICBiYXIuYXBwZW5kKGxhYmVsLCBsaW5lKTtcbiAgaG9zdC5hcHBlbmRDaGlsZChiYXIpO1xuICByZXR1cm4gW2JhciwgbGFiZWwsIGxpbmVdO1xufVxuIl19
@@ -0,0 +1,105 @@
1
+ import { OSD } from './osd-lib';
2
+ import { buildTileUrl } from './tile-client';
3
+ /**
4
+ * Per-channel fit-view tile budget (tiles at the coarsest real level × channels).
5
+ * Above it, a multichannel image renders server-composited instead of per-channel
6
+ * — its full-res reads (it has no overview pyramid) would be too many × N channels.
7
+ * 64 (e.g. a 4x4 single-FOV z-stack × 4ch) stays per-channel; a whole-slide
8
+ * (hundreds–thousands) falls back.
9
+ */
10
+ export const MAX_MULTICHANNEL_FIT_TILES = 256;
11
+ /**
12
+ * Decide how to draw a tiled image. Multichannel fluorescence (indexed/LUT-bearing
13
+ * stacks) composite client-side from per-channel tiles. Trust the server's explicit
14
+ * `multichannel` flag — the old `channels>1 && grayscale` heuristic also matched RGB
15
+ * photos Bio-Formats reads as separated planes (channels>1, rgbChannels==1),
16
+ * splitting them into N per-channel TiledImages that flooded the tile endpoint and
17
+ * hung on load.
18
+ */
19
+ export function planTiledMount(d, maxFitTiles = MAX_MULTICHANNEL_FIT_TILES) {
20
+ const realLevels = d.realLevels ?? d.levels.length;
21
+ // Tiles to cover the whole image at the coarsest REAL Bio-Formats level (the
22
+ // smallest level that has real, per-channel-fetchable tiles — synthetic overview
23
+ // levels are server-composited only). A pyramidal image's coarsest real level is
24
+ // tiny (few tiles); a flat/no-pyramid image's is the full-res grid (many tiles).
25
+ const coarse = d.levels[realLevels - 1] ?? d.levels[d.levels.length - 1];
26
+ const coarseW = coarse ? Math.ceil(coarse.width / d.tileSize) : 1;
27
+ const coarseH = coarse ? Math.ceil(coarse.height / d.tileSize) : 1;
28
+ const coarseTiles = coarseW * coarseH;
29
+ let multiChannel = !!d.multichannel;
30
+ if (multiChannel) {
31
+ // Per-channel rendering can only use the REAL levels, so OSD requests the
32
+ // coarsest real level's whole tile grid × N channels at fit. When that's large
33
+ // (a whole-slide), it's too many (often slow, pyramid-less) full-res reads —
34
+ // fall back to the single server-composited source (which keeps the fast
35
+ // synthetic overviews). A small single-FOV z-stack stays per-channel. Size in
36
+ // BYTES isn't the signal — tile count is.
37
+ const fitTiles = coarseTiles * Math.max(1, d.channels ?? 1);
38
+ if (fitTiles > maxFitTiles) {
39
+ multiChannel = false;
40
+ console.warn('[OSD] multichannel composite too large for per-channel rendering: ' +
41
+ `${coarseW}x${coarseH} tiles x ${d.channels} channels = ${fitTiles} at the coarsest ` +
42
+ `real level (> ${maxFitTiles}); rendering server-composited for speed.`);
43
+ }
44
+ }
45
+ return { realLevels, multiChannel, coarseTiles };
46
+ }
47
+ /**
48
+ * Custom tile source built from the descriptor. OSD numbers levels
49
+ * coarsest-first; the backend numbers resolutions full-res-first, so
50
+ * `res = (levels-1) - osdLevel`. Overriding getLevelScale/getNumTiles lets us
51
+ * honour Bio-Formats' actual per-level dimensions (not assume power-of-two).
52
+ *
53
+ * Multichannel images composite from per-channel tiles, which only exist at
54
+ * real Bio-Formats resolutions — so `realLevelsOnly` drives OSD off the real
55
+ * levels alone and skips the synthetic (server-composited) overviews. Every
56
+ * displayed tile is then per-channel-fetchable at any zoom.
57
+ */
58
+ export function buildOsdTileSource(d, spec) {
59
+ const levels = spec.realLevelsOnly != null ? d.levels.slice(0, spec.realLevelsOnly) : d.levels;
60
+ const n = levels.length;
61
+ const t = d.tileSize;
62
+ // OSD level i (0 = coarsest) <-> backend resolution (n-1-i) (res 0 = full).
63
+ // The backend pyramid is NOT necessarily power-of-two, so we drive OSD off
64
+ // the backend's real per-level dimensions. We override ONLY getLevelScale:
65
+ // OSD derives getNumTiles, getTileBounds AND its per-zoom level selection
66
+ // from getLevelScale, so they all stay consistent — requesting exactly the
67
+ // tiles each resolution actually has (no out-of-range 400s, no flood).
68
+ const resForLevel = (level) => n - 1 - level;
69
+ const osd = OSD;
70
+ const ts = new osd.TileSource({
71
+ width: d.width,
72
+ height: d.height,
73
+ tileSize: t,
74
+ tileOverlap: 0,
75
+ minLevel: 0,
76
+ maxLevel: n - 1,
77
+ });
78
+ ts['getLevelScale'] = (level) => {
79
+ const lvl = levels[resForLevel(level)];
80
+ return lvl ? lvl.width / d.width : 1;
81
+ };
82
+ // Drive the tile COUNT off each level's own (independently-rounded) dimensions,
83
+ // not OSD's default `ceil(scale * fullDimension / tileSize)`. Synthetic AND real
84
+ // Bio-Formats levels aren't exact proportional scales of the full image, so
85
+ // `scale * fullHeight` can round up to one more row (or column) than the level
86
+ // actually has — OSD then requests an out-of-range tile that the server 400s
87
+ // ("Tile (col,row) out of range"). Using the level's real w/h matches the
88
+ // server's own bounds check exactly.
89
+ ts['getNumTiles'] = (level) => {
90
+ const lvl = levels[resForLevel(level)];
91
+ if (!lvl)
92
+ return new osd.Point(0, 0);
93
+ return new osd.Point(Math.ceil(lvl.width / t), Math.ceil(lvl.height / t));
94
+ };
95
+ ts['getTileUrl'] = (level, x, y) => buildTileUrl(spec.api, spec.infoB64, {
96
+ res: resForLevel(level),
97
+ col: x,
98
+ row: y,
99
+ z: spec.z,
100
+ tileSize: t,
101
+ channel: spec.channel,
102
+ });
103
+ return ts;
104
+ }
105
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3NkLXRpbGUtc291cmNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvb3NkL29zZC10aWxlLXNvdXJjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2hDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFHN0M7Ozs7OztHQU1HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQUcsR0FBRyxDQUFDO0FBWTlDOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUFDLENBQWlCLEVBQUUsV0FBVyxHQUFHLDBCQUEwQjtJQUN4RixNQUFNLFVBQVUsR0FBRyxDQUFDLENBQUMsVUFBVSxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ25ELDZFQUE2RTtJQUM3RSxpRkFBaUY7SUFDakYsaUZBQWlGO0lBQ2pGLGlGQUFpRjtJQUNqRixNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3pFLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25FLE1BQU0sV0FBVyxHQUFHLE9BQU8sR0FB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LENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVFLENBQUMsQ0FBQztJQUNGLEVBQUUsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEtBQWEsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLEVBQUUsQ0FDekQsWUFBWSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRTtRQUNuQyxHQUFHLEVBQUUsV0FBVyxDQUFDLEtBQUssQ0FBQztRQUN2QixHQUFHLEVBQUUsQ0FBQztRQUNOLEdBQUcsRUFBRSxDQUFDO1FBQ04sQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ1QsUUFBUSxFQUFFLENBQUM7UUFDWCxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87S0FDdEIsQ0FBQyxDQUFDO0lBQ0wsT0FBTyxFQUFFLENBQUM7QUFDWixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT1NEIH0gZnJvbSAnLi9vc2QtbGliJztcbmltcG9ydCB7IGJ1aWxkVGlsZVVybCB9IGZyb20gJy4vdGlsZS1jbGllbnQnO1xuaW1wb3J0IHsgVGlsZURlc2NyaXB0b3IgfSBmcm9tICcuLi90aWxlLXNlcnZlcic7XG5cbi8qKlxuICogUGVyLWNoYW5uZWwgZml0LXZpZXcgdGlsZSBidWRnZXQgKHRpbGVzIGF0IHRoZSBjb2Fyc2VzdCByZWFsIGxldmVsIMOXIGNoYW5uZWxzKS5cbiAqIEFib3ZlIGl0LCBhIG11bHRpY2hhbm5lbCBpbWFnZSByZW5kZXJzIHNlcnZlci1jb21wb3NpdGVkIGluc3RlYWQgb2YgcGVyLWNoYW5uZWxcbiAqIOKAlCBpdHMgZnVsbC1yZXMgcmVhZHMgKGl0IGhhcyBubyBvdmVydmlldyBweXJhbWlkKSB3b3VsZCBiZSB0b28gbWFueSDDlyBOIGNoYW5uZWxzLlxuICogNjQgKGUuZy4gYSA0eDQgc2luZ2xlLUZPViB6LXN0YWNrIMOXIDRjaCkgc3RheXMgcGVyLWNoYW5uZWw7IGEgd2hvbGUtc2xpZGVcbiAqIChodW5kcmVkc+KAk3Rob3VzYW5kcykgZmFsbHMgYmFjay5cbiAqL1xuZXhwb3J0IGNvbnN0IE1BWF9NVUxUSUNIQU5ORUxfRklUX1RJTEVTID0gMjU2O1xuXG4vKiogSG93IGEgdGlsZWQgaW1hZ2UgaXMgZHJhd24sIGRlY2lkZWQgb25jZSBwZXIgbW91bnQgYnkge0BsaW5rIHBsYW5UaWxlZE1vdW50fS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGlsZWRNb3VudFBsYW4ge1xuICAvKiogUmVhbCBCaW8tRm9ybWF0cyByZXNvbHV0aW9uIGxldmVscyAocGVyLWNoYW5uZWwgdGlsZXMgZXhpc3Qgb25seSBoZXJlKS4gKi9cbiAgcmVhbExldmVsczogbnVtYmVyO1xuICAvKiogQ29tcG9zaXRlIGNsaWVudC1zaWRlIGZyb20gb25lIFRpbGVkSW1hZ2UgcGVyIGNoYW5uZWwuICovXG4gIG11bHRpQ2hhbm5lbDogYm9vbGVhbjtcbiAgLyoqIFRpbGVzIGNvdmVyaW5nIHRoZSB3aG9sZSBpbWFnZSBhdCB0aGUgY29hcnNlc3QgcmVhbCBsZXZlbC4gKi9cbiAgY29hcnNlVGlsZXM6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBEZWNpZGUgaG93IHRvIGRyYXcgYSB0aWxlZCBpbWFnZS4gTXVsdGljaGFubmVsIGZsdW9yZXNjZW5jZSAoaW5kZXhlZC9MVVQtYmVhcmluZ1xuICogc3RhY2tzKSBjb21wb3NpdGUgY2xpZW50LXNpZGUgZnJvbSBwZXItY2hhbm5lbCB0aWxlcy4gVHJ1c3QgdGhlIHNlcnZlcidzIGV4cGxpY2l0XG4gKiBgbXVsdGljaGFubmVsYCBmbGFnIOKAlCB0aGUgb2xkIGBjaGFubmVscz4xICYmIGdyYXlzY2FsZWAgaGV1cmlzdGljIGFsc28gbWF0Y2hlZCBSR0JcbiAqIHBob3RvcyBCaW8tRm9ybWF0cyByZWFkcyBhcyBzZXBhcmF0ZWQgcGxhbmVzIChjaGFubmVscz4xLCByZ2JDaGFubmVscz09MSksXG4gKiBzcGxpdHRpbmcgdGhlbSBpbnRvIE4gcGVyLWNoYW5uZWwgVGlsZWRJbWFnZXMgdGhhdCBmbG9vZGVkIHRoZSB0aWxlIGVuZHBvaW50IGFuZFxuICogaHVuZyBvbiBsb2FkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGxhblRpbGVkTW91bnQoZDogVGlsZURlc2NyaXB0b3IsIG1heEZpdFRpbGVzID0gTUFYX01VTFRJQ0hBTk5FTF9GSVRfVElMRVMpOiBUaWxlZE1vdW50UGxhbiB7XG4gIGNvbnN0IHJlYWxMZXZlbHMgPSBkLnJlYWxMZXZlbHMgPz8gZC5sZXZlbHMubGVuZ3RoO1xuICAvLyBUaWxlcyB0byBjb3ZlciB0aGUgd2hvbGUgaW1hZ2UgYXQgdGhlIGNvYXJzZXN0IFJFQUwgQmlvLUZvcm1hdHMgbGV2ZWwgKHRoZVxuICAvLyBzbWFsbGVzdCBsZXZlbCB0aGF0IGhhcyByZWFsLCBwZXItY2hhbm5lbC1mZXRjaGFibGUgdGlsZXMg4oCUIHN5bnRoZXRpYyBvdmVydmlld1xuICAvLyBsZXZlbHMgYXJlIHNlcnZlci1jb21wb3NpdGVkIG9ubHkpLiBBIHB5cmFtaWRhbCBpbWFnZSdzIGNvYXJzZXN0IHJlYWwgbGV2ZWwgaXNcbiAgLy8gdGlueSAoZmV3IHRpbGVzKTsgYSBmbGF0L25vLXB5cmFtaWQgaW1hZ2UncyBpcyB0aGUgZnVsbC1yZXMgZ3JpZCAobWFueSB0aWxlcykuXG4gIGNvbnN0IGNvYXJzZSA9IGQubGV2ZWxzW3JlYWxMZXZlbHMgLSAxXSA/PyBkLmxldmVsc1tkLmxldmVscy5sZW5ndGggLSAxXTtcbiAgY29uc3QgY29hcnNlVyA9IGNvYXJzZSA/IE1hdGguY2VpbChjb2Fyc2Uud2lkdGggLyBkLnRpbGVTaXplKSA6IDE7XG4gIGNvbnN0IGNvYXJzZUggPSBjb2Fyc2UgPyBNYXRoLmNlaWwoY29hcnNlLmhlaWdodCAvIGQudGlsZVNpemUpIDogMTtcbiAgY29uc3QgY29hcnNlVGlsZXMgPSBjb2Fyc2VXICogY29hcnNlSDtcbiAgbGV0IG11bHRpQ2hhbm5lbCA9ICEhZC5tdWx0aWNoYW5uZWw7XG4gIGlmIChtdWx0aUNoYW5uZWwpIHtcbiAgICAvLyBQZXItY2hhbm5lbCByZW5kZXJpbmcgY2FuIG9ubHkgdXNlIHRoZSBSRUFMIGxldmVscywgc28gT1NEIHJlcXVlc3RzIHRoZVxuICAgIC8vIGNvYXJzZXN0IHJlYWwgbGV2ZWwncyB3aG9sZSB0aWxlIGdyaWQgw5cgTiBjaGFubmVscyBhdCBmaXQuIFdoZW4gdGhhdCdzIGxhcmdlXG4gICAgLy8gKGEgd2hvbGUtc2xpZGUpLCBpdCdzIHRvbyBtYW55IChvZnRlbiBzbG93LCBweXJhbWlkLWxlc3MpIGZ1bGwtcmVzIHJlYWRzIOKAlFxuICAgIC8vIGZhbGwgYmFjayB0byB0aGUgc2luZ2xlIHNlcnZlci1jb21wb3NpdGVkIHNvdXJjZSAod2hpY2gga2VlcHMgdGhlIGZhc3RcbiAgICAvLyBzeW50aGV0aWMgb3ZlcnZpZXdzKS4gQSBzbWFsbCBzaW5nbGUtRk9WIHotc3RhY2sgc3RheXMgcGVyLWNoYW5uZWwuIFNpemUgaW5cbiAgICAvLyBCWVRFUyBpc24ndCB0aGUgc2lnbmFsIOKAlCB0aWxlIGNvdW50IGlzLlxuICAgIGNvbnN0IGZpdFRpbGVzID0gY29hcnNlVGlsZXMgKiBNYXRoLm1heCgxLCBkLmNoYW5uZWxzID8/IDEpO1xuICAgIGlmIChmaXRUaWxlcyA+IG1heEZpdFRpbGVzKSB7XG4gICAgICBtdWx0aUNoYW5uZWwgPSBmYWxzZTtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgJ1tPU0RdIG11bHRpY2hhbm5lbCBjb21wb3NpdGUgdG9vIGxhcmdlIGZvciBwZXItY2hhbm5lbCByZW5kZXJpbmc6ICcgK1xuICAgICAgICAgIGAke2NvYXJzZVd9eCR7Y29hcnNlSH0gdGlsZXMgeCAke2QuY2hhbm5lbHN9IGNoYW5uZWxzID0gJHtmaXRUaWxlc30gYXQgdGhlIGNvYXJzZXN0IGAgK1xuICAgICAgICAgIGByZWFsIGxldmVsICg+ICR7bWF4Rml0VGlsZXN9KTsgcmVuZGVyaW5nIHNlcnZlci1jb21wb3NpdGVkIGZvciBzcGVlZC5gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHsgcmVhbExldmVscywgbXVsdGlDaGFubmVsLCBjb2Fyc2VUaWxlcyB9O1xufVxuXG4vKiogV2hlcmUgdGhlIHRpbGVzIG9mIG9uZSBzbGljZSAoYW5kIG9wdGlvbmFsbHkgb25lIGNoYW5uZWwpIGNvbWUgZnJvbS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGlsZVNvdXJjZVNwZWMge1xuICBhcGk6IHN0cmluZztcbiAgaW5mb0I2NDogc3RyaW5nO1xuICB6OiBudW1iZXI7XG4gIC8qKiBGZXRjaCB0aGlzIGNoYW5uZWwncyBzaW5nbGUtYmFuZCB0aWxlcyAocGVyLWNoYW5uZWwgbXVsdGljaGFubmVsIHJlbmRlcmluZykuICovXG4gIGNoYW5uZWw/OiBudW1iZXI7XG4gIC8qKiBEcml2ZSBPU0Qgb2ZmIHRoZSBmaXJzdCBOIChyZWFsKSBsZXZlbHMgb25seSDigJQgc2VlIHtAbGluayBidWlsZE9zZFRpbGVTb3VyY2V9LiAqL1xuICByZWFsTGV2ZWxzT25seT86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBDdXN0b20gdGlsZSBzb3VyY2UgYnVpbHQgZnJvbSB0aGUgZGVzY3JpcHRvci4gT1NEIG51bWJlcnMgbGV2ZWxzXG4gKiBjb2Fyc2VzdC1maXJzdDsgdGhlIGJhY2tlbmQgbnVtYmVycyByZXNvbHV0aW9ucyBmdWxsLXJlcy1maXJzdCwgc29cbiAqIGByZXMgPSAobGV2ZWxzLTEpIC0gb3NkTGV2ZWxgLiBPdmVycmlkaW5nIGdldExldmVsU2NhbGUvZ2V0TnVtVGlsZXMgbGV0cyB1c1xuICogaG9ub3VyIEJpby1Gb3JtYXRzJyBhY3R1YWwgcGVyLWxldmVsIGRpbWVuc2lvbnMgKG5vdCBhc3N1bWUgcG93ZXItb2YtdHdvKS5cbiAqXG4gKiBNdWx0aWNoYW5uZWwgaW1hZ2VzIGNvbXBvc2l0ZSBmcm9tIHBlci1jaGFubmVsIHRpbGVzLCB3aGljaCBvbmx5IGV4aXN0IGF0XG4gKiByZWFsIEJpby1Gb3JtYXRzIHJlc29sdXRpb25zIOKAlCBzbyBgcmVhbExldmVsc09ubHlgIGRyaXZlcyBPU0Qgb2ZmIHRoZSByZWFsXG4gKiBsZXZlbHMgYWxvbmUgYW5kIHNraXBzIHRoZSBzeW50aGV0aWMgKHNlcnZlci1jb21wb3NpdGVkKSBvdmVydmlld3MuIEV2ZXJ5XG4gKiBkaXNwbGF5ZWQgdGlsZSBpcyB0aGVuIHBlci1jaGFubmVsLWZldGNoYWJsZSBhdCBhbnkgem9vbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkT3NkVGlsZVNvdXJjZShkOiBUaWxlRGVzY3JpcHRvciwgc3BlYzogVGlsZVNvdXJjZVNwZWMpOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGNvbnN0IGxldmVscyA9IHNwZWMucmVhbExldmVsc09ubHkgIT0gbnVsbCA/IGQubGV2ZWxzLnNsaWNlKDAsIHNwZWMucmVhbExldmVsc09ubHkpIDogZC5sZXZlbHM7XG4gIGNvbnN0IG4gPSBsZXZlbHMubGVuZ3RoO1xuICBjb25zdCB0ID0gZC50aWxlU2l6ZTtcblxuICAvLyBPU0QgbGV2ZWwgaSAoMCA9IGNvYXJzZXN0KSA8LT4gYmFja2VuZCByZXNvbHV0aW9uIChuLTEtaSkgKHJlcyAwID0gZnVsbCkuXG4gIC8vIFRoZSBiYWNrZW5kIHB5cmFtaWQgaXMgTk9UIG5lY2Vzc2FyaWx5IHBvd2VyLW9mLXR3bywgc28gd2UgZHJpdmUgT1NEIG9mZlxuICAvLyB0aGUgYmFja2VuZCdzIHJlYWwgcGVyLWxldmVsIGRpbWVuc2lvbnMuIFdlIG92ZXJyaWRlIE9OTFkgZ2V0TGV2ZWxTY2FsZTpcbiAgLy8gT1NEIGRlcml2ZXMgZ2V0TnVtVGlsZXMsIGdldFRpbGVCb3VuZHMgQU5EIGl0cyBwZXItem9vbSBsZXZlbCBzZWxlY3Rpb25cbiAgLy8gZnJvbSBnZXRMZXZlbFNjYWxlLCBzbyB0aGV5IGFsbCBzdGF5IGNvbnNpc3RlbnQg4oCUIHJlcXVlc3RpbmcgZXhhY3RseSB0aGVcbiAgLy8gdGlsZXMgZWFjaCByZXNvbHV0aW9uIGFjdHVhbGx5IGhhcyAobm8gb3V0LW9mLXJhbmdlIDQwMHMsIG5vIGZsb29kKS5cbiAgY29uc3QgcmVzRm9yTGV2ZWwgPSAobGV2ZWw6IG51bWJlcikgPT4gbiAtIDEgLSBsZXZlbDtcbiAgY29uc3Qgb3NkID0gT1NEIGFzIHVua25vd24gYXMge1xuICAgIFRpbGVTb3VyY2U6IG5ldyAobzogb2JqZWN0KSA9PiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICBQb2ludDogbmV3ICh4OiBudW1iZXIsIHk6IG51bWJlcikgPT4gdW5rbm93bjtcbiAgfTtcbiAgY29uc3QgdHMgPSBuZXcgb3NkLlRpbGVTb3VyY2Uoe1xuICAgIHdpZHRoOiBkLndpZHRoLFxuICAgIGhlaWdodDogZC5oZWlnaHQsXG4gICAgdGlsZVNpemU6IHQsXG4gICAgdGlsZU92ZXJsYXA6IDAsXG4gICAgbWluTGV2ZWw6IDAsXG4gICAgbWF4TGV2ZWw6IG4gLSAxLFxuICB9KTtcbiAgdHNbJ2dldExldmVsU2NhbGUnXSA9IChsZXZlbDogbnVtYmVyKSA9PiB7XG4gICAgY29uc3QgbHZsID0gbGV2ZWxzW3Jlc0ZvckxldmVsKGxldmVsKV07XG4gICAgcmV0dXJuIGx2bCA/IGx2bC53aWR0aCAvIGQud2lkdGggOiAxO1xuICB9O1xuICAvLyBEcml2ZSB0aGUgdGlsZSBDT1VOVCBvZmYgZWFjaCBsZXZlbCdzIG93biAoaW5kZXBlbmRlbnRseS1yb3VuZGVkKSBkaW1lbnNpb25zLFxuICAvLyBub3QgT1NEJ3MgZGVmYXVsdCBgY2VpbChzY2FsZSAqIGZ1bGxEaW1lbnNpb24gLyB0aWxlU2l6ZSlgLiBTeW50aGV0aWMgQU5EIHJlYWxcbiAgLy8gQmlvLUZvcm1hdHMgbGV2ZWxzIGFyZW4ndCBleGFjdCBwcm9wb3J0aW9uYWwgc2NhbGVzIG9mIHRoZSBmdWxsIGltYWdlLCBzb1xuICAvLyBgc2NhbGUgKiBmdWxsSGVpZ2h0YCBjYW4gcm91bmQgdXAgdG8gb25lIG1vcmUgcm93IChvciBjb2x1bW4pIHRoYW4gdGhlIGxldmVsXG4gIC8vIGFjdHVhbGx5IGhhcyDigJQgT1NEIHRoZW4gcmVxdWVzdHMgYW4gb3V0LW9mLXJhbmdlIHRpbGUgdGhhdCB0aGUgc2VydmVyIDQwMHNcbiAgLy8gKFwiVGlsZSAoY29sLHJvdykgb3V0IG9mIHJhbmdlXCIpLiBVc2luZyB0aGUgbGV2ZWwncyByZWFsIHcvaCBtYXRjaGVzIHRoZVxuICAvLyBzZXJ2ZXIncyBvd24gYm91bmRzIGNoZWNrIGV4YWN0bHkuXG4gIHRzWydnZXROdW1UaWxlcyddID0gKGxldmVsOiBudW1iZXIpID0+IHtcbiAgICBjb25zdCBsdmwgPSBsZXZlbHNbcmVzRm9yTGV2ZWwobGV2ZWwpXTtcbiAgICBpZiAoIWx2bCkgcmV0dXJuIG5ldyBvc2QuUG9pbnQoMCwgMCk7XG4gICAgcmV0dXJuIG5ldyBvc2QuUG9pbnQoTWF0aC5jZWlsKGx2bC53aWR0aCAvIHQpLCBNYXRoLmNlaWwobHZsLmhlaWdodCAvIHQpKTtcbiAgfTtcbiAgdHNbJ2dldFRpbGVVcmwnXSA9IChsZXZlbDogbnVtYmVyLCB4OiBudW1iZXIsIHk6IG51bWJlcikgPT5cbiAgICBidWlsZFRpbGVVcmwoc3BlYy5hcGksIHNwZWMuaW5mb0I2NCwge1xuICAgICAgcmVzOiByZXNGb3JMZXZlbChsZXZlbCksXG4gICAgICBjb2w6IHgsXG4gICAgICByb3c6IHksXG4gICAgICB6OiBzcGVjLnosXG4gICAgICB0aWxlU2l6ZTogdCxcbiAgICAgIGNoYW5uZWw6IHNwZWMuY2hhbm5lbCxcbiAgICB9KTtcbiAgcmV0dXJuIHRzO1xufVxuIl19
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3NkLXZpZXdlci1saWtlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvb3NkL29zZC12aWV3ZXItbGlrZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgKiBhcyBPcGVuU2VhZHJhZ29uIGZyb20gJ29wZW5zZWFkcmFnb24nO1xuXG4vKipcbiAqIFRoZSBzbGljZSBvZiBhbiBPcGVuU2VhZHJhZ29uIGBWaWV3ZXJgIHRoYXQgdGhlIE9TRCBoZWxwZXJzIChvc2QtY29vcmRzLCB0aGVcbiAqIGNvb3JkaW5hdGUgdHJhbnNmb3JtLCB0aGUgc2NhbGUgYmFyLCB0aGUgcmVnaW9uIG92ZXJsYXkgYW5kIHRoZSBzbGljZSBjYWNoZSlcbiAqIGFjdHVhbGx5IHVzZSDigJQgYW5kIG5vdGhpbmcgbW9yZSAoT1NELVBMT1RMWS0yNykuXG4gKlxuICogVGhlIHJlYWwgYE9wZW5TZWFkcmFnb24uVmlld2VyYCBpcyBhc3NpZ25hYmxlIHRvIGl0IGFzIGlzLCBzbyB0aGUgc2VydmljZVxuICogcGFzc2VzIGl0cyB2aWV3ZXIgc3RyYWlnaHQgdGhyb3VnaDsgdGhlIHNwZWNzIGJ1aWxkIGEgc21hbGwgZmFrZSAoc2VlXG4gKiBgdGVzdGluZy9mYWtlLW9zZC12aWV3ZXIudHNgKSBpbnN0ZWFkIG9mIGNhc3RpbmcgYSBwYXJ0aWFsIG9iamVjdC4gUG9pbnRzIGFuZFxuICogcmVjdGFuZ2xlcyBhcmUgc3RydWN0dXJhbCB3aGVyZSB0aGUgaGVscGVycyBvbmx5IHJlYWQgYHhgL2B5YC9gd2lkdGhgL2BoZWlnaHRgO1xuICogYE9wZW5TZWFkcmFnb24uUmVjdGAgaXMga2VwdCBvbmx5IHdoZXJlIHRoZSByZXN1bHQgZ29lcyBiYWNrIGludG8gT1NEXG4gKiAoYGltYWdlVG9WaWV3cG9ydFJlY3RhbmdsZWAg4oaSIGB2aWV3cG9ydC5maXRCb3VuZHNgKS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPc2RWaWV3ZXJMaWtlIHtcbiAgLyoqIFRoZSBlbGVtZW50IE9TRCBkcmF3cyBpbnRvOyBvdmVybGF5cyAoc2NhbGUgYmFyLCByZWdpb24gU1ZHKSBhcmUgYXBwZW5kZWRcbiAgICogIGhlcmUgYW5kIGl0cyBjbGllbnQgcmVjdCBhbmNob3JzIGNsaWVudOKGlGVsZW1lbnQgY29udmVyc2lvbnMuICovXG4gIGNhbnZhczogSFRNTEVsZW1lbnQ7XG4gIC8qKiBUaGUgdmlld2VyJ3Mgcm9vdCBlbGVtZW50IChhbiBhbmNlc3RvciBvZiB0aGUgY2FudmFzIGFuZCBvZiB0aGUgdG9vbFxuICAgKiAgb3ZlcmxheXMpIOKAlCB0aGUgd2hlZWwtem9vbSBsaXN0ZW5lciBpcyBib3VuZCBoZXJlLiAqL1xuICBlbGVtZW50OiBIVE1MRWxlbWVudDtcbiAgdmlld3BvcnQ6IHtcbiAgICB2aWV3ZXJFbGVtZW50VG9WaWV3cG9ydENvb3JkaW5hdGVzKHA6IE9zZFhZKTogT3NkWFk7XG4gICAgdmlld3BvcnRUb1ZpZXdlckVsZW1lbnRDb29yZGluYXRlcyhwOiBPc2RYWSk6IE9zZFhZO1xuICAgIC8qKiBJbWFnZSBjb252ZXJzaW9ucyBvbiB0aGUgdmlld3BvcnQg4oCUIGFtYmlndW91cyBvbmNlIHRoZSB3b3JsZCBob2xkc1xuICAgICAqICBzZXZlcmFsIGltYWdlczsgdXNlZCBvbmx5IGFzIHRoZSBlbXB0eS13b3JsZCBmYWxsYmFjay4gKi9cbiAgICB2aWV3ZXJFbGVtZW50VG9JbWFnZUNvb3JkaW5hdGVzKHA6IE9zZFhZKTogT3NkWFk7XG4gICAgaW1hZ2VUb1ZpZXdlckVsZW1lbnRDb29yZGluYXRlcyhwOiBPc2RYWSk6IE9zZFhZO1xuICAgIGltYWdlVG9WaWV3cG9ydFJlY3RhbmdsZShyOiBPcGVuU2VhZHJhZ29uLlJlY3QpOiBPcGVuU2VhZHJhZ29uLlJlY3Q7XG4gICAgdmlld3BvcnRUb0ltYWdlUmVjdGFuZ2xlKHI6IE9zZFJlY3RMaWtlKTogT3NkUmVjdExpa2U7XG4gICAgLyoqIFZpZXdlci1lbGVtZW50IHBpeGVsIOKGkiB2aWV3cG9ydCBwb2ludCAodGhlIHdoZWVsLXpvb20gYW5jaG9yKS4gKi9cbiAgICBwb2ludEZyb21QaXhlbChwOiBPc2RYWSk6IE9zZFhZO1xuICAgIHpvb21CeShmYWN0b3I6IG51bWJlciwgcmVmUG9pbnQ/OiBPc2RYWSk6IHVua25vd247XG4gICAgYXBwbHlDb25zdHJhaW50cyhpbW1lZGlhdGVseT86IGJvb2xlYW4pOiB1bmtub3duO1xuICB9O1xuICB3b3JsZDoge1xuICAgIGdldEl0ZW1Db3VudCgpOiBudW1iZXI7XG4gICAgLyoqIGB1bmRlZmluZWRgIHBhc3QgdGhlIGVuZCBvZiB0aGUgd29ybGQgKE9TRCByZXR1cm5zIGl0IGF0IHJ1bnRpbWUpLiAqL1xuICAgIGdldEl0ZW1BdChpbmRleDogbnVtYmVyKTogT3NkVGlsZWRJbWFnZUxpa2UgfCB1bmRlZmluZWQ7XG4gICAgLyoqIC0xIHdoZW4gdGhlIGl0ZW0gaXMgbm8gbG9uZ2VyIGluIHRoZSB3b3JsZCAoZXZpY3RlZCAvIHJlbW92ZWQpLiAqL1xuICAgIGdldEluZGV4T2ZJdGVtKGl0ZW06IE9zZFRpbGVkSW1hZ2VMaWtlKTogbnVtYmVyO1xuICAgIHJlbW92ZUl0ZW0oaXRlbTogT3NkVGlsZWRJbWFnZUxpa2UpOiB2b2lkO1xuICB9O1xuICAvKiogUXVldWUgYSB0aWxlZCBpbWFnZSBpbnRvIHRoZSB3b3JsZDsgYHN1Y2Nlc3NgIGZpcmVzIG9uY2UgaXQgaXMgYWRkZWQgKG5vdFxuICAgKiAgb25jZSBpdHMgdGlsZXMgaGF2ZSBsb2FkZWQpLiAqL1xuICBhZGRUaWxlZEltYWdlKG9wdGlvbnM6IE9zZEFkZFRpbGVkSW1hZ2VPcHRpb25zKTogdm9pZDtcbiAgYWRkSGFuZGxlcihldmVudDogT3NkVmlld2VyRXZlbnROYW1lLCBoYW5kbGVyOiAoKSA9PiB2b2lkKTogdW5rbm93bjtcbiAgcmVtb3ZlSGFuZGxlcihldmVudDogT3NkVmlld2VyRXZlbnROYW1lLCBoYW5kbGVyOiAoKSA9PiB2b2lkKTogdW5rbm93bjtcbiAgLyoqIE9TRCdzIG93biBwYW4vem9vbSAoZHJhZyArIHdoZWVsKTsgcmVnaW9uIHRvb2xzIHN3aXRjaCBpdCBvZmYuICovXG4gIHNldE1vdXNlTmF2RW5hYmxlZChlbmFibGVkOiBib29sZWFuKTogdW5rbm93bjtcbiAgaXNNb3VzZU5hdkVuYWJsZWQoKTogYm9vbGVhbjtcbn1cblxuLyoqIEEgcG9pbnQgaW4gYW55IE9TRCBzcGFjZSAodmlld2VyLWVsZW1lbnQgcHgsIHZpZXdwb3J0IHVuaXRzIG9yIGltYWdlIHB4IOKAlFxuICogIHRoZSBtZXRob2QgaXQgY29tZXMgZnJvbSBzYXlzIHdoaWNoKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3NkWFkge1xuICB4OiBudW1iZXI7XG4gIHk6IG51bWJlcjtcbn1cblxuLyoqIEFuIGF4aXMtYWxpZ25lZCByZWN0YW5nbGUsIGluIHRoZSBzcGFjZSBvZiB0aGUgbWV0aG9kIHRoYXQgcHJvZHVjZWQgaXQuICovXG5leHBvcnQgaW50ZXJmYWNlIE9zZFJlY3RMaWtlIHtcbiAgeDogbnVtYmVyO1xuICB5OiBudW1iZXI7XG4gIHdpZHRoOiBudW1iZXI7XG4gIGhlaWdodDogbnVtYmVyO1xufVxuXG4vKiogVGhlIG1lbWJlcnMgb2YgYW4gT1NEIGBUaWxlZEltYWdlYCAob25lIHdvcmxkIGl0ZW06IGFuIGltYWdlLCBhIHN0YWNrIHNsaWNlXG4gKiAgb3Igb25lIGNoYW5uZWwgbGF5ZXIpIHRoZSBoZWxwZXJzIHVzZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3NkVGlsZWRJbWFnZUxpa2Uge1xuICB2aWV3cG9ydFRvSW1hZ2VDb29yZGluYXRlcyhwOiBPc2RYWSk6IE9zZFhZO1xuICBpbWFnZVRvVmlld3BvcnRDb29yZGluYXRlcyhwOiBPc2RYWSk6IE9zZFhZO1xuICBpbWFnZVRvVmlld3BvcnRSZWN0YW5nbGUocjogT3BlblNlYWRyYWdvbi5SZWN0KTogT3BlblNlYWRyYWdvbi5SZWN0O1xuICB2aWV3cG9ydFRvSW1hZ2VSZWN0YW5nbGUocjogT3NkUmVjdExpa2UpOiBPc2RSZWN0TGlrZTtcbiAgc2V0T3BhY2l0eShvcGFjaXR5OiBudW1iZXIpOiB2b2lkO1xuICAvKiogRmFsc2Ugd2hpbGUgYW55IG9mIHRoZSBpbWFnZSdzIHRpbGVzIGFyZSBzdGlsbCBsb2FkaW5nLiAqL1xuICBnZXRGdWxseUxvYWRlZCgpOiBib29sZWFuO1xuICAvKiogUmUtcnVuIHRoZSB0aWxlIHBpcGVsaW5lIChyZXN0b3JlICsgcmUtcHJvY2VzcykgZm9yIHRoaXMgaW1hZ2UncyB0aWxlcztcbiAgICogIHRpbGVzIGFscmVhZHkgc3RhbXBlZCBhdCBgPj0gdFN0YW1wYCBhcmUgc2tpcHBlZC4gT3B0aW9uYWw6IHRoZSBzbGljZVxuICAgKiAgY2FjaGUgZmVhdHVyZS10ZXN0cyBpdC4gKi9cbiAgcmVxdWVzdEludmFsaWRhdGU/KHJlc3RvcmVUaWxlcz86IGJvb2xlYW4sIHZpZXdwb3J0T25seT86IGJvb2xlYW4sIHRTdGFtcD86IG51bWJlcik6IHVua25vd247XG59XG5cbi8qKiBUaGUgYGFkZFRpbGVkSW1hZ2VgIG9wdGlvbnMgdGhlIHNsaWNlIGNhY2hlIHBhc3Nlcy4gSW1hZ2UgcGxhY2VtZW50IGlzIGluXG4gKiAgdmlld3BvcnQgdW5pdHMgKGB3aWR0aDogMWAgPSB0aGUgcHJpbWFyeSBpbWFnZSdzIG5vcm1hbGl6ZWQgd2lkdGgpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBPc2RBZGRUaWxlZEltYWdlT3B0aW9ucyB7XG4gIHRpbGVTb3VyY2U6IHN0cmluZyB8IG9iamVjdDtcbiAgeD86IG51bWJlcjtcbiAgeT86IG51bWJlcjtcbiAgd2lkdGg/OiBudW1iZXI7XG4gIG9wYWNpdHk/OiBudW1iZXI7XG4gIC8qKiBMb2FkIHRpbGVzIGV2ZW4gd2hpbGUgaGlkZGVuIChvcGFjaXR5IDApLiAqL1xuICBwcmVsb2FkPzogYm9vbGVhbjtcbiAgLyoqIENhbnZhcyBjb21wb3NpdGUgb3BlcmF0aW9uLCBlLmcuIGAnbGlnaHRlcidgIGZvciBhZGRpdGl2ZSBjaGFubmVscy4gKi9cbiAgY29tcG9zaXRlT3BlcmF0aW9uPzogc3RyaW5nO1xuICAvKiogRmlyZXMgb25jZSB0aGUgaW1hZ2UgaXMgaW4gdGhlIHdvcmxkLiBPU0QgdHlwZXMgdGhlIHBheWxvYWQgYXMgYSBET01cbiAgICogIGBFdmVudGA7IGF0IHJ1bnRpbWUgaXQgY2FycmllcyB0aGUgYWRkZWQgYGl0ZW1gLiAqL1xuICBzdWNjZXNzPyhldmVudDogRXZlbnQgJiB7IGl0ZW0/OiBPc2RUaWxlZEltYWdlTGlrZSB9KTogdm9pZDtcbiAgZXJyb3I/KCk6IHZvaWQ7XG59XG5cbi8qKiBUaGUgdmlld2VyIGV2ZW50cyB0aGUgaGVscGVycyBzdWJzY3JpYmUgdG8uICovXG5leHBvcnQgdHlwZSBPc2RWaWV3ZXJFdmVudE5hbWUgPSAndXBkYXRlLXZpZXdwb3J0JyB8ICdhbmltYXRpb24nIHwgJ3Jlc2l6ZScgfCAncm90YXRlJztcbiJdfQ==
@@ -0,0 +1,44 @@
1
+ import { OSD } from './osd-lib';
2
+ import { silenceOsdMultiImageAdvisory } from './openseadragon-viewer-options';
3
+ /** How long a mount waits for OSD's `open`/`open-failed` before giving up. */
4
+ export const OSD_OPEN_TIMEOUT_MS = 8000;
5
+ /** Create an OpenSeadragon viewer (synchronously: a throwing factory throws here). */
6
+ export function createViewer(options) {
7
+ silenceOsdMultiImageAdvisory();
8
+ return OSD(options);
9
+ }
10
+ /**
11
+ * Open `tileSource` in `viewer`. `onOpen` wires the freshly opened viewer
12
+ * (overlays, handlers); the promise resolves true once it ran, false on
13
+ * `open-failed` — and ALWAYS settles: if OSD never emits either (a bad tile
14
+ * source, a viewer torn down mid-open), the render pipeline must not hang, since
15
+ * a hang leaves imageLoading=true, sticking the spinner and the 500ms
16
+ * cache-progress poll forever (NS_BINDING_ABORTED storm).
17
+ */
18
+ export function openViewer(viewer, tileSource, onOpen) {
19
+ return new Promise((resolve) => {
20
+ let settled = false;
21
+ const done = (ok) => {
22
+ if (!settled) {
23
+ settled = true;
24
+ resolve(ok);
25
+ }
26
+ };
27
+ viewer.addOnceHandler('open', () => {
28
+ onOpen(viewer);
29
+ done(true);
30
+ });
31
+ viewer.addOnceHandler('open-failed', (e) => {
32
+ const err = e;
33
+ console.warn('[OSD] open-failed', err?.message ?? e);
34
+ done(false);
35
+ });
36
+ setTimeout(() => {
37
+ if (!settled)
38
+ console.warn('[OSD] viewer open timed out');
39
+ done(false);
40
+ }, OSD_OPEN_TIMEOUT_MS);
41
+ viewer.open(tileSource);
42
+ });
43
+ }
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3NkLXZpZXdlci1tb3VudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvaW1wbGVtZW50YXRpb25zL29zZC9vc2Qtdmlld2VyLW1vdW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDaEMsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFOUUsOEVBQThFO0FBQzlFLE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQztBQUV4QyxzRkFBc0Y7QUFDdEYsTUFBTSxVQUFVLFlBQVksQ0FBQyxPQUFnQztJQUMzRCw0QkFBNEIsRUFBRSxDQUFDO0lBQy9CLE9BQVEsR0FBdUUsQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUMzRixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxVQUFVLENBQ3hCLE1BQTRCLEVBQzVCLFVBQW1CLEVBQ25CLE1BQThDO0lBRTlDLE9BQU8sSUFBSSxPQUFPLENBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRTtRQUN0QyxJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDcEIsTUFBTSxJQUFJLEdBQUcsQ0FBQyxFQUFXLEVBQUUsRUFBRTtZQUMzQixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2IsT0FBTyxHQUFHLElBQUksQ0FBQztnQkFDZixPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDZCxDQUFDO1FBQ0gsQ0FBQyxDQUFDO1FBQ0YsTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFO1lBQ2pDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNmLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNiLENBQUMsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxDQUFDLGNBQWMsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUN6QyxNQUFNLEdBQUcsR0FBRyxDQUFxQyxDQUFDO1lBQ2xELE9BQU8sQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsR0FBRyxFQUFFLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNyRCxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDZCxDQUFDLENBQUMsQ0FBQztRQUNILFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxJQUFJLENBQUMsT0FBTztnQkFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUM7WUFDMUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2QsQ0FBQyxFQUFFLG1CQUFtQixDQUFDLENBQUM7UUFDeEIsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUF5RCxDQUFDLENBQUM7SUFDekUsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgKiBhcyBPcGVuU2VhZHJhZ29uIGZyb20gJ29wZW5zZWFkcmFnb24nO1xuXG5pbXBvcnQgeyBPU0QgfSBmcm9tICcuL29zZC1saWInO1xuaW1wb3J0IHsgc2lsZW5jZU9zZE11bHRpSW1hZ2VBZHZpc29yeSB9IGZyb20gJy4vb3BlbnNlYWRyYWdvbi12aWV3ZXItb3B0aW9ucyc7XG5cbi8qKiBIb3cgbG9uZyBhIG1vdW50IHdhaXRzIGZvciBPU0QncyBgb3BlbmAvYG9wZW4tZmFpbGVkYCBiZWZvcmUgZ2l2aW5nIHVwLiAqL1xuZXhwb3J0IGNvbnN0IE9TRF9PUEVOX1RJTUVPVVRfTVMgPSA4MDAwO1xuXG4vKiogQ3JlYXRlIGFuIE9wZW5TZWFkcmFnb24gdmlld2VyIChzeW5jaHJvbm91c2x5OiBhIHRocm93aW5nIGZhY3RvcnkgdGhyb3dzIGhlcmUpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVZpZXdlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IE9wZW5TZWFkcmFnb24uVmlld2VyIHtcbiAgc2lsZW5jZU9zZE11bHRpSW1hZ2VBZHZpc29yeSgpO1xuICByZXR1cm4gKE9TRCBhcyB1bmtub3duIGFzIChvOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gT3BlblNlYWRyYWdvbi5WaWV3ZXIpKG9wdGlvbnMpO1xufVxuXG4vKipcbiAqIE9wZW4gYHRpbGVTb3VyY2VgIGluIGB2aWV3ZXJgLiBgb25PcGVuYCB3aXJlcyB0aGUgZnJlc2hseSBvcGVuZWQgdmlld2VyXG4gKiAob3ZlcmxheXMsIGhhbmRsZXJzKTsgdGhlIHByb21pc2UgcmVzb2x2ZXMgdHJ1ZSBvbmNlIGl0IHJhbiwgZmFsc2Ugb25cbiAqIGBvcGVuLWZhaWxlZGAg4oCUIGFuZCBBTFdBWVMgc2V0dGxlczogaWYgT1NEIG5ldmVyIGVtaXRzIGVpdGhlciAoYSBiYWQgdGlsZVxuICogc291cmNlLCBhIHZpZXdlciB0b3JuIGRvd24gbWlkLW9wZW4pLCB0aGUgcmVuZGVyIHBpcGVsaW5lIG11c3Qgbm90IGhhbmcsIHNpbmNlXG4gKiBhIGhhbmcgbGVhdmVzIGltYWdlTG9hZGluZz10cnVlLCBzdGlja2luZyB0aGUgc3Bpbm5lciBhbmQgdGhlIDUwMG1zXG4gKiBjYWNoZS1wcm9ncmVzcyBwb2xsIGZvcmV2ZXIgKE5TX0JJTkRJTkdfQUJPUlRFRCBzdG9ybSkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvcGVuVmlld2VyKFxuICB2aWV3ZXI6IE9wZW5TZWFkcmFnb24uVmlld2VyLFxuICB0aWxlU291cmNlOiB1bmtub3duLFxuICBvbk9wZW46ICh2aWV3ZXI6IE9wZW5TZWFkcmFnb24uVmlld2VyKSA9PiB2b2lkLFxuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZTxib29sZWFuPigocmVzb2x2ZSkgPT4ge1xuICAgIGxldCBzZXR0bGVkID0gZmFsc2U7XG4gICAgY29uc3QgZG9uZSA9IChvazogYm9vbGVhbikgPT4ge1xuICAgICAgaWYgKCFzZXR0bGVkKSB7XG4gICAgICAgIHNldHRsZWQgPSB0cnVlO1xuICAgICAgICByZXNvbHZlKG9rKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHZpZXdlci5hZGRPbmNlSGFuZGxlcignb3BlbicsICgpID0+IHtcbiAgICAgIG9uT3Blbih2aWV3ZXIpO1xuICAgICAgZG9uZSh0cnVlKTtcbiAgICB9KTtcbiAgICB2aWV3ZXIuYWRkT25jZUhhbmRsZXIoJ29wZW4tZmFpbGVkJywgKGUpID0+IHtcbiAgICAgIGNvbnN0IGVyciA9IGUgYXMgeyBtZXNzYWdlPzogc3RyaW5nIH0gfCB1bmRlZmluZWQ7XG4gICAgICBjb25zb2xlLndhcm4oJ1tPU0RdIG9wZW4tZmFpbGVkJywgZXJyPy5tZXNzYWdlID8/IGUpO1xuICAgICAgZG9uZShmYWxzZSk7XG4gICAgfSk7XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAoIXNldHRsZWQpIGNvbnNvbGUud2FybignW09TRF0gdmlld2VyIG9wZW4gdGltZWQgb3V0Jyk7XG4gICAgICBkb25lKGZhbHNlKTtcbiAgICB9LCBPU0RfT1BFTl9USU1FT1VUX01TKTtcbiAgICB2aWV3ZXIub3Blbih0aWxlU291cmNlIGFzIFBhcmFtZXRlcnM8T3BlblNlYWRyYWdvbi5WaWV3ZXJbJ29wZW4nXT5bMF0pO1xuICB9KTtcbn1cbiJdfQ==
@@ -0,0 +1,184 @@
1
+ import { Subject, defer } from 'rxjs';
2
+ import { startWith } from 'rxjs/operators';
3
+ import { quiet } from './osd-lib';
4
+ import { ZOOM_BUTTON_STEP } from './osd-zoom';
5
+ import { imageRectToViewport, viewportRectToImage } from './osd-coords';
6
+ /**
7
+ * The OpenSeadragon viewport as the rest of the library sees it: the visible
8
+ * image rect (settled, and per animation frame), the {@link PlotModeViewport} a
9
+ * contributed plot mode draws over, and the zoom/fit commands.
10
+ *
11
+ * Every member reads the CURRENT viewer through the host, so one instance lives
12
+ * as long as the service and stays valid across viewer rebuilds.
13
+ */
14
+ export class OsdViewportAdapter {
15
+ constructor(host) {
16
+ this.host = host;
17
+ /** Visible image region (full-image pixel coords) emitted when the view
18
+ * settles, so the intensity inset can re-sample at the current zoom level. */
19
+ this.viewportChange$ = new Subject();
20
+ /** The visible rect on every redraw, coalesced to one emission per animation
21
+ * frame. Feeds {@link PlotModeViewport.frame$}. */
22
+ this.frame$ = new Subject();
23
+ this.frameRaf = null;
24
+ this.plotModeViewport = null;
25
+ }
26
+ /** Compute the current viewport's image-pixel rectangle (clamped to the image)
27
+ * and broadcast it. */
28
+ emitViewportChange() {
29
+ const rect = this.visibleImageRect();
30
+ if (rect)
31
+ this.viewportChange$.next(rect);
32
+ }
33
+ /** The current viewport's image-pixel rectangle, clamped to the image, or
34
+ * null when there is no laid-out viewport. */
35
+ visibleImageRect() {
36
+ const viewer = this.host.viewer();
37
+ const d = this.host.descriptor();
38
+ const vp = viewer?.viewport;
39
+ if (!vp || !d)
40
+ return null;
41
+ try {
42
+ // Route through world item 0 (osd-coords): vp.viewportToImageRectangle is
43
+ // inaccurate and warns when the world holds multiple images (per-channel
44
+ // multichannel layers), which fed the intensity inset a wrong ROI.
45
+ const r = viewportRectToImage(viewer, vp.getBounds(true));
46
+ const iw = d.width, ih = d.height;
47
+ const x = Math.max(0, Math.min(iw, r.x));
48
+ const y = Math.max(0, Math.min(ih, r.y));
49
+ const width = Math.max(1, Math.min(iw - x, r.width));
50
+ const height = Math.max(1, Math.min(ih - y, r.height));
51
+ return { x, y, width, height };
52
+ }
53
+ catch {
54
+ return null; /* viewport not ready */
55
+ }
56
+ }
57
+ /**
58
+ * Image-pixel rectangle the drawer canvas currently covers. Unlike
59
+ * {@link visibleImageRect}, this is NOT clamped to the image bounds: the canvas
60
+ * maps 1:1 to the viewport rectangle, so leaving it unclamped keeps
61
+ * `canvasPx -> imagePx` an exact affine map (clamping would skew coordinates
62
+ * near the image edges). Routed through world item 0 (see
63
+ * {@link viewportRectToImage}) for multi-layer accuracy.
64
+ */
65
+ displayedSourceRect() {
66
+ const viewer = this.host.viewer();
67
+ const vp = viewer?.viewport;
68
+ if (!vp || !this.host.descriptor())
69
+ return null;
70
+ try {
71
+ const r = viewportRectToImage(viewer, vp.getBounds(true));
72
+ return { x: r.x, y: r.y, width: r.width, height: r.height };
73
+ }
74
+ catch {
75
+ return null;
76
+ }
77
+ }
78
+ /** Coalesce redraws into one {@link frame$} emission per animation frame.
79
+ * Skipped entirely while nothing listens. */
80
+ scheduleFrame() {
81
+ if (this.frameRaf !== null || !this.frame$.observed)
82
+ return;
83
+ this.frameRaf = requestAnimationFrame(() => {
84
+ this.frameRaf = null;
85
+ const rect = this.visibleImageRect();
86
+ if (rect)
87
+ this.frame$.next(rect);
88
+ });
89
+ }
90
+ /** Drop a pending {@link scheduleFrame} (the viewer is going away). */
91
+ cancelFrame() {
92
+ if (this.frameRaf !== null) {
93
+ cancelAnimationFrame(this.frameRaf);
94
+ this.frameRaf = null;
95
+ }
96
+ }
97
+ /**
98
+ * The viewport a contributed plot mode draws over. One stable object per
99
+ * service: every method reads the CURRENT viewer, so it stays valid across a
100
+ * viewer rebuild and reports `isReady() === false` while none is mounted
101
+ * (conversions then return NaN rather than throwing).
102
+ */
103
+ plotModeViewportFor() {
104
+ if (this.plotModeViewport)
105
+ return this.plotModeViewport;
106
+ const nan = { x: NaN, y: NaN };
107
+ const ct = () => this.host.coordTransform();
108
+ const ready = () => !!ct()?.isReady();
109
+ this.plotModeViewport = {
110
+ getOverlayContainer: () => this.host.overlayContainer(),
111
+ dataToClient: (x, y) => (ready() ? ct().dataToClient(x, y) : nan),
112
+ clientToData: (cx, cy) => (ready() ? ct().clientToData(cx, cy) : nan),
113
+ dataLengthToScreen: (len) => (ready() ? ct().dataLengthToScreen(len) : NaN),
114
+ isReady: ready,
115
+ // Both start with the current visible rect when the viewport is ready: a mode
116
+ // activates after the base render has gone idle, so without it an overlay
117
+ // following `frame$.subscribe(redraw)` would stay blank until the next pan/zoom.
118
+ frame$: this.withCurrentRect(this.frame$, ready),
119
+ settled$: this.withCurrentRect(this.viewportChange$, ready),
120
+ fitBounds: (rect, options) => {
121
+ const viewer = this.host.viewer();
122
+ if (!viewer || !ready() || !(rect.width > 0) || !(rect.height > 0))
123
+ return;
124
+ const vpRect = imageRectToViewport(viewer, rect.x, rect.y, rect.width, rect.height);
125
+ viewer.viewport.fitBoundsWithConstraints(vpRect, !!options?.immediately);
126
+ },
127
+ };
128
+ return this.plotModeViewport;
129
+ }
130
+ /** `source`, preceded by the current visible rect for each subscriber (when ready). */
131
+ withCurrentRect(source, ready) {
132
+ return defer(() => {
133
+ const rect = ready() ? this.visibleImageRect() : null;
134
+ return rect ? source.pipe(startWith(rect)) : source.asObservable();
135
+ });
136
+ }
137
+ /**
138
+ * Keep the user's current view across a container/split resize instead of
139
+ * snapping home. Viewport bounds are image-relative (image width = 1), so
140
+ * they're independent of the container's pixel size — capture the visible
141
+ * region now and re-fit it once the new size has settled. OSD's autoResize
142
+ * fires asynchronously and the angular-split transition animates the width
143
+ * over a few hundred ms, so restore on the next frame and again after the
144
+ * transition completes.
145
+ */
146
+ keepViewAcrossResize() {
147
+ const vp = this.host.viewer()?.viewport;
148
+ if (!vp)
149
+ return;
150
+ const bounds = vp.getBounds(true);
151
+ const restore = () => quiet(() => {
152
+ this.host.viewer()?.viewport.fitBounds(bounds, true);
153
+ this.host.viewer()?.viewport.applyConstraints(true);
154
+ });
155
+ requestAnimationFrame(restore);
156
+ setTimeout(restore, 350);
157
+ }
158
+ goHome() {
159
+ this.host.viewer()?.viewport.goHome();
160
+ }
161
+ /** Zoom by one button step about the centre (`factor` > 1 zooms in). */
162
+ zoomBy(direction) {
163
+ const vp = this.host.viewer()?.viewport;
164
+ vp?.zoomBy(direction > 0 ? ZOOM_BUTTON_STEP : 1 / ZOOM_BUTTON_STEP);
165
+ vp?.applyConstraints();
166
+ }
167
+ /** Fit the OSD viewport to an image-space rectangle (coords ordered
168
+ * [xMin, xMax, yMax, yMin]). */
169
+ applyZoomToBox(coordinates) {
170
+ const viewer = this.host.viewer();
171
+ if (!viewer || coordinates.length < 4)
172
+ return;
173
+ const [a, b, c, d] = coordinates;
174
+ const x = Math.min(a, b);
175
+ const w = Math.abs(b - a);
176
+ const y = Math.min(c, d);
177
+ const h = Math.abs(c - d);
178
+ if (w <= 0 || h <= 0)
179
+ return;
180
+ const rect = imageRectToViewport(viewer, x, y, w, h);
181
+ viewer.viewport.fitBounds(rect, false);
182
+ }
183
+ }
184
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3NkLXZpZXdwb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvb3NkL29zZC12aWV3cG9ydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHM0MsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDOUMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLG1CQUFtQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBYXhFOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLE9BQU8sa0JBQWtCO0lBVTdCLFlBQTZCLElBQXFCO1FBQXJCLFNBQUksR0FBSixJQUFJLENBQWlCO1FBVGxEO3VGQUMrRTtRQUN0RSxvQkFBZSxHQUFHLElBQUksT0FBTyxFQUFnQixDQUFDO1FBQ3ZEOzREQUNvRDtRQUNuQyxXQUFNLEdBQUcsSUFBSSxPQUFPLEVBQWdCLENBQUM7UUFDOUMsYUFBUSxHQUFrQixJQUFJLENBQUM7UUFDL0IscUJBQWdCLEdBQTRCLElBQUksQ0FBQztJQUVKLENBQUM7SUFFdEQ7NEJBQ3dCO0lBQ3hCLGtCQUFrQjtRQUNoQixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUNyQyxJQUFJLElBQUk7WUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQ7bURBQytDO0lBQy9DLGdCQUFnQjtRQUNkLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDbEMsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUks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ZWN0LCBkZWZlciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgc3RhcnRXaXRoIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHR5cGUgKiBhcyBPcGVuU2VhZHJhZ29uIGZyb20gJ29wZW5zZWFkcmFnb24nO1xuXG5pbXBvcnQgeyBxdWlldCB9IGZyb20gJy4vb3NkLWxpYic7XG5pbXBvcnQgeyBaT09NX0JVVFRPTl9TVEVQIH0gZnJvbSAnLi9vc2Qtem9vbSc7XG5pbXBvcnQgeyBpbWFnZVJlY3RUb1ZpZXdwb3J0LCB2aWV3cG9ydFJlY3RUb0ltYWdlIH0gZnJvbSAnLi9vc2QtY29vcmRzJztcbmltcG9ydCB7IE9zZENvb3JkaW5hdGVUcmFuc2Zvcm0gfSBmcm9tICcuL29zZC1jb29yZGluYXRlLXRyYW5zZm9ybSc7XG5pbXBvcnQgeyBQbG90TW9kZVJlY3QsIFBsb3RNb2RlVmlld3BvcnQgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvcGxvdC10eXBlLWNvbnRyaWJ1dGlvbi5jb250cmFjdCc7XG5pbXBvcnQgeyBUaWxlRGVzY3JpcHRvciB9IGZyb20gJy4uL3RpbGUtc2VydmVyJztcblxuLyoqIFRoZSBzZXJ2aWNlIHN0YXRlIHRoZSB2aWV3cG9ydCBhZGFwdGVyIHJlYWRzIOKAlCBsaXZlLCBzbyBpdCBmb2xsb3dzIGEgdmlld2VyIHJlYnVpbGQuICovXG5leHBvcnQgaW50ZXJmYWNlIE9zZFZpZXdwb3J0SG9zdCB7XG4gIHZpZXdlcigpOiBPcGVuU2VhZHJhZ29uLlZpZXdlciB8IG51bGw7XG4gIGRlc2NyaXB0b3IoKTogVGlsZURlc2NyaXB0b3IgfCBudWxsO1xuICBjb29yZFRyYW5zZm9ybSgpOiBPc2RDb29yZGluYXRlVHJhbnNmb3JtIHwgbnVsbDtcbiAgb3ZlcmxheUNvbnRhaW5lcigpOiBIVE1MRWxlbWVudCB8IG51bGw7XG59XG5cbi8qKlxuICogVGhlIE9wZW5TZWFkcmFnb24gdmlld3BvcnQgYXMgdGhlIHJlc3Qgb2YgdGhlIGxpYnJhcnkgc2VlcyBpdDogdGhlIHZpc2libGVcbiAqIGltYWdlIHJlY3QgKHNldHRsZWQsIGFuZCBwZXIgYW5pbWF0aW9uIGZyYW1lKSwgdGhlIHtAbGluayBQbG90TW9kZVZpZXdwb3J0fSBhXG4gKiBjb250cmlidXRlZCBwbG90IG1vZGUgZHJhd3Mgb3ZlciwgYW5kIHRoZSB6b29tL2ZpdCBjb21tYW5kcy5cbiAqXG4gKiBFdmVyeSBtZW1iZXIgcmVhZHMgdGhlIENVUlJFTlQgdmlld2VyIHRocm91Z2ggdGhlIGhvc3QsIHNvIG9uZSBpbnN0YW5jZSBsaXZlc1xuICogYXMgbG9uZyBhcyB0aGUgc2VydmljZSBhbmQgc3RheXMgdmFsaWQgYWNyb3NzIHZpZXdlciByZWJ1aWxkcy5cbiAqL1xuZXhwb3J0IGNsYXNzIE9zZFZpZXdwb3J0QWRhcHRlciB7XG4gIC8qKiBWaXNpYmxlIGltYWdlIHJlZ2lvbiAoZnVsbC1pbWFnZSBwaXhlbCBjb29yZHMpIGVtaXR0ZWQgd2hlbiB0aGUgdmlld1xuICAgKiAgc2V0dGxlcywgc28gdGhlIGludGVuc2l0eSBpbnNldCBjYW4gcmUtc2FtcGxlIGF0IHRoZSBjdXJyZW50IHpvb20gbGV2ZWwuICovXG4gIHJlYWRvbmx5IHZpZXdwb3J0Q2hhbmdlJCA9IG5ldyBTdWJqZWN0PFBsb3RNb2RlUmVjdD4oKTtcbiAgLyoqIFRoZSB2aXNpYmxlIHJlY3Qgb24gZXZlcnkgcmVkcmF3LCBjb2FsZXNjZWQgdG8gb25lIGVtaXNzaW9uIHBlciBhbmltYXRpb25cbiAgICogIGZyYW1lLiBGZWVkcyB7QGxpbmsgUGxvdE1vZGVWaWV3cG9ydC5mcmFtZSR9LiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGZyYW1lJCA9IG5ldyBTdWJqZWN0PFBsb3RNb2RlUmVjdD4oKTtcbiAgcHJpdmF0ZSBmcmFtZVJhZjogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcGxvdE1vZGVWaWV3cG9ydDogUGxvdE1vZGVWaWV3cG9ydCB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgaG9zdDogT3NkVmlld3BvcnRIb3N0KSB7fVxuXG4gIC8qKiBDb21wdXRlIHRoZSBjdXJyZW50IHZpZXdwb3J0J3MgaW1hZ2UtcGl4ZWwgcmVjdGFuZ2xlIChjbGFtcGVkIHRvIHRoZSBpbWFnZSlcbiAgICogIGFuZCBicm9hZGNhc3QgaXQuICovXG4gIGVtaXRWaWV3cG9ydENoYW5nZSgpOiB2b2lkIHtcbiAgICBjb25zdCByZWN0ID0gdGhpcy52aXNpYmxlSW1hZ2VSZWN0KCk7XG4gICAgaWYgKHJlY3QpIHRoaXMudmlld3BvcnRDaGFuZ2UkLm5leHQocmVjdCk7XG4gIH1cblxuICAvKiogVGhlIGN1cnJlbnQgdmlld3BvcnQncyBpbWFnZS1waXhlbCByZWN0YW5nbGUsIGNsYW1wZWQgdG8gdGhlIGltYWdlLCBvclxuICAgKiAgbnVsbCB3aGVuIHRoZXJlIGlzIG5vIGxhaWQtb3V0IHZpZXdwb3J0LiAqL1xuICB2aXNpYmxlSW1hZ2VSZWN0KCk6IFBsb3RNb2RlUmVjdCB8IG51bGwge1xuICAgIGNvbnN0IHZpZXdlciA9IHRoaXMuaG9zdC52aWV3ZXIoKTtcbiAgICBjb25zdCBkID0gdGhpcy5ob3N0LmRlc2NyaXB0b3IoKTtcbiAgICBjb25zdCB2cCA9IHZpZXdlcj8udmlld3BvcnQ7XG4gICAgaWYgKCF2cCB8fCAhZCkgcmV0dXJuIG51bGw7XG4gICAgdHJ5IHtcbiAgICAgIC8vIFJvdXRlIHRocm91Z2ggd29ybGQgaXRlbSAwIChvc2QtY29vcmRzKTogdnAudmlld3BvcnRUb0ltYWdlUmVjdGFuZ2xlIGlzXG4gICAgICAvLyBpbmFjY3VyYXRlIGFuZCB3YXJucyB3aGVuIHRoZSB3b3JsZCBob2xkcyBtdWx0aXBsZSBpbWFnZXMgKHBlci1jaGFubmVsXG4gICAgICAvLyBtdWx0aWNoYW5uZWwgbGF5ZXJzKSwgd2hpY2ggZmVkIHRoZSBpbnRlbnNpdHkgaW5zZXQgYSB3cm9uZyBST0kuXG4gICAgICBjb25zdCByID0gdmlld3BvcnRSZWN0VG9JbWFnZSh2aWV3ZXIsIHZwLmdldEJvdW5kcyh0cnVlKSk7XG4gICAgICBjb25zdCBpdyA9IGQud2lkdGgsXG4gICAgICAgIGloID0gZC5oZWlnaHQ7XG4gICAgICBjb25zdCB4ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oaXcsIHIueCkpO1xuICAgICAgY29uc3QgeSA9IE1hdGgubWF4KDAsIE1hdGgubWluKGloLCByLnkpKTtcbiAgICAgIGNvbnN0IHdpZHRoID0gTWF0aC5tYXgoMSwgTWF0aC5taW4oaXcgLSB4LCByLndpZHRoKSk7XG4gICAgICBjb25zdCBoZWlnaHQgPSBNYXRoLm1heCgxLCBNYXRoLm1pbihpaCAtIHksIHIuaGVpZ2h0KSk7XG4gICAgICByZXR1cm4geyB4LCB5LCB3aWR0aCwgaGVpZ2h0IH07XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gbnVsbDsgLyogdmlld3BvcnQgbm90IHJlYWR5ICovXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEltYWdlLXBpeGVsIHJlY3RhbmdsZSB0aGUgZHJhd2VyIGNhbnZhcyBjdXJyZW50bHkgY292ZXJzLiBVbmxpa2VcbiAgICoge0BsaW5rIHZpc2libGVJbWFnZVJlY3R9LCB0aGlzIGlzIE5PVCBjbGFtcGVkIHRvIHRoZSBpbWFnZSBib3VuZHM6IHRoZSBjYW52YXNcbiAgICogbWFwcyAxOjEgdG8gdGhlIHZpZXdwb3J0IHJlY3RhbmdsZSwgc28gbGVhdmluZyBpdCB1bmNsYW1wZWQga2VlcHNcbiAgICogYGNhbnZhc1B4IC0+IGltYWdlUHhgIGFuIGV4YWN0IGFmZmluZSBtYXAgKGNsYW1waW5nIHdvdWxkIHNrZXcgY29vcmRpbmF0ZXNcbiAgICogbmVhciB0aGUgaW1hZ2UgZWRnZXMpLiBSb3V0ZWQgdGhyb3VnaCB3b3JsZCBpdGVtIDAgKHNlZVxuICAgKiB7QGxpbmsgdmlld3BvcnRSZWN0VG9JbWFnZX0pIGZvciBtdWx0aS1sYXllciBhY2N1cmFjeS5cbiAgICovXG4gIGRpc3BsYXllZFNvdXJjZVJlY3QoKTogUGxvdE1vZGVSZWN0IHwgbnVsbCB7XG4gICAgY29uc3Qgdmlld2VyID0gdGhpcy5ob3N0LnZpZXdlcigpO1xuICAgIGNvbnN0IHZwID0gdmlld2VyPy52aWV3cG9ydDtcbiAgICBpZiAoIXZwIHx8ICF0aGlzLmhvc3QuZGVzY3JpcHRvcigpKSByZXR1cm4gbnVsbDtcbiAgICB0cnkge1xuICAgICAgY29uc3QgciA9IHZpZXdwb3J0UmVjdFRvSW1hZ2Uodmlld2VyLCB2cC5nZXRCb3VuZHModHJ1ZSkpO1xuICAgICAgcmV0dXJuIHsgeDogci54LCB5OiByLnksIHdpZHRoOiByLndpZHRoLCBoZWlnaHQ6IHIuaGVpZ2h0IH07XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKiogQ29hbGVzY2UgcmVkcmF3cyBpbnRvIG9uZSB7QGxpbmsgZnJhbWUkfSBlbWlzc2lvbiBwZXIgYW5pbWF0aW9uIGZyYW1lLlxuICAgKiAgU2tpcHBlZCBlbnRpcmVseSB3aGlsZSBub3RoaW5nIGxpc3RlbnMuICovXG4gIHNjaGVkdWxlRnJhbWUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZnJhbWVSYWYgIT09IG51bGwgfHwgIXRoaXMuZnJhbWUkLm9ic2VydmVkKSByZXR1cm47XG4gICAgdGhpcy5mcmFtZVJhZiA9IHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICB0aGlzLmZyYW1lUmFmID0gbnVsbDtcbiAgICAgIGNvbnN0IHJlY3QgPSB0aGlzLnZpc2libGVJbWFnZVJlY3QoKTtcbiAgICAgIGlmIChyZWN0KSB0aGlzLmZyYW1lJC5uZXh0KHJlY3QpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqIERyb3AgYSBwZW5kaW5nIHtAbGluayBzY2hlZHVsZUZyYW1lfSAodGhlIHZpZXdlciBpcyBnb2luZyBhd2F5KS4gKi9cbiAgY2FuY2VsRnJhbWUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZnJhbWVSYWYgIT09IG51bGwpIHtcbiAgICAgIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMuZnJhbWVSYWYpO1xuICAgICAgdGhpcy5mcmFtZVJhZiA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoZSB2aWV3cG9ydCBhIGNvbnRyaWJ1dGVkIHBsb3QgbW9kZSBkcmF3cyBvdmVyLiBPbmUgc3RhYmxlIG9iamVjdCBwZXJcbiAgICogc2VydmljZTogZXZlcnkgbWV0aG9kIHJlYWRzIHRoZSBDVVJSRU5UIHZpZXdlciwgc28gaXQgc3RheXMgdmFsaWQgYWNyb3NzIGFcbiAgICogdmlld2VyIHJlYnVpbGQgYW5kIHJlcG9ydHMgYGlzUmVhZHkoKSA9PT0gZmFsc2VgIHdoaWxlIG5vbmUgaXMgbW91bnRlZFxuICAgKiAoY29udmVyc2lvbnMgdGhlbiByZXR1cm4gTmFOIHJhdGhlciB0aGFuIHRocm93aW5nKS5cbiAgICovXG4gIHBsb3RNb2RlVmlld3BvcnRGb3IoKTogUGxvdE1vZGVWaWV3cG9ydCB7XG4gICAgaWYgKHRoaXMucGxvdE1vZGVWaWV3cG9ydCkgcmV0dXJuIHRoaXMucGxvdE1vZGVWaWV3cG9ydDtcbiAgICBjb25zdCBuYW4gPSB7IHg6IE5hTiwgeTogTmFOIH07XG4gICAgY29uc3QgY3QgPSAoKSA9PiB0aGlzLmhvc3QuY29vcmRUcmFuc2Zvcm0oKTtcbiAgICBjb25zdCByZWFkeSA9ICgpID0+ICEhY3QoKT8uaXNSZWFkeSgpO1xuICAgIHRoaXMucGxvdE1vZGVWaWV3cG9ydCA9IHtcbiAgICAgIGdldE92ZXJsYXlDb250YWluZXI6ICgpID0+IHRoaXMuaG9zdC5vdmVybGF5Q29udGFpbmVyKCksXG4gICAgICBkYXRhVG9DbGllbnQ6ICh4LCB5KSA9PiAocmVhZHkoKSA/IGN0KCkhLmRhdGFUb0NsaWVudCh4LCB5KSA6IG5hbiksXG4gICAgICBjbGllbnRUb0RhdGE6IChjeCwgY3kpID0+IChyZWFkeSgpID8gY3QoKSEuY2xpZW50VG9EYXRhKGN4LCBjeSkgOiBuYW4pLFxuICAgICAgZGF0YUxlbmd0aFRvU2NyZWVuOiAobGVuKSA9PiAocmVhZHkoKSA/IGN0KCkhLmRhdGFMZW5ndGhUb1NjcmVlbihsZW4pIDogTmFOKSxcbiAgICAgIGlzUmVhZHk6IHJlYWR5LFxuICAgICAgLy8gQm90aCBzdGFydCB3aXRoIHRoZSBjdXJyZW50IHZpc2libGUgcmVjdCB3aGVuIHRoZSB2aWV3cG9ydCBpcyByZWFkeTogYSBtb2RlXG4gICAgICAvLyBhY3RpdmF0ZXMgYWZ0ZXIgdGhlIGJhc2UgcmVuZGVyIGhhcyBnb25lIGlkbGUsIHNvIHdpdGhvdXQgaXQgYW4gb3ZlcmxheVxuICAgICAgLy8gZm9sbG93aW5nIGBmcmFtZSQuc3Vic2NyaWJlKHJlZHJhdylgIHdvdWxkIHN0YXkgYmxhbmsgdW50aWwgdGhlIG5leHQgcGFuL3pvb20uXG4gICAgICBmcmFtZSQ6IHRoaXMud2l0aEN1cnJlbnRSZWN0KHRoaXMuZnJhbWUkLCByZWFkeSksXG4gICAgICBzZXR0bGVkJDogdGhpcy53aXRoQ3VycmVudFJlY3QodGhpcy52aWV3cG9ydENoYW5nZSQsIHJlYWR5KSxcbiAgICAgIGZpdEJvdW5kczogKHJlY3QsIG9wdGlvbnMpID0+IHtcbiAgICAgICAgY29uc3Qgdmlld2VyID0gdGhpcy5ob3N0LnZpZXdlcigpO1xuICAgICAgICBpZiAoIXZpZXdlciB8fCAhcmVhZHkoKSB8fCAhKHJlY3Qud2lkdGggPiAwKSB8fCAhKHJlY3QuaGVpZ2h0ID4gMCkpIHJldHVybjtcbiAgICAgICAgY29uc3QgdnBSZWN0ID0gaW1hZ2VSZWN0VG9WaWV3cG9ydCh2aWV3ZXIsIHJlY3QueCwgcmVjdC55LCByZWN0LndpZHRoLCByZWN0LmhlaWdodCk7XG4gICAgICAgIHZpZXdlci52aWV3cG9ydC5maXRCb3VuZHNXaXRoQ29uc3RyYWludHModnBSZWN0LCAhIW9wdGlvbnM/LmltbWVkaWF0ZWx5KTtcbiAgICAgIH0sXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5wbG90TW9kZVZpZXdwb3J0O1xuICB9XG5cbiAgLyoqIGBzb3VyY2VgLCBwcmVjZWRlZCBieSB0aGUgY3VycmVudCB2aXNpYmxlIHJlY3QgZm9yIGVhY2ggc3Vic2NyaWJlciAod2hlbiByZWFkeSkuICovXG4gIHByaXZhdGUgd2l0aEN1cnJlbnRSZWN0KHNvdXJjZTogU3ViamVjdDxQbG90TW9kZVJlY3Q+LCByZWFkeTogKCkgPT4gYm9vbGVhbik6IE9ic2VydmFibGU8UGxvdE1vZGVSZWN0PiB7XG4gICAgcmV0dXJuIGRlZmVyKCgpID0+IHtcbiAgICAgIGNvbnN0IHJlY3QgPSByZWFkeSgpID8gdGhpcy52aXNpYmxlSW1hZ2VSZWN0KCkgOiBudWxsO1xuICAgICAgcmV0dXJuIHJlY3QgPyBzb3VyY2UucGlwZShzdGFydFdpdGgocmVjdCkpIDogc291cmNlLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEtlZXAgdGhlIHVzZXIncyBjdXJyZW50IHZpZXcgYWNyb3NzIGEgY29udGFpbmVyL3NwbGl0IHJlc2l6ZSBpbnN0ZWFkIG9mXG4gICAqIHNuYXBwaW5nIGhvbWUuIFZpZXdwb3J0IGJvdW5kcyBhcmUgaW1hZ2UtcmVsYXRpdmUgKGltYWdlIHdpZHRoID0gMSksIHNvXG4gICAqIHRoZXkncmUgaW5kZXBlbmRlbnQgb2YgdGhlIGNvbnRhaW5lcidzIHBpeGVsIHNpemUg4oCUIGNhcHR1cmUgdGhlIHZpc2libGVcbiAgICogcmVnaW9uIG5vdyBhbmQgcmUtZml0IGl0IG9uY2UgdGhlIG5ldyBzaXplIGhhcyBzZXR0bGVkLiBPU0QncyBhdXRvUmVzaXplXG4gICAqIGZpcmVzIGFzeW5jaHJvbm91c2x5IGFuZCB0aGUgYW5ndWxhci1zcGxpdCB0cmFuc2l0aW9uIGFuaW1hdGVzIHRoZSB3aWR0aFxuICAgKiBvdmVyIGEgZmV3IGh1bmRyZWQgbXMsIHNvIHJlc3RvcmUgb24gdGhlIG5leHQgZnJhbWUgYW5kIGFnYWluIGFmdGVyIHRoZVxuICAgKiB0cmFuc2l0aW9uIGNvbXBsZXRlcy5cbiAgICovXG4gIGtlZXBWaWV3QWNyb3NzUmVzaXplKCk6IHZvaWQge1xuICAgIGNvbnN0IHZwID0gdGhpcy5ob3N0LnZpZXdlcigpPy52aWV3cG9ydDtcbiAgICBpZiAoIXZwKSByZXR1cm47XG4gICAgY29uc3QgYm91bmRzID0gdnAuZ2V0Qm91bmRzKHRydWUpO1xuICAgIGNvbnN0IHJlc3RvcmUgPSAoKSA9PlxuICAgICAgcXVpZXQoKCkgPT4ge1xuICAgICAgICB0aGlzLmhvc3Qudmlld2VyKCk/LnZpZXdwb3J0LmZpdEJvdW5kcyhib3VuZHMsIHRydWUpO1xuICAgICAgICB0aGlzLmhvc3Qudmlld2VyKCk/LnZpZXdwb3J0LmFwcGx5Q29uc3RyYWludHModHJ1ZSk7XG4gICAgICB9KTtcbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocmVzdG9yZSk7XG4gICAgc2V0VGltZW91dChyZXN0b3JlLCAzNTApO1xuICB9XG5cbiAgZ29Ib21lKCk6IHZvaWQge1xuICAgIHRoaXMuaG9zdC52aWV3ZXIoKT8udmlld3BvcnQuZ29Ib21lKCk7XG4gIH1cblxuICAvKiogWm9vbSBieSBvbmUgYnV0dG9uIHN0ZXAgYWJvdXQgdGhlIGNlbnRyZSAoYGZhY3RvcmAgPiAxIHpvb21zIGluKS4gKi9cbiAgem9vbUJ5KGRpcmVjdGlvbjogMSB8IC0xKTogdm9pZCB7XG4gICAgY29uc3QgdnAgPSB0aGlzLmhvc3Qudmlld2VyKCk/LnZpZXdwb3J0O1xuICAgIHZwPy56b29tQnkoZGlyZWN0aW9uID4gMCA/IFpPT01fQlVUVE9OX1NURVAgOiAxIC8gWk9PTV9CVVRUT05fU1RFUCk7XG4gICAgdnA/LmFwcGx5Q29uc3RyYWludHMoKTtcbiAgfVxuXG4gIC8qKiBGaXQgdGhlIE9TRCB2aWV3cG9ydCB0byBhbiBpbWFnZS1zcGFjZSByZWN0YW5nbGUgKGNvb3JkcyBvcmRlcmVkXG4gICAqICBbeE1pbiwgeE1heCwgeU1heCwgeU1pbl0pLiAqL1xuICBhcHBseVpvb21Ub0JveChjb29yZGluYXRlczogbnVtYmVyW10pOiB2b2lkIHtcbiAgICBjb25zdCB2aWV3ZXIgPSB0aGlzLmhvc3Qudmlld2VyKCk7XG4gICAgaWYgKCF2aWV3ZXIgfHwgY29vcmRpbmF0ZXMubGVuZ3RoIDwgNCkgcmV0dXJuO1xuICAgIGNvbnN0IFthLCBiLCBjLCBkXSA9IGNvb3JkaW5hdGVzO1xuICAgIGNvbnN0IHggPSBNYXRoLm1pbihhLCBiKTtcbiAgICBjb25zdCB3ID0gTWF0aC5hYnMoYiAtIGEpO1xuICAgIGNvbnN0IHkgPSBNYXRoLm1pbihjLCBkKTtcbiAgICBjb25zdCBoID0gTWF0aC5hYnMoYyAtIGQpO1xuICAgIGlmICh3IDw9IDAgfHwgaCA8PSAwKSByZXR1cm47XG4gICAgY29uc3QgcmVjdCA9IGltYWdlUmVjdFRvVmlld3BvcnQodmlld2VyLCB4LCB5LCB3LCBoKTtcbiAgICB2aWV3ZXIudmlld3BvcnQuZml0Qm91bmRzKHJlY3QsIGZhbHNlKTtcbiAgfVxufVxuIl19
@@ -17,4 +17,10 @@
17
17
  * zoom visibly changing pace when a tool is picked up is the bug this constant prevents.
18
18
  */
19
19
  export const OSD_ZOOM_PER_SCROLL = 1.03;
20
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3NkLXpvb20uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ltcGxlbWVudGF0aW9ucy9vc2Qvb3NkLXpvb20udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBXaGVlbC16b29tIHN0ZXAgZm9yIHRoZSBPcGVuU2VhZHJhZ29uIGJhY2tlbmQuXG4gKlxuICogQXBwbGllZCBwZXIgc2Nyb2xsIEVWRU5ULCBub3QgcGVyIHVuaXQgb2YgZGVsdGEg4oCUIHdoaWNoIGlzIHdoYXQgT3BlblNlYWRyYWdvbidzIG93blxuICogYHpvb21QZXJTY3JvbGxgIGRvZXMsIGFuZCB3aGF0IHRoZSByZWdpb24gb3ZlcmxheSBkb2VzIHdoZW4gYW4gYWN0aXZlIHRvb2wgaGFzIHRha2VuIHRoZSB3aGVlbFxuICogb3Zlci4gVGhhdCBtYWtlcyB0aGUgc3RlcCBjb21wb3VuZCB3aXRoIHRoZSBudW1iZXIgb2YgZXZlbnRzIGEgZGV2aWNlIHNlbmRzOiBhIG1vdXNlIG5vdGNoIGlzXG4gKiBvbmUgZXZlbnQsIGJ1dCBhIHRyYWNrcGFkIHN3aXBlIGlzIGEgYnVyc3Qgb2YgdGhlbSwgc28gYSBzdGVwIHRoYXQgZmVlbHMgcmlnaHQgZm9yIGEgbW91c2UgcnVuc1xuICogYXdheSB1bmRlciBhIHRyYWNrcGFkLlxuICpcbiAqIEF0IHRoZSBwcmV2aW91cyAxLjEgKE9wZW5TZWFkcmFnb24ncyBkZWZhdWx0IGlzIDEuMikgYW4gaW1hZ2UgZG91YmxlZCBpbiA3IG5vdGNoZXMsIGFnYWluc3QgdGhlXG4gKiB+MjQgdGhlIG5hcGFyaS1qcyBiYWNrZW5kIHRvb2sgZm9yIHRoZSBzYW1lIHBpY3R1cmUg4oCUIHRoZSBzYW1lIGdlc3R1cmUgem9vbWVkIHNldmVyYWwgdGltZXNcbiAqIGZ1cnRoZXIgZGVwZW5kaW5nIG9ubHkgb24gd2hpY2ggcmVuZGVyZXIgd2FzIGFjdGl2ZS4gMS4wMyBwdXRzIHRoZSB0d28gd2l0aGluIGEgd2hpc2tlciBvZiBlYWNoXG4gKiBvdGhlciwgc28gdGhlIHdoZWVsIGZlZWxzIHRoZSBzYW1lIHdoaWNoZXZlciBiYWNrZW5kIGlzIGRyYXdpbmcuXG4gKlxuICogU2hhcmVkIGJlY2F1c2UgdGhlIHZpZXdlciBvcHRpb24gYW5kIHRoZSBvdmVybGF5J3MgaGFuZGxlciBNVVNUIGFncmVlOiB3aGV0aGVyIHRoZSB3aGVlbCBpc1xuICogaGFuZGxlZCBieSBPcGVuU2VhZHJhZ29uIG9yIGJ5IHRoZSBvdmVybGF5IGRlcGVuZHMgb24gd2hldGhlciBhIHJlZ2lvbiB0b29sIGlzIGFjdGl2ZSwgYW5kIHRoZVxuICogem9vbSB2aXNpYmx5IGNoYW5naW5nIHBhY2Ugd2hlbiBhIHRvb2wgaXMgcGlja2VkIHVwIGlzIHRoZSBidWcgdGhpcyBjb25zdGFudCBwcmV2ZW50cy5cbiAqL1xuZXhwb3J0IGNvbnN0IE9TRF9aT09NX1BFUl9TQ1JPTEwgPSAxLjAzO1xuIl19
20
+ /**
21
+ * Zoom factor per zoom-button press / +/- key, shared by every backend (OpenSeadragon, napari-js
22
+ * and Plotly's axis-range zoom) so a button press zooms the same amount whichever renderer is
23
+ * drawing. Unlike {@link OSD_ZOOM_PER_SCROLL} it is one deliberate step per press, not per event.
24
+ */
25
+ export const ZOOM_BUTTON_STEP = 1.3;
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3NkLXpvb20uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ltcGxlbWVudGF0aW9ucy9vc2Qvb3NkLXpvb20udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDO0FBRXhDOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxHQUFHLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFdoZWVsLXpvb20gc3RlcCBmb3IgdGhlIE9wZW5TZWFkcmFnb24gYmFja2VuZC5cbiAqXG4gKiBBcHBsaWVkIHBlciBzY3JvbGwgRVZFTlQsIG5vdCBwZXIgdW5pdCBvZiBkZWx0YSDigJQgd2hpY2ggaXMgd2hhdCBPcGVuU2VhZHJhZ29uJ3Mgb3duXG4gKiBgem9vbVBlclNjcm9sbGAgZG9lcywgYW5kIHdoYXQgdGhlIHJlZ2lvbiBvdmVybGF5IGRvZXMgd2hlbiBhbiBhY3RpdmUgdG9vbCBoYXMgdGFrZW4gdGhlIHdoZWVsXG4gKiBvdmVyLiBUaGF0IG1ha2VzIHRoZSBzdGVwIGNvbXBvdW5kIHdpdGggdGhlIG51bWJlciBvZiBldmVudHMgYSBkZXZpY2Ugc2VuZHM6IGEgbW91c2Ugbm90Y2ggaXNcbiAqIG9uZSBldmVudCwgYnV0IGEgdHJhY2twYWQgc3dpcGUgaXMgYSBidXJzdCBvZiB0aGVtLCBzbyBhIHN0ZXAgdGhhdCBmZWVscyByaWdodCBmb3IgYSBtb3VzZSBydW5zXG4gKiBhd2F5IHVuZGVyIGEgdHJhY2twYWQuXG4gKlxuICogQXQgdGhlIHByZXZpb3VzIDEuMSAoT3BlblNlYWRyYWdvbidzIGRlZmF1bHQgaXMgMS4yKSBhbiBpbWFnZSBkb3VibGVkIGluIDcgbm90Y2hlcywgYWdhaW5zdCB0aGVcbiAqIH4yNCB0aGUgbmFwYXJpLWpzIGJhY2tlbmQgdG9vayBmb3IgdGhlIHNhbWUgcGljdHVyZSDigJQgdGhlIHNhbWUgZ2VzdHVyZSB6b29tZWQgc2V2ZXJhbCB0aW1lc1xuICogZnVydGhlciBkZXBlbmRpbmcgb25seSBvbiB3aGljaCByZW5kZXJlciB3YXMgYWN0aXZlLiAxLjAzIHB1dHMgdGhlIHR3byB3aXRoaW4gYSB3aGlza2VyIG9mIGVhY2hcbiAqIG90aGVyLCBzbyB0aGUgd2hlZWwgZmVlbHMgdGhlIHNhbWUgd2hpY2hldmVyIGJhY2tlbmQgaXMgZHJhd2luZy5cbiAqXG4gKiBTaGFyZWQgYmVjYXVzZSB0aGUgdmlld2VyIG9wdGlvbiBhbmQgdGhlIG92ZXJsYXkncyBoYW5kbGVyIE1VU1QgYWdyZWU6IHdoZXRoZXIgdGhlIHdoZWVsIGlzXG4gKiBoYW5kbGVkIGJ5IE9wZW5TZWFkcmFnb24gb3IgYnkgdGhlIG92ZXJsYXkgZGVwZW5kcyBvbiB3aGV0aGVyIGEgcmVnaW9uIHRvb2wgaXMgYWN0aXZlLCBhbmQgdGhlXG4gKiB6b29tIHZpc2libHkgY2hhbmdpbmcgcGFjZSB3aGVuIGEgdG9vbCBpcyBwaWNrZWQgdXAgaXMgdGhlIGJ1ZyB0aGlzIGNvbnN0YW50IHByZXZlbnRzLlxuICovXG5leHBvcnQgY29uc3QgT1NEX1pPT01fUEVSX1NDUk9MTCA9IDEuMDM7XG5cbi8qKlxuICogWm9vbSBmYWN0b3IgcGVyIHpvb20tYnV0dG9uIHByZXNzIC8gKy8tIGtleSwgc2hhcmVkIGJ5IGV2ZXJ5IGJhY2tlbmQgKE9wZW5TZWFkcmFnb24sIG5hcGFyaS1qc1xuICogYW5kIFBsb3RseSdzIGF4aXMtcmFuZ2Ugem9vbSkgc28gYSBidXR0b24gcHJlc3Mgem9vbXMgdGhlIHNhbWUgYW1vdW50IHdoaWNoZXZlciByZW5kZXJlciBpc1xuICogZHJhd2luZy4gVW5saWtlIHtAbGluayBPU0RfWk9PTV9QRVJfU0NST0xMfSBpdCBpcyBvbmUgZGVsaWJlcmF0ZSBzdGVwIHBlciBwcmVzcywgbm90IHBlciBldmVudC5cbiAqL1xuZXhwb3J0IGNvbnN0IFpPT01fQlVUVE9OX1NURVAgPSAxLjM7XG4iXX0=