@jax-data-science/sci-image-visualizer 0.8.3 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (579) hide show
  1. package/README.md +201 -460
  2. package/esm2022/index.mjs +34 -15
  3. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
  4. package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
  5. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
  7. package/esm2022/lib/contracts/color.mjs +60 -0
  8. package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
  9. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
  10. package/esm2022/lib/contracts/display-types.mjs +11 -1
  11. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  12. package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
  13. package/esm2022/lib/contracts/intensity.mjs +48 -5
  14. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  15. package/esm2022/lib/contracts/plot-type.mjs +134 -17
  16. package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
  17. package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
  18. package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
  19. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
  20. package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
  21. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  22. package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
  23. package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
  24. package/esm2022/lib/contracts/sam.contract.mjs +1 -1
  25. package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
  26. package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
  27. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  28. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
  29. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  30. package/esm2022/lib/contracts/viz-config.mjs +2 -1
  31. package/esm2022/lib/geometry/contour.mjs +63 -0
  32. package/esm2022/lib/geometry/loft.mjs +128 -0
  33. package/esm2022/lib/geometry/polylabel.mjs +156 -0
  34. package/esm2022/lib/geometry/raster.mjs +98 -0
  35. package/esm2022/lib/geometry/reconstruct.mjs +315 -0
  36. package/esm2022/lib/geometry/reslice-image.mjs +57 -0
  37. package/esm2022/lib/geometry/ring.mjs +201 -0
  38. package/esm2022/lib/geometry/section.mjs +215 -0
  39. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
  40. package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
  41. package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
  42. package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
  43. package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
  44. package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
  45. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +12 -9
  46. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +83 -0
  47. package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
  48. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +180 -591
  49. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
  50. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
  51. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
  52. package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
  53. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +270 -0
  54. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
  55. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
  56. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
  57. package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
  58. package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
  59. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +347 -0
  60. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +427 -4207
  61. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
  62. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +550 -0
  63. package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
  64. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
  65. package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
  66. package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
  67. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +194 -0
  68. package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
  69. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
  70. package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
  71. package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
  72. package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
  73. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
  74. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
  75. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
  76. package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
  77. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
  78. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
  79. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
  80. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
  81. package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
  82. package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
  83. package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
  84. package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
  85. package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
  86. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +164 -0
  87. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +213 -716
  88. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
  89. package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
  90. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
  91. package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
  92. package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
  93. package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
  94. package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
  95. package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
  96. package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
  97. package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
  98. package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
  99. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
  100. package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
  101. package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
  102. package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
  103. package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
  104. package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
  105. package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
  106. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
  107. package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
  108. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
  109. package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
  110. package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
  111. package/esm2022/lib/implementations/region-centroids.mjs +47 -0
  112. package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
  113. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
  114. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
  115. package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
  116. package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
  117. package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
  118. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
  119. package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
  120. package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
  121. package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
  122. package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
  123. package/esm2022/lib/models/bezier.mjs +1 -11
  124. package/esm2022/lib/models/class-preset.mjs +41 -3
  125. package/esm2022/lib/models/geometry.mjs +27 -164
  126. package/esm2022/lib/models/polygon-edit.mjs +254 -0
  127. package/esm2022/lib/models/polygon-factory.mjs +134 -0
  128. package/esm2022/lib/models/region-clone.mjs +68 -0
  129. package/esm2022/lib/models/region-geojson.mjs +411 -0
  130. package/esm2022/lib/models/region.mjs +34 -33
  131. package/esm2022/lib/models/shape.mjs +18 -16
  132. package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
  133. package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
  134. package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
  135. package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
  136. package/esm2022/lib/plot.utilities.mjs +296 -473
  137. package/esm2022/lib/processing/image-crop.mjs +1 -1
  138. package/esm2022/lib/processing/processing-image.mjs +28 -15
  139. package/esm2022/lib/provide-visualization.mjs +40 -14
  140. package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
  141. package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
  142. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +163 -0
  143. package/esm2022/lib/region-editor/file-stem.mjs +13 -0
  144. package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
  145. package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
  146. package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
  147. package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
  148. package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
  149. package/esm2022/lib/region-editor/region-editor.component.mjs +896 -660
  150. package/esm2022/lib/region-editor/region-metrics.mjs +86 -0
  151. package/esm2022/lib/region-editor/region-persistence.service.mjs +160 -0
  152. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +169 -0
  153. package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
  154. package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
  155. package/esm2022/lib/region-ops.service.mjs +28 -70
  156. package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
  157. package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
  158. package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
  159. package/esm2022/lib/region-overlay/region-style.mjs +97 -0
  160. package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
  161. package/esm2022/lib/region-source/http-region-source.mjs +104 -0
  162. package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
  163. package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
  164. package/esm2022/lib/region-source/region-source.mjs +67 -0
  165. package/esm2022/lib/region-source/region-tiles.mjs +708 -0
  166. package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
  167. package/esm2022/lib/render-orchestrator.mjs +14 -11
  168. package/esm2022/lib/render-session.mjs +207 -0
  169. package/esm2022/lib/routing-visualizer.service.mjs +858 -414
  170. package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
  171. package/esm2022/lib/spatial/density-raster.mjs +14 -0
  172. package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
  173. package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
  174. package/esm2022/lib/spatial/gene-search.mjs +1 -1
  175. package/esm2022/lib/spatial/glyphs.mjs +97 -0
  176. package/esm2022/lib/spatial/lod.mjs +187 -0
  177. package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
  178. package/esm2022/lib/spatial/spatial-density.mjs +25 -16
  179. package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
  180. package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
  181. package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
  182. package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
  183. package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
  184. package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
  185. package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
  186. package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
  187. package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
  188. package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
  189. package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
  190. package/esm2022/lib/spatial/stats.mjs +71 -0
  191. package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
  192. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
  193. package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
  194. package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
  195. package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
  196. package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
  197. package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
  198. package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
  199. package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
  200. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
  201. package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
  202. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
  203. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
  204. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
  205. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
  206. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
  207. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
  208. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
  209. package/esm2022/lib/store/class-color.util.mjs +53 -5
  210. package/esm2022/lib/store/class-signatures.mjs +63 -0
  211. package/esm2022/lib/store/region-history.mjs +146 -0
  212. package/esm2022/lib/store/region-scope-cache.mjs +144 -0
  213. package/esm2022/lib/store/region-selection.mjs +82 -0
  214. package/esm2022/lib/store/region-source-scope.mjs +171 -0
  215. package/esm2022/lib/store/region-store.service.mjs +986 -670
  216. package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
  217. package/esm2022/lib/store/visualizer-store.service.mjs +81 -76
  218. package/esm2022/lib/toast-outlets.mjs +5 -4
  219. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
  220. package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
  221. package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
  222. package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
  223. package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
  224. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +120 -0
  225. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
  226. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
  227. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
  228. package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
  229. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
  230. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
  231. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
  232. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
  233. package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
  234. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
  235. package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
  236. package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
  237. package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
  238. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +121 -0
  239. package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
  240. package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
  241. package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
  242. package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
  243. package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
  244. package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
  245. package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
  246. package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
  247. package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
  248. package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
  249. package/esm2022/lib/toolbar/toolbar.component.mjs +84 -119
  250. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
  251. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
  252. package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
  253. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
  254. package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
  255. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
  256. package/esm2022/lib/util/mark-for-check.mjs +17 -0
  257. package/esm2022/lib/util/supersede.mjs +56 -0
  258. package/esm2022/lib/visualization.module.mjs +39 -141
  259. package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
  260. package/esm2022/lib/visualizer/region-actions.mjs +149 -0
  261. package/esm2022/lib/visualizer/region-load.mjs +123 -0
  262. package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
  263. package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
  264. package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
  265. package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
  266. package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
  267. package/esm2022/lib/visualizer.component.mjs +602 -1902
  268. package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
  269. package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
  270. package/esm2022/lib/workers/spatial-math.mjs +190 -0
  271. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs +47169 -0
  272. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
  273. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs +238 -0
  274. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map +1 -0
  275. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
  276. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
  277. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
  278. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
  279. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34467
  280. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  281. package/fesm2022/mask.worker.js +36 -917
  282. package/fesm2022/onnx-sam.worker.js +52 -16
  283. package/fesm2022/region-source.worker.js +1067 -0
  284. package/fesm2022/spatial-math.worker.js +471 -0
  285. package/fesm2022/tsne.worker.js +32 -15
  286. package/index.d.ts +19 -10
  287. package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
  288. package/lib/contracts/capabilities.contract.d.ts +4 -2
  289. package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
  290. package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
  291. package/lib/contracts/color.d.ts +27 -0
  292. package/lib/contracts/colormap-lut.d.ts +19 -4
  293. package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
  294. package/lib/contracts/display-types.d.ts +21 -0
  295. package/lib/contracts/image.contract.d.ts +4 -0
  296. package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
  297. package/lib/contracts/intensity.d.ts +13 -2
  298. package/lib/contracts/plot-type.d.ts +3 -1
  299. package/lib/contracts/ports/image-state.port.d.ts +6 -2
  300. package/lib/contracts/ports/preferences.port.d.ts +4 -0
  301. package/lib/contracts/ports/region-io.port.d.ts +1 -0
  302. package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
  303. package/lib/contracts/ports/tile-access.port.d.ts +1 -0
  304. package/lib/contracts/region-editor-api.contract.d.ts +85 -1
  305. package/lib/contracts/region-overlay.contract.d.ts +5 -0
  306. package/lib/contracts/region-store.contract.d.ts +22 -0
  307. package/lib/contracts/sam.contract.d.ts +7 -0
  308. package/lib/contracts/section-view.contract.d.ts +44 -0
  309. package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
  310. package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
  311. package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
  312. package/lib/contracts/visualizer.contract.d.ts +231 -54
  313. package/lib/contracts/viz-config.d.ts +9 -0
  314. package/lib/geometry/contour.d.ts +24 -0
  315. package/lib/geometry/loft.d.ts +22 -0
  316. package/lib/geometry/polylabel.d.ts +23 -0
  317. package/lib/geometry/raster.d.ts +42 -0
  318. package/lib/geometry/reconstruct.d.ts +54 -0
  319. package/lib/geometry/reslice-image.d.ts +33 -0
  320. package/lib/geometry/ring.d.ts +67 -0
  321. package/lib/geometry/section.d.ts +52 -0
  322. package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
  323. package/lib/implementations/base-store-visualizer.d.ts +61 -15
  324. package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
  325. package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
  326. package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
  327. package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
  328. package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -3
  329. package/lib/implementations/napari-js/napari-loading-state.d.ts +37 -0
  330. package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
  331. package/lib/implementations/napari-js/napari-region-overlay.d.ts +68 -71
  332. package/lib/implementations/napari-js/napari-scene.d.ts +126 -0
  333. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
  334. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
  335. package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
  336. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +91 -0
  337. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
  338. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
  339. package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
  340. package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
  341. package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
  342. package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
  343. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +169 -883
  344. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
  345. package/lib/implementations/napari-js/napari-volume-scene.d.ts +148 -0
  346. package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
  347. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
  348. package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
  349. package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
  350. package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
  351. package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
  352. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
  353. package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
  354. package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
  355. package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
  356. package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
  357. package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
  358. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
  359. package/lib/implementations/osd/display-pipeline.d.ts +38 -9
  360. package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
  361. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
  362. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
  363. package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
  364. package/lib/implementations/osd/osd-coords.d.ts +6 -4
  365. package/lib/implementations/osd/osd-export.d.ts +36 -0
  366. package/lib/implementations/osd/osd-lib.d.ts +7 -0
  367. package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
  368. package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
  369. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +38 -0
  370. package/lib/implementations/osd/osd-region-overlay.d.ts +46 -51
  371. package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
  372. package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
  373. package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
  374. package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
  375. package/lib/implementations/osd/osd-viewport.d.ts +77 -0
  376. package/lib/implementations/osd/osd-zoom.d.ts +6 -0
  377. package/lib/implementations/osd/simple-source.d.ts +161 -0
  378. package/lib/implementations/osd/slice-cache.d.ts +12 -3
  379. package/lib/implementations/osd/tile-client.d.ts +11 -14
  380. package/lib/implementations/osd/tile-recolor.d.ts +141 -0
  381. package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
  382. package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
  383. package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
  384. package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
  385. package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
  386. package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
  387. package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
  388. package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
  389. package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
  390. package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
  391. package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
  392. package/lib/implementations/plotly/plotly.service.d.ts +136 -401
  393. package/lib/implementations/region-centroids.d.ts +14 -0
  394. package/lib/implementations/simple-slice-access.service.d.ts +7 -4
  395. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
  396. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
  397. package/lib/implementations/tile-server/index.d.ts +5 -0
  398. package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
  399. package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
  400. package/lib/implementations/tile-server/tile-protocol.d.ts +83 -0
  401. package/lib/implementations/tile-server/transport.d.ts +62 -0
  402. package/lib/intensity/intensity-profile.d.ts +66 -0
  403. package/lib/intensity/intensity-profile.service.d.ts +108 -0
  404. package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
  405. package/lib/models/bezier.d.ts +0 -5
  406. package/lib/models/class-preset.d.ts +25 -0
  407. package/lib/models/geometry.d.ts +14 -48
  408. package/lib/models/polygon-edit.d.ts +72 -0
  409. package/lib/models/polygon-factory.d.ts +45 -0
  410. package/lib/models/region-clone.d.ts +20 -0
  411. package/lib/models/region-geojson.d.ts +57 -0
  412. package/lib/models/region.d.ts +59 -4
  413. package/lib/models/shape.d.ts +8 -0
  414. package/lib/plot-mode/contribution-host.d.ts +125 -0
  415. package/lib/plot-mode/plot-type-menu.d.ts +60 -0
  416. package/lib/plot-mode/tool-params-model.d.ts +49 -0
  417. package/lib/plot.utilities.d.ts +19 -30
  418. package/lib/processing/processing-image.d.ts +5 -2
  419. package/lib/provide-visualization.d.ts +19 -2
  420. package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
  421. package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
  422. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +86 -0
  423. package/lib/region-editor/file-stem.d.ts +7 -0
  424. package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
  425. package/lib/region-editor/mask-export.service.d.ts +54 -0
  426. package/lib/region-editor/mask-raster.d.ts +2 -8
  427. package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
  428. package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
  429. package/lib/region-editor/region-editor.component.d.ts +283 -200
  430. package/lib/region-editor/region-metrics.d.ts +34 -0
  431. package/lib/region-editor/region-persistence.service.d.ts +77 -0
  432. package/lib/region-editor/region-table/region-table.component.d.ts +89 -0
  433. package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
  434. package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
  435. package/lib/region-ops.service.d.ts +1 -7
  436. package/lib/region-overlay/region-geometry.d.ts +158 -0
  437. package/lib/region-overlay/region-hit-test.d.ts +38 -0
  438. package/lib/region-overlay/region-source-layer.d.ts +96 -0
  439. package/lib/region-overlay/region-style.d.ts +52 -0
  440. package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
  441. package/lib/region-source/http-region-source.d.ts +45 -0
  442. package/lib/region-source/region-source-ops.d.ts +89 -0
  443. package/lib/region-source/region-source-worker.d.ts +7 -0
  444. package/lib/region-source/region-source.d.ts +82 -0
  445. package/lib/region-source/region-tiles.d.ts +289 -0
  446. package/lib/region-source/worker-region-source.d.ts +65 -0
  447. package/lib/render-orchestrator.d.ts +6 -2
  448. package/lib/render-session.d.ts +75 -0
  449. package/lib/routing-visualizer.service.d.ts +248 -59
  450. package/lib/section-pane/section-pane.component.d.ts +47 -0
  451. package/lib/spatial/density-raster.d.ts +6 -0
  452. package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
  453. package/lib/spatial/embedding-compute.d.ts +21 -2
  454. package/lib/spatial/glyphs.d.ts +16 -0
  455. package/lib/spatial/lod.d.ts +94 -0
  456. package/lib/spatial/spatial-controls.facade.d.ts +64 -0
  457. package/lib/spatial/spatial-density.d.ts +15 -5
  458. package/lib/spatial/spatial-encoding.d.ts +11 -44
  459. package/lib/spatial/spatial-expression.d.ts +40 -22
  460. package/lib/spatial/spatial-framing.d.ts +1 -0
  461. package/lib/spatial/spatial-heatmap.d.ts +2 -0
  462. package/lib/spatial/spatial-hover.d.ts +4 -16
  463. package/lib/spatial/spatial-panel-model.d.ts +135 -0
  464. package/lib/spatial/spatial-selection.d.ts +21 -26
  465. package/lib/spatial/spatial-tile-merge.d.ts +41 -0
  466. package/lib/spatial/spatial-tiles.d.ts +9 -256
  467. package/lib/spatial/stats.d.ts +38 -0
  468. package/lib/spatial/transcript-grouping.d.ts +119 -0
  469. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
  470. package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
  471. package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
  472. package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
  473. package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
  474. package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
  475. package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
  476. package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
  477. package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
  478. package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
  479. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
  480. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
  481. package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
  482. package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
  483. package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
  484. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
  485. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
  486. package/lib/store/class-color.util.d.ts +39 -2
  487. package/lib/store/class-signatures.d.ts +11 -0
  488. package/lib/store/region-history.d.ts +66 -0
  489. package/lib/store/region-scope-cache.d.ts +65 -0
  490. package/lib/store/region-selection.d.ts +36 -0
  491. package/lib/store/region-source-scope.d.ts +68 -0
  492. package/lib/store/region-store.service.d.ts +312 -116
  493. package/lib/store/visualizer-store.service.d.ts +32 -33
  494. package/lib/toast-outlets.d.ts +4 -3
  495. package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
  496. package/lib/toolbar/canvas-tools.d.ts +20 -0
  497. package/lib/toolbar/crop/slide-crop.d.ts +10 -4
  498. package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
  499. package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
  500. package/lib/toolbar/region-tools/region-tools.component.d.ts +62 -0
  501. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
  502. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
  503. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
  504. package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
  505. package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
  506. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
  507. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
  508. package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
  509. package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
  510. package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
  511. package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
  512. package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
  513. package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
  514. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +51 -0
  515. package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
  516. package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
  517. package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
  518. package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
  519. package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
  520. package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
  521. package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
  522. package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
  523. package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
  524. package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
  525. package/lib/toolbar/toolbar.component.d.ts +55 -84
  526. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
  527. package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
  528. package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
  529. package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
  530. package/lib/toolbar/wand/wand.service.d.ts +22 -116
  531. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
  532. package/lib/util/mark-for-check.d.ts +11 -0
  533. package/lib/util/supersede.d.ts +53 -0
  534. package/lib/visualization.module.d.ts +18 -39
  535. package/lib/visualizer/floating-drag.directive.d.ts +30 -0
  536. package/lib/visualizer/region-actions.d.ts +54 -0
  537. package/lib/visualizer/region-load.d.ts +46 -0
  538. package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
  539. package/lib/visualizer/tool-modes.d.ts +49 -0
  540. package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
  541. package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
  542. package/lib/visualizer/volume-sections.d.ts +64 -0
  543. package/lib/visualizer.component.d.ts +232 -447
  544. package/lib/workers/spatial-math-ops.d.ts +65 -0
  545. package/lib/workers/spatial-math-worker.d.ts +7 -0
  546. package/lib/workers/spatial-math.d.ts +74 -0
  547. package/package.json +12 -3
  548. package/src/lib/assets/slice.svg +23 -0
  549. package/src/lib/styles/_viz-icons-rules.scss +73 -0
  550. package/src/lib/styles/viz-icons.scss +14 -0
  551. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
  552. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
  553. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
  554. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
  555. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
  556. package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
  557. package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
  558. package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
  559. package/src/lib/assets/cell-detection.svg +0 -37
  560. package/src/lib/assets/click.svg +0 -1
  561. package/src/lib/assets/colormap-luts.json +0 -1
  562. package/src/lib/assets/edit-selection-white.svg +0 -47
  563. package/src/lib/assets/icons/colormap-earth.png +0 -0
  564. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  565. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  566. package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
  567. package/src/lib/assets/picture-segmentation.svg +0 -43
  568. package/src/lib/assets/test/download-379.svg +0 -1
  569. package/src/lib/assets/test/download-98.svg +0 -1
  570. package/src/lib/assets/test/json-1.svg +0 -1
  571. package/src/lib/assets/test/load-53.svg +0 -1
  572. package/src/lib/assets/test/mask-44.svg +0 -1
  573. package/src/lib/assets/test/mask-download-44.svg +0 -15
  574. package/src/lib/assets/test/mask-save-44.svg +0 -11
  575. package/src/lib/assets/test/overlay-1.svg +0 -1
  576. package/src/lib/assets/test/overlay-4.svg +0 -1
  577. package/src/lib/assets/test/region-26.svg +0 -1
  578. package/src/lib/assets/test/save-56.svg +0 -1
  579. package/src/lib/assets/test/upload-43.svg +0 -1
@@ -1,3 +1,4 @@
1
+ import { withRegionPatch } from '../models/region-clone';
1
2
  export function normalizeLabel(s) {
2
3
  return (s ?? '').trim().toLowerCase();
3
4
  }
@@ -10,14 +11,24 @@ export function hashString(s) {
10
11
  // Fold to non-negative without the Math.abs(INT_MIN) overflow pitfall.
11
12
  return h < 0 ? ~h : h;
12
13
  }
13
- function hslToHex(hDeg, sPct, lPct) {
14
+ /**
15
+ * The key two class names are compared by under the set's match mode: the name
16
+ * itself for `exact`, trimmed and lower-cased for `normalized`.
17
+ */
18
+ export function presetKey(set, label) {
19
+ return set?.matchMode === 'normalized' ? normalizeLabel(label) : label;
20
+ }
21
+ /** `#RRGGBB` (upper-case) for an HSL colour: hue in degrees, saturation and lightness in %. */
22
+ export function hslToHex(hDeg, sPct, lPct) {
14
23
  const s = sPct / 100;
15
24
  const l = lPct / 100;
16
25
  const k = (n) => (n + hDeg / 30) % 12;
17
26
  const a = s * Math.min(l, 1 - l);
18
27
  const channel = (n) => {
19
28
  const v = l - a * Math.max(-1, Math.min(k(n) - 3, 9 - k(n), 1));
20
- return Math.round(255 * v).toString(16).padStart(2, '0');
29
+ return Math.round(255 * v)
30
+ .toString(16)
31
+ .padStart(2, '0');
21
32
  };
22
33
  return `#${channel(0)}${channel(8)}${channel(4)}`.toUpperCase();
23
34
  }
@@ -44,9 +55,46 @@ export function fallbackColorFor(label, palette) {
44
55
  const hue = (hashString(key) * 137.508) % 360;
45
56
  return hslToHex(hue, 65, 50);
46
57
  }
47
- /** Resolve a colour for `label`: a matching preset's colour, else the deterministic fallback. */
58
+ /**
59
+ * Resolve a colour for `label`: a matching preset's colour, else the colour an imported file
60
+ * gave the class, else the deterministic fallback.
61
+ */
48
62
  export function colorForLabel(label, set) {
49
63
  const preset = findPreset(label, set);
50
- return preset ? preset.color : fallbackColorFor(label, set.fallbackPalette);
64
+ if (preset)
65
+ return preset.color;
66
+ return set.importedColors?.[presetKey(set, label)] ?? fallbackColorFor(label, set.fallbackPalette);
67
+ }
68
+ /**
69
+ * Resolve each labelled region's colour from the preset set (jit-ui#70). The
70
+ * presets are the source of truth: a matching preset gives the class colour,
71
+ * an unknown class the colour an imported file gave it (`importedColors`) or else
72
+ * its deterministic fallback, **overriding any colour already on the region**. Unlabelled regions and
73
+ * ones the user recoloured (`colorOverridden`) are left untouched. Unknown
74
+ * classes are reported through `onPromote` when `autoPromote` is on.
75
+ *
76
+ * Returns a new array; regions whose colour is already right are the same
77
+ * instances.
78
+ */
79
+ export function applyPresetColors(regions, set, opts = {}) {
80
+ const known = new Set(set.classes.map((c) => presetKey(set, c.name)));
81
+ return regions.map((region) => {
82
+ if (!region.label || region.colorOverridden)
83
+ return region;
84
+ const color = colorForLabel(region.label, set);
85
+ if (set.autoPromote && !known.has(presetKey(set, region.label))) {
86
+ known.add(presetKey(set, region.label));
87
+ // In normalized mode, trim the promoted name so leading/trailing
88
+ // whitespace doesn't create invisible duplicates or odd display names.
89
+ const name = set.matchMode === 'normalized' ? region.label.trim() : region.label;
90
+ opts.onPromote?.({ name, color, source: 'auto' });
91
+ }
92
+ if (region.color === color)
93
+ return region;
94
+ if (!opts.inPlace?.(region))
95
+ return withRegionPatch(region, { color });
96
+ region.color = color;
97
+ return region;
98
+ });
51
99
  }
52
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3MtY29sb3IudXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc3RvcmUvY2xhc3MtY29sb3IudXRpbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFjQSxNQUFNLFVBQVUsY0FBYyxDQUFDLENBQVM7SUFDdEMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztBQUN4QyxDQUFDO0FBRUQsb0ZBQW9GO0FBQ3BGLE1BQU0sVUFBVSxVQUFVLENBQUMsQ0FBUztJQUNsQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDVixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ2xDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUNELHVFQUF1RTtJQUN2RSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDeEIsQ0FBQztBQUVELFNBQVMsUUFBUSxDQUFDLElBQVksRUFBRSxJQUFZLEVBQUUsSUFBWTtJQUN4RCxNQUFNLENBQUMsR0FBRyxJQUFJLEdBQUcsR0FBRyxDQUFDO0lBQ3JCLE1BQU0sQ0FBQyxHQUFHLElBQUksR0FBRyxHQUFHLENBQUM7SUFDckIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDOUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNqQyxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQVMsRUFBRSxFQUFFO1FBQzVCLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hFLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDM0QsQ0FBQyxDQUFDO0lBQ0YsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7QUFDbEUsQ0FBQztBQUVELG1FQUFtRTtBQUNuRSxNQUFNLFVBQVUsVUFBVSxDQUFDLEtBQWEsRUFBRSxHQUFjO0lBQ3RELElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxHQUFHLEVBQUUsT0FBTztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQzlDLElBQUksR0FBRyxDQUFDLFNBQVMsS0FBSyxZQUFZLEVBQUUsQ0FBQztRQUNuQyxNQUFNLENBQUMsR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDaEMsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUMvRCxDQUFDO0lBQ0QsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxLQUFLLENBQUMsQ0FBQztBQUNuRCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxLQUFhLEVBQUUsT0FBaUI7SUFDL0QsTUFBTSxHQUFHLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2xDLElBQUksT0FBTyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDbEMsT0FBTyxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lBQ0QsTUFBTSxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsT0FBTyxDQUFDLEdBQUcsR0FBRyxDQUFDO0lBQzlDLE9BQU8sUUFBUSxDQUFDLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDL0IsQ0FBQztBQUVELGlHQUFpRztBQUNqRyxNQUFNLFVBQVUsYUFBYSxDQUFDLEtBQWEsRUFBRSxHQUFjO0lBQ3pELE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDdEMsT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUM7QUFDOUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRGV0ZXJtaW5pc3RpYyBjb2xvdXIgZW5naW5lIGZvciBwcmVzZXQgYW5ub3RhdGlvbiBjbGFzc2VzIChqaXQtdWkjNzApLlxuICpcbiAqIFJlc29sdXRpb24gb3JkZXIgZm9yIGEgcmVnaW9uIGBsYWJlbGA6XG4gKiAgIDEuIGEgbWF0Y2hpbmcgcHJlc2V0IChleGFjdCBieSBkZWZhdWx0LCBvciBub3JtYWxpemVkIGlmIHRoZSBzZXQncyBtYXRjaE1vZGUgc2F5cyBzbylcbiAqICAgICAgLT4gdGhlIHByZXNldCdzIGNvbG91cjtcbiAqICAgMi4gb3RoZXJ3aXNlIGEgZGV0ZXJtaW5pc3RpYyBmYWxsYmFjayBjb2xvdXIgZGVyaXZlZCBmcm9tIGEgc3RhYmxlIGhhc2ggb2YgdGhlIG5hbWUsXG4gKiAgICAgIHNvIHRoZSBzYW1lIHVua25vd24gY2xhc3MgYWx3YXlzIGdldHMgdGhlIHNhbWUgY29sb3VyIHdpdGggbm8gc3RvcmVkIHN0YXRlLlxuICpcbiAqIFRoZXNlIGZ1bmN0aW9ucyBhcmUgcHVyZSAobm8gbXV0YXRpb24pOyBvcHQtaW4gcHJvbW90aW9uIG9mIHVua25vd24gY2xhc3NlcyBpbnRvIHRoZVxuICogc2V0IGlzIGhhbmRsZWQgYnkgdGhlIHN0b3JlLCB3aGljaCBvd25zIHBlcnNpc3RlbmNlLlxuICovXG5pbXBvcnQgeyBDbGFzc1ByZXNldCwgUHJlc2V0U2V0IH0gZnJvbSAnLi4vbW9kZWxzL2NsYXNzLXByZXNldCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVMYWJlbChzOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gKHMgPz8gJycpLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xufVxuXG4vKiogU3RhYmxlLCBub24tbmVnYXRpdmUgMzItYml0IHN0cmluZyBoYXNoIChpZGVudGljYWwgYWNyb3NzIHJ1bnMgYW5kIG1hY2hpbmVzKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNoU3RyaW5nKHM6IHN0cmluZyk6IG51bWJlciB7XG4gIGxldCBoID0gMDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzLmxlbmd0aDsgaSsrKSB7XG4gICAgaCA9IChNYXRoLmltdWwoMzEsIGgpICsgcy5jaGFyQ29kZUF0KGkpKSB8IDA7XG4gIH1cbiAgLy8gRm9sZCB0byBub24tbmVnYXRpdmUgd2l0aG91dCB0aGUgTWF0aC5hYnMoSU5UX01JTikgb3ZlcmZsb3cgcGl0ZmFsbC5cbiAgcmV0dXJuIGggPCAwID8gfmggOiBoO1xufVxuXG5mdW5jdGlvbiBoc2xUb0hleChoRGVnOiBudW1iZXIsIHNQY3Q6IG51bWJlciwgbFBjdDogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgcyA9IHNQY3QgLyAxMDA7XG4gIGNvbnN0IGwgPSBsUGN0IC8gMTAwO1xuICBjb25zdCBrID0gKG46IG51bWJlcikgPT4gKG4gKyBoRGVnIC8gMzApICUgMTI7XG4gIGNvbnN0IGEgPSBzICogTWF0aC5taW4obCwgMSAtIGwpO1xuICBjb25zdCBjaGFubmVsID0gKG46IG51bWJlcikgPT4ge1xuICAgIGNvbnN0IHYgPSBsIC0gYSAqIE1hdGgubWF4KC0xLCBNYXRoLm1pbihrKG4pIC0gMywgOSAtIGsobiksIDEpKTtcbiAgICByZXR1cm4gTWF0aC5yb3VuZCgyNTUgKiB2KS50b1N0cmluZygxNikucGFkU3RhcnQoMiwgJzAnKTtcbiAgfTtcbiAgcmV0dXJuIGAjJHtjaGFubmVsKDApfSR7Y2hhbm5lbCg4KX0ke2NoYW5uZWwoNCl9YC50b1VwcGVyQ2FzZSgpO1xufVxuXG4vKiogRmluZCB0aGUgcHJlc2V0IG1hdGNoaW5nIGBsYWJlbGAgdW5kZXIgdGhlIHNldCdzIG1hdGNoIG1vZGUuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZFByZXNldChsYWJlbDogc3RyaW5nLCBzZXQ6IFByZXNldFNldCk6IENsYXNzUHJlc2V0IHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFsYWJlbCB8fCAhc2V0Py5jbGFzc2VzKSByZXR1cm4gdW5kZWZpbmVkO1xuICBpZiAoc2V0Lm1hdGNoTW9kZSA9PT0gJ25vcm1hbGl6ZWQnKSB7XG4gICAgY29uc3QgbiA9IG5vcm1hbGl6ZUxhYmVsKGxhYmVsKTtcbiAgICByZXR1cm4gc2V0LmNsYXNzZXMuZmluZCgoYykgPT4gbm9ybWFsaXplTGFiZWwoYy5uYW1lKSA9PT0gbik7XG4gIH1cbiAgcmV0dXJuIHNldC5jbGFzc2VzLmZpbmQoKGMpID0+IGMubmFtZSA9PT0gbGFiZWwpO1xufVxuXG4vKipcbiAqIERldGVybWluaXN0aWMgZmFsbGJhY2sgY29sb3VyIGZvciBhbiB1bmtub3duIGNsYXNzIG5hbWU6IGluZGV4IGludG8gdGhlIHBhbGV0dGUgYnkgYVxuICogc3RhYmxlIGhhc2ggb2YgdGhlIChub3JtYWxpemVkKSBuYW1lOyBpZiB0aGUgcGFsZXR0ZSBpcyBlbXB0eSwgZ2VuZXJhdGUgYSBnb2xkZW4tYW5nbGVcbiAqIEhTTCBodWUuIFNhbWUgbmFtZSAtPiBzYW1lIGNvbG91ciwgZXZlcnkgcnVuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmFsbGJhY2tDb2xvckZvcihsYWJlbDogc3RyaW5nLCBwYWxldHRlOiBzdHJpbmdbXSk6IHN0cmluZyB7XG4gIGNvbnN0IGtleSA9IG5vcm1hbGl6ZUxhYmVsKGxhYmVsKTtcbiAgaWYgKHBhbGV0dGUgJiYgcGFsZXR0ZS5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIHBhbGV0dGVbaGFzaFN0cmluZyhrZXkpICUgcGFsZXR0ZS5sZW5ndGhdO1xuICB9XG4gIGNvbnN0IGh1ZSA9IChoYXNoU3RyaW5nKGtleSkgKiAxMzcuNTA4KSAlIDM2MDtcbiAgcmV0dXJuIGhzbFRvSGV4KGh1ZSwgNjUsIDUwKTtcbn1cblxuLyoqIFJlc29sdmUgYSBjb2xvdXIgZm9yIGBsYWJlbGA6IGEgbWF0Y2hpbmcgcHJlc2V0J3MgY29sb3VyLCBlbHNlIHRoZSBkZXRlcm1pbmlzdGljIGZhbGxiYWNrLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbG9yRm9yTGFiZWwobGFiZWw6IHN0cmluZywgc2V0OiBQcmVzZXRTZXQpOiBzdHJpbmcge1xuICBjb25zdCBwcmVzZXQgPSBmaW5kUHJlc2V0KGxhYmVsLCBzZXQpO1xuICByZXR1cm4gcHJlc2V0ID8gcHJlc2V0LmNvbG9yIDogZmFsbGJhY2tDb2xvckZvcihsYWJlbCwgc2V0LmZhbGxiYWNrUGFsZXR0ZSk7XG59XG4iXX0=
100
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3MtY29sb3IudXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc3RvcmUvY2xhc3MtY29sb3IudXRpbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFjQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFekQsTUFBTSxVQUFVLGNBQWMsQ0FBQyxDQUFTO0lBQ3RDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7QUFDeEMsQ0FBQztBQUVELG9GQUFvRjtBQUNwRixNQUFNLFVBQVUsVUFBVSxDQUFDLENBQVM7SUFDbEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ1YsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNsQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFDRCx1RUFBdUU7SUFDdkUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLEdBQWlDLEVBQUUsS0FBYTtJQUN4RSxPQUFPLEdBQUcsRUFBRSxTQUFTLEtBQUssWUFBWSxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztBQUN6RSxDQUFDO0FBRUQsK0ZBQStGO0FBQy9GLE1BQU0sVUFBVSxRQUFRLENBQUMsSUFBWSxFQUFFLElBQVksRUFBRSxJ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QUMsQ0FBQztRQUNwRCxDQUFDO1FBQ0QsSUFBSSxNQUFNLENBQUMsS0FBSyxLQUFLLEtBQUs7WUFBRSxPQUFPLE1BQU0sQ0FBQztRQUMxQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQztZQUFFLE9BQU8sZUFBZSxDQUFDLE1BQU0sRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDdkUsTUFBTSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDckIsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBEZXRlcm1pbmlzdGljIGNvbG91ciBlbmdpbmUgZm9yIHByZXNldCBhbm5vdGF0aW9uIGNsYXNzZXMgKGppdC11aSM3MCkuXG4gKlxuICogUmVzb2x1dGlvbiBvcmRlciBmb3IgYSByZWdpb24gYGxhYmVsYDpcbiAqICAgMS4gYSBtYXRjaGluZyBwcmVzZXQgKGV4YWN0IGJ5IGRlZmF1bHQsIG9yIG5vcm1hbGl6ZWQgaWYgdGhlIHNldCdzIG1hdGNoTW9kZSBzYXlzIHNvKVxuICogICAgICAtPiB0aGUgcHJlc2V0J3MgY29sb3VyO1xuICogICAyLiBvdGhlcndpc2UgYSBkZXRlcm1pbmlzdGljIGZhbGxiYWNrIGNvbG91ciBkZXJpdmVkIGZyb20gYSBzdGFibGUgaGFzaCBvZiB0aGUgbmFtZSxcbiAqICAgICAgc28gdGhlIHNhbWUgdW5rbm93biBjbGFzcyBhbHdheXMgZ2V0cyB0aGUgc2FtZSBjb2xvdXIgd2l0aCBubyBzdG9yZWQgc3RhdGUuXG4gKlxuICogVGhlc2UgZnVuY3Rpb25zIGFyZSBwdXJlIChubyBtdXRhdGlvbik7IG9wdC1pbiBwcm9tb3Rpb24gb2YgdW5rbm93biBjbGFzc2VzIGludG8gdGhlXG4gKiBzZXQgaXMgcmVwb3J0ZWQgdG8gdGhlIGNhbGxlciAoc2VlIHtAbGluayBhcHBseVByZXNldENvbG9yc30pLCB3aGljaCBvd25zIHBlcnNpc3RlbmNlLlxuICovXG5pbXBvcnQgeyBDbGFzc1ByZXNldCwgUHJlc2V0U2V0IH0gZnJvbSAnLi4vbW9kZWxzL2NsYXNzLXByZXNldCc7XG5pbXBvcnQgeyBSZWdpb24gfSBmcm9tICcuLi9tb2RlbHMvcmVnaW9uJztcbmltcG9ydCB7IHdpdGhSZWdpb25QYXRjaCB9IGZyb20gJy4uL21vZGVscy9yZWdpb24tY2xvbmUnO1xuXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplTGFiZWwoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIChzID8/ICcnKS50cmltKCkudG9Mb3dlckNhc2UoKTtcbn1cblxuLyoqIFN0YWJsZSwgbm9uLW5lZ2F0aXZlIDMyLWJpdCBzdHJpbmcgaGFzaCAoaWRlbnRpY2FsIGFjcm9zcyBydW5zIGFuZCBtYWNoaW5lcykuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzaFN0cmluZyhzOiBzdHJpbmcpOiBudW1iZXIge1xuICBsZXQgaCA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcy5sZW5ndGg7IGkrKykge1xuICAgIGggPSAoTWF0aC5pbXVsKDMxLCBoKSArIHMuY2hhckNvZGVBdChpKSkgfCAwO1xuICB9XG4gIC8vIEZvbGQgdG8gbm9uLW5lZ2F0aXZlIHdpdGhvdXQgdGhlIE1hdGguYWJzKElOVF9NSU4pIG92ZXJmbG93IHBpdGZhbGwuXG4gIHJldHVybiBoIDwgMCA/IH5oIDogaDtcbn1cblxuLyoqXG4gKiBUaGUga2V5IHR3byBjbGFzcyBuYW1lcyBhcmUgY29tcGFyZWQgYnkgdW5kZXIgdGhlIHNldCdzIG1hdGNoIG1vZGU6IHRoZSBuYW1lXG4gKiBpdHNlbGYgZm9yIGBleGFjdGAsIHRyaW1tZWQgYW5kIGxvd2VyLWNhc2VkIGZvciBgbm9ybWFsaXplZGAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmVzZXRLZXkoc2V0OiBQaWNrPFByZXNldFNldCwgJ21hdGNoTW9kZSc+LCBsYWJlbDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHNldD8ubWF0Y2hNb2RlID09PSAnbm9ybWFsaXplZCcgPyBub3JtYWxpemVMYWJlbChsYWJlbCkgOiBsYWJlbDtcbn1cblxuLyoqIGAjUlJHR0JCYCAodXBwZXItY2FzZSkgZm9yIGFuIEhTTCBjb2xvdXI6IGh1ZSBpbiBkZWdyZWVzLCBzYXR1cmF0aW9uIGFuZCBsaWdodG5lc3MgaW4gJS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoc2xUb0hleChoRGVnOiBudW1iZXIsIHNQY3Q6IG51bWJlciwgbFBjdDogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgcyA9IHNQY3QgLyAxMDA7XG4gIGNvbnN0IGwgPSBsUGN0IC8gMTAwO1xuICBjb25zdCBrID0gKG46IG51bWJlcikgPT4gKG4gKyBoRGVnIC8gMzApICUgMTI7XG4gIGNvbnN0IGEgPSBzICogTWF0aC5taW4obCwgMSAtIGwpO1xuICBjb25zdCBjaGFubmVsID0gKG46IG51bWJlcikgPT4ge1xuICAgIGNvbnN0IHYgPSBsIC0gYSAqIE1hdGgubWF4KC0xLCBNYXRoLm1pbihrKG4pIC0gMywgOSAtIGsobiksIDEpKTtcbiAgICByZXR1cm4gTWF0aC5yb3VuZCgyNTUgKiB2KVxuICAgICAgLnRvU3RyaW5nKDE2KVxuICAgICAgLnBhZFN0YXJ0KDIsICcwJyk7XG4gIH07XG4gIHJldHVybiBgIyR7Y2hhbm5lbCgwKX0ke2NoYW5uZWwoOCl9JHtjaGFubmVsKDQpfWAudG9VcHBlckNhc2UoKTtcbn1cblxuLyoqIEZpbmQgdGhlIHByZXNldCBtYXRjaGluZyBgbGFiZWxgIHVuZGVyIHRoZSBzZXQncyBtYXRjaCBtb2RlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbmRQcmVzZXQobGFiZWw6IHN0cmluZywgc2V0OiBQcmVzZXRTZXQpOiBDbGFzc1ByZXNldCB8IHVuZGVmaW5lZCB7XG4gIGlmICghbGFiZWwgfHwgIXNldD8uY2xhc3NlcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgaWYgKHNldC5tYXRjaE1vZGUgPT09ICdub3JtYWxpemVkJykge1xuICAgIGNvbnN0IG4gPSBub3JtYWxpemVMYWJlbChsYWJlbCk7XG4gICAgcmV0dXJuIHNldC5jbGFzc2VzLmZpbmQoKGMpID0+IG5vcm1hbGl6ZUxhYmVsKGMubmFtZSkgPT09IG4pO1xuICB9XG4gIHJldHVybiBzZXQuY2xhc3Nlcy5maW5kKChjKSA9PiBjLm5hbWUgPT09IGxhYmVsKTtcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmlzdGljIGZhbGxiYWNrIGNvbG91ciBmb3IgYW4gdW5rbm93biBjbGFzcyBuYW1lOiBpbmRleCBpbnRvIHRoZSBwYWxldHRlIGJ5IGFcbiAqIHN0YWJsZSBoYXNoIG9mIHRoZSAobm9ybWFsaXplZCkgbmFtZTsgaWYgdGhlIHBhbGV0dGUgaXMgZW1wdHksIGdlbmVyYXRlIGEgZ29sZGVuLWFuZ2xlXG4gKiBIU0wgaHVlLiBTYW1lIG5hbWUgLT4gc2FtZSBjb2xvdXIsIGV2ZXJ5IHJ1bi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZhbGxiYWNrQ29sb3JGb3IobGFiZWw6IHN0cmluZywgcGFsZXR0ZTogc3RyaW5nW10pOiBzdHJpbmcge1xuICBjb25zdCBrZXkgPSBub3JtYWxpemVMYWJlbChsYWJlbCk7XG4gIGlmIChwYWxldHRlICYmIHBhbGV0dGUubGVuZ3RoID4gMCkge1xuICAgIHJldHVybiBwYWxldHRlW2hhc2hTdHJpbmcoa2V5KSAlIHBhbGV0dGUubGVuZ3RoXTtcbiAgfVxuICBjb25zdCBodWUgPSAoaGFzaFN0cmluZyhrZXkpICogMTM3LjUwOCkgJSAzNjA7XG4gIHJldHVybiBoc2xUb0hleChodWUsIDY1LCA1MCk7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBhIGNvbG91ciBmb3IgYGxhYmVsYDogYSBtYXRjaGluZyBwcmVzZXQncyBjb2xvdXIsIGVsc2UgdGhlIGNvbG91ciBhbiBpbXBvcnRlZCBmaWxlXG4gKiBnYXZlIHRoZSBjbGFzcywgZWxzZSB0aGUgZGV0ZXJtaW5pc3RpYyBmYWxsYmFjay5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbG9yRm9yTGFiZWwobGFiZWw6IHN0cmluZywgc2V0OiBQcmVzZXRTZXQpOiBzdHJpbmcge1xuICBjb25zdCBwcmVzZXQgPSBmaW5kUHJlc2V0KGxhYmVsLCBzZXQpO1xuICBpZiAocHJlc2V0KSByZXR1cm4gcHJlc2V0LmNvbG9yO1xuICByZXR1cm4gc2V0LmltcG9ydGVkQ29sb3JzPy5bcHJlc2V0S2V5KHNldCwgbGFiZWwpXSA/PyBmYWxsYmFja0NvbG9yRm9yKGxhYmVsLCBzZXQuZmFsbGJhY2tQYWxldHRlKTtcbn1cblxuLyoqIE9wdGlvbnMgZm9yIHtAbGluayBhcHBseVByZXNldENvbG9yc30uICovXG5leHBvcnQgaW50ZXJmYWNlIEFwcGx5UHJlc2V0Q29sb3JzT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUcnVlIGZvciBhIHJlZ2lvbiB0aGUgY2FsbGVyIG93bnMgb3V0cmlnaHQgKGZyZXNoLCBub3QgeWV0IHN0b3JlZCwgc28gaW4gbm9cbiAgICogdW5kbyBzbmFwc2hvdCk6IGl0cyBjb2xvdXIgaXMgc2V0IGluIHBsYWNlLiBFdmVyeSBvdGhlciByZWdpb24gd2hvc2VcbiAgICogY29sb3VyIGNoYW5nZXMgaXMgY29waWVkLiBEZWZhdWx0OiBuZXZlciBpbiBwbGFjZS5cbiAgICovXG4gIGluUGxhY2U/OiAocjogUmVnaW9uKSA9PiBib29sZWFuO1xuICAvKipcbiAgICogQ2FsbGVkIG9uY2UgcGVyIHVua25vd24gY2xhc3Mgd2hlbiBgc2V0LmF1dG9Qcm9tb3RlYCBpcyBvbiwgd2l0aCB0aGVcbiAgICogcHJlc2V0IHRvIGFkZCAobmFtZSB0cmltbWVkIGluIGBub3JtYWxpemVkYCBtYXRjaCBtb2RlLCBgc291cmNlOiAnYXV0bydgKS5cbiAgICovXG4gIG9uUHJvbW90ZT86IChwcmVzZXQ6IENsYXNzUHJlc2V0KSA9PiB2b2lkO1xufVxuXG4vKipcbiAqIFJlc29sdmUgZWFjaCBsYWJlbGxlZCByZWdpb24ncyBjb2xvdXIgZnJvbSB0aGUgcHJlc2V0IHNldCAoaml0LXVpIzcwKS4gVGhlXG4gKiBwcmVzZXRzIGFyZSB0aGUgc291cmNlIG9mIHRydXRoOiBhIG1hdGNoaW5nIHByZXNldCBnaXZlcyB0aGUgY2xhc3MgY29sb3VyLFxuICogYW4gdW5rbm93biBjbGFzcyB0aGUgY29sb3VyIGFuIGltcG9ydGVkIGZpbGUgZ2F2ZSBpdCAoYGltcG9ydGVkQ29sb3JzYCkgb3IgZWxzZVxuICogaXRzIGRldGVybWluaXN0aWMgZmFsbGJhY2ssICoqb3ZlcnJpZGluZyBhbnkgY29sb3VyIGFscmVhZHkgb24gdGhlIHJlZ2lvbioqLiBVbmxhYmVsbGVkIHJlZ2lvbnMgYW5kXG4gKiBvbmVzIHRoZSB1c2VyIHJlY29sb3VyZWQgKGBjb2xvck92ZXJyaWRkZW5gKSBhcmUgbGVmdCB1bnRvdWNoZWQuIFVua25vd25cbiAqIGNsYXNzZXMgYXJlIHJlcG9ydGVkIHRocm91Z2ggYG9uUHJvbW90ZWAgd2hlbiBgYXV0b1Byb21vdGVgIGlzIG9uLlxuICpcbiAqIFJldHVybnMgYSBuZXcgYXJyYXk7IHJlZ2lvbnMgd2hvc2UgY29sb3VyIGlzIGFscmVhZHkgcmlnaHQgYXJlIHRoZSBzYW1lXG4gKiBpbnN0YW5jZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVByZXNldENvbG9ycyhcbiAgcmVnaW9uczogUmVnaW9uW10sXG4gIHNldDogUHJlc2V0U2V0LFxuICBvcHRzOiBBcHBseVByZXNldENvbG9yc09wdGlvbnMgPSB7fSxcbik6IFJlZ2lvbltdIHtcbiAgY29uc3Qga25vd24gPSBuZXcgU2V0KHNldC5jbGFzc2VzLm1hcCgoYykgPT4gcHJlc2V0S2V5KHNldCwgYy5uYW1lKSkpO1xuICByZXR1cm4gcmVnaW9ucy5tYXAoKHJlZ2lvbikgPT4ge1xuICAgIGlmICghcmVnaW9uLmxhYmVsIHx8IHJlZ2lvbi5jb2xvck92ZXJyaWRkZW4pIHJldHVybiByZWdpb247XG4gICAgY29uc3QgY29sb3IgPSBjb2xvckZvckxhYmVsKHJlZ2lvbi5sYWJlbCwgc2V0KTtcbiAgICBpZiAoc2V0LmF1dG9Qcm9tb3RlICYmICFrbm93bi5oYXMocHJlc2V0S2V5KHNldCwgcmVnaW9uLmxhYmVsKSkpIHtcbiAgICAgIGtub3duLmFkZChwcmVzZXRLZXkoc2V0LCByZWdpb24ubGFiZWwpKTtcbiAgICAgIC8vIEluIG5vcm1hbGl6ZWQgbW9kZSwgdHJpbSB0aGUgcHJvbW90ZWQgbmFtZSBzbyBsZWFkaW5nL3RyYWlsaW5nXG4gICAgICAvLyB3aGl0ZXNwYWNlIGRvZXNuJ3QgY3JlYXRlIGludmlzaWJsZSBkdXBsaWNhdGVzIG9yIG9kZCBkaXNwbGF5IG5hbWVzLlxuICAgICAgY29uc3QgbmFtZSA9IHNldC5tYXRjaE1vZGUgPT09ICdub3JtYWxpemVkJyA/IHJlZ2lvbi5sYWJlbC50cmltKCkgOiByZWdpb24ubGFiZWw7XG4gICAgICBvcHRzLm9uUHJvbW90ZT8uKHsgbmFtZSwgY29sb3IsIHNvdXJjZTogJ2F1dG8nIH0pO1xuICAgIH1cbiAgICBpZiAocmVnaW9uLmNvbG9yID09PSBjb2xvcikgcmV0dXJuIHJlZ2lvbjtcbiAgICBpZiAoIW9wdHMuaW5QbGFjZT8uKHJlZ2lvbikpIHJldHVybiB3aXRoUmVnaW9uUGF0Y2gocmVnaW9uLCB7IGNvbG9yIH0pO1xuICAgIHJlZ2lvbi5jb2xvciA9IGNvbG9yO1xuICAgIHJldHVybiByZWdpb247XG4gIH0pO1xufVxuIl19
@@ -0,0 +1,63 @@
1
+ import { MultiPolygon, Polygon, Rectangle } from '../models/region';
2
+ /**
3
+ * A fingerprint of each class's regions (by label): their ids and geometry folded into one number
4
+ * per class. Two sets give the same fingerprint for a class when its regions did not change, so
5
+ * comparing a slice's fingerprints before and after an edit names the classes the edit touched
6
+ * (a recoloured or relabelled region touches its old class and its new one). Profile lines and
7
+ * unlabelled regions are left out: they are in no class.
8
+ */
9
+ export function classSignatures(regions) {
10
+ const out = new Map();
11
+ for (const r of regions) {
12
+ if (!r.label || r.isProfile?.())
13
+ continue;
14
+ out.set(r.label, mix(out.get(r.label) ?? 0, regionHash(r)));
15
+ }
16
+ return out;
17
+ }
18
+ /** The classes whose fingerprints differ between `before` and `after` (added and removed included). */
19
+ export function changedClasses(before, after) {
20
+ const out = new Set();
21
+ for (const [label, sig] of after)
22
+ if (before.get(label) !== sig)
23
+ out.add(label);
24
+ for (const label of before.keys())
25
+ if (!after.has(label))
26
+ out.add(label);
27
+ return out;
28
+ }
29
+ /** Order-independent within a class (summed), so reordering regions changes nothing. */
30
+ function mix(acc, h) {
31
+ return (acc + h) % 4294967296;
32
+ }
33
+ function regionHash(r) {
34
+ let h = hashString(String(r.id ?? ''));
35
+ const b = r.bounds;
36
+ if (b instanceof Rectangle)
37
+ return fold(fold(fold(fold(h, b.x), b.y), b.width), b.height);
38
+ const polygons = b instanceof MultiPolygon ? b.polygons : b instanceof Polygon ? [b] : [];
39
+ for (const p of polygons) {
40
+ h = fold(h, p.closed === false ? 1 : 2);
41
+ for (let i = 0; i < p.xpoints.length; i++)
42
+ h = fold(fold(h, p.xpoints[i]), p.ypoints[i]);
43
+ for (const hole of p.holes ?? [])
44
+ for (const [x, y] of hole)
45
+ h = fold(fold(h, x), y);
46
+ // A bézier region's curve moves with its handles, not only its anchors.
47
+ if (p.bezier)
48
+ for (const [dx, dy] of [...(p.handlesIn ?? []), ...(p.handlesOut ?? [])])
49
+ h = fold(fold(h, dx), dy);
50
+ }
51
+ return h;
52
+ }
53
+ /** FNV-style step over a coordinate (kept to 1/1000 px, which no edit is finer than). */
54
+ function fold(h, v) {
55
+ return Math.imul(h ^ (Math.round(v * 1000) | 0), 16777619) >>> 0;
56
+ }
57
+ function hashString(s) {
58
+ let h = 2166136261;
59
+ for (let i = 0; i < s.length; i++)
60
+ h = Math.imul(h ^ s.charCodeAt(i), 16777619) >>> 0;
61
+ return h;
62
+ }
63
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Mtc2lnbmF0dXJlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc3RvcmUvY2xhc3Mtc2lnbmF0dXJlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQVUsTUFBTSxrQkFBa0IsQ0FBQztBQUU1RTs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUFDLE9BQTBCO0lBQ3hELE1BQU0sR0FBRyxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO0lBQ3RDLEtBQUssTUFBTSxDQUFDLElBQUksT0FBTyxFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFO1lBQUUsU0FBUztRQUMxQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlELENBQUM7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRCx1R0FBdUc7QUFDdkcsTUFBTSxVQUFVLGNBQWMsQ0FDNUIsTUFBbUMsRUFDbkMsS0FBa0M7SUFFbEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUM5QixLQUFLLE1BQU0sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLElBQUksS0FBSztRQUFFLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHO1lBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNoRixLQUFLLE1BQU0sS0FBSyxJQUFJLE1BQU0sQ0FBQyxJQUFJLEVBQUU7UUFBRSxJQUFJLENBQUMsS0FBSyxDQUFD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QUFFLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRTtRQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN0RixPQUFPLENBQUMsQ0FBQztBQUNYLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNdWx0aVBvbHlnb24sIFBvbHlnb24sIFJlY3RhbmdsZSwgUmVnaW9uIH0gZnJvbSAnLi4vbW9kZWxzL3JlZ2lvbic7XG5cbi8qKlxuICogQSBmaW5nZXJwcmludCBvZiBlYWNoIGNsYXNzJ3MgcmVnaW9ucyAoYnkgbGFiZWwpOiB0aGVpciBpZHMgYW5kIGdlb21ldHJ5IGZvbGRlZCBpbnRvIG9uZSBudW1iZXJcbiAqIHBlciBjbGFzcy4gVHdvIHNldHMgZ2l2ZSB0aGUgc2FtZSBmaW5nZXJwcmludCBmb3IgYSBjbGFzcyB3aGVuIGl0cyByZWdpb25zIGRpZCBub3QgY2hhbmdlLCBzb1xuICogY29tcGFyaW5nIGEgc2xpY2UncyBmaW5nZXJwcmludHMgYmVmb3JlIGFuZCBhZnRlciBhbiBlZGl0IG5hbWVzIHRoZSBjbGFzc2VzIHRoZSBlZGl0IHRvdWNoZWRcbiAqIChhIHJlY29sb3VyZWQgb3IgcmVsYWJlbGxlZCByZWdpb24gdG91Y2hlcyBpdHMgb2xkIGNsYXNzIGFuZCBpdHMgbmV3IG9uZSkuIFByb2ZpbGUgbGluZXMgYW5kXG4gKiB1bmxhYmVsbGVkIHJlZ2lvbnMgYXJlIGxlZnQgb3V0OiB0aGV5IGFyZSBpbiBubyBjbGFzcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsYXNzU2lnbmF0dXJlcyhyZWdpb25zOiByZWFkb25seSBSZWdpb25bXSk6IE1hcDxzdHJpbmcsIG51bWJlcj4ge1xuICBjb25zdCBvdXQgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICBmb3IgKGNvbnN0IHIgb2YgcmVnaW9ucykge1xuICAgIGlmICghci5sYWJlbCB8fCByLmlzUHJvZmlsZT8uKCkpIGNvbnRpbnVlO1xuICAgIG91dC5zZXQoci5sYWJlbCwgbWl4KG91dC5nZXQoci5sYWJlbCkgPz8gMCwgcmVnaW9uSGFzaChyKSkpO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKiBUaGUgY2xhc3NlcyB3aG9zZSBmaW5nZXJwcmludHMgZGlmZmVyIGJldHdlZW4gYGJlZm9yZWAgYW5kIGBhZnRlcmAgKGFkZGVkIGFuZCByZW1vdmVkIGluY2x1ZGVkKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGFuZ2VkQ2xhc3NlcyhcbiAgYmVmb3JlOiBSZWFkb25seU1hcDxzdHJpbmcsIG51bWJlcj4sXG4gIGFmdGVyOiBSZWFkb25seU1hcDxzdHJpbmcsIG51bWJlcj4sXG4pOiBTZXQ8c3RyaW5nPiB7XG4gIGNvbnN0IG91dCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBmb3IgKGNvbnN0IFtsYWJlbCwgc2lnXSBvZiBhZnRlcikgaWYgKGJlZm9yZS5nZXQobGFiZWwpICE9PSBzaWcpIG91dC5hZGQobGFiZWwpO1xuICBmb3IgKGNvbnN0IGxhYmVsIG9mIGJlZm9yZS5rZXlzKCkpIGlmICghYWZ0ZXIuaGFzKGxhYmVsKSkgb3V0LmFkZChsYWJlbCk7XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKiBPcmRlci1pbmRlcGVuZGVudCB3aXRoaW4gYSBjbGFzcyAoc3VtbWVkKSwgc28gcmVvcmRlcmluZyByZWdpb25zIGNoYW5nZXMgbm90aGluZy4gKi9cbmZ1bmN0aW9uIG1peChhY2M6IG51bWJlciwgaDogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIChhY2MgKyBoKSAlIDQyOTQ5NjcyOTY7XG59XG5cbmZ1bmN0aW9uIHJlZ2lvbkhhc2gocjogUmVnaW9uKTogbnVtYmVyIHtcbiAgbGV0IGggPSBoYXNoU3RyaW5nKFN0cmluZyhyLmlkID8/ICcnKSk7XG4gIGNvbnN0IGIgPSByLmJvdW5kcztcbiAgaWYgKGIgaW5zdGFuY2VvZiBSZWN0YW5nbGUpIHJldHVybiBmb2xkKGZvbGQoZm9sZChmb2xkKGgsIGIueCksIGIueSksIGIud2lkdGgpLCBiLmhlaWdodCk7XG4gIGNvbnN0IHBvbHlnb25zID0gYiBpbnN0YW5jZW9mIE11bHRpUG9seWdvbiA/IGIucG9seWdvbnMgOiBiIGluc3RhbmNlb2YgUG9seWdvbiA/IFtiXSA6IFtdO1xuICBmb3IgKGNvbnN0IHAgb2YgcG9seWdvbnMpIHtcbiAgICBoID0gZm9sZChoLCBwLmNsb3NlZCA9PT0gZmFsc2UgPyAxIDogMik7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwLnhwb2ludHMubGVuZ3RoOyBpKyspIGggPSBmb2xkKGZvbGQoaCwgcC54cG9pbnRzW2ldKSwgcC55cG9pbnRzW2ldKTtcbiAgICBmb3IgKGNvbnN0IGhvbGUgb2YgcC5ob2xlcyA/PyBbXSkgZm9yIChjb25zdCBbeCwgeV0gb2YgaG9sZSkgaCA9IGZvbGQoZm9sZChoLCB4KSwgeSk7XG4gICAgLy8gQSBiw6l6aWVyIHJlZ2lvbidzIGN1cnZlIG1vdmVzIHdpdGggaXRzIGhhbmRsZXMsIG5vdCBvbmx5IGl0cyBhbmNob3JzLlxuICAgIGlmIChwLmJlemllcilcbiAgICAgIGZvciAoY29uc3QgW2R4LCBkeV0gb2YgWy4uLihwLmhhbmRsZXNJbiA/PyBbXSksIC4uLihwLmhhbmRsZXNPdXQgPz8gW10pXSkgaCA9IGZvbGQoZm9sZChoLCBkeCksIGR5KTtcbiAgfVxuICByZXR1cm4gaDtcbn1cblxuLyoqIEZOVi1zdHlsZSBzdGVwIG92ZXIgYSBjb29yZGluYXRlIChrZXB0IHRvIDEvMTAwMCBweCwgd2hpY2ggbm8gZWRpdCBpcyBmaW5lciB0aGFuKS4gKi9cbmZ1bmN0aW9uIGZvbGQoaDogbnVtYmVyLCB2OiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gTWF0aC5pbXVsKGggXiAoTWF0aC5yb3VuZCh2ICogMTAwMCkgfCAwKSwgMTY3Nzc2MTkpID4+PiAwO1xufVxuXG5mdW5jdGlvbiBoYXNoU3RyaW5nKHM6IHN0cmluZyk6IG51bWJlciB7XG4gIGxldCBoID0gMjE2NjEzNjI2MTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzLmxlbmd0aDsgaSsrKSBoID0gTWF0aC5pbXVsKGggXiBzLmNoYXJDb2RlQXQoaSksIDE2Nzc3NjE5KSA+Pj4gMDtcbiAgcmV0dXJuIGg7XG59XG4iXX0=
@@ -0,0 +1,146 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ /**
3
+ * Bounded undo/redo history of immutable snapshots (review RT-13, RegionStore
4
+ * split "RegionHistory").
5
+ *
6
+ * Holds snapshots by reference. That is only sound because the store never
7
+ * changes a snapshot after recording it — `RegionStore` is copy-on-write: each
8
+ * edit replaces the edited region (and the array) rather than mutating them —
9
+ * so a snapshot costs one array of pointers, not a deep clone of every vertex.
10
+ *
11
+ * Recording: call {@link record} with the state just BEFORE a change. Commits
12
+ * coalesce into one step:
13
+ * - between {@link beginGesture} and {@link endGesture} every commit folds into
14
+ * the step its first commit opened, however long the pauses, and a gesture
15
+ * never merges with a commit before or after it (RT-12);
16
+ * - outside a gesture, each commit within `coalesceMs` of the previous one
17
+ * folds into the same step.
18
+ * A fresh step drops the redo future. Up to `limit` steps are kept each way.
19
+ */
20
+ export class RegionHistory {
21
+ constructor(limit = 10, coalesceMs = 250) {
22
+ this.limit = limit;
23
+ this.coalesceMs = coalesceMs;
24
+ this.undoStack = [];
25
+ this.redoStack = [];
26
+ /** True while a coalescing burst is open (further commits fold into it). */
27
+ this.burstOpen = false;
28
+ /** Open gestures (nested begin/end); while > 0 the burst stays open with no timer. */
29
+ this.gestureDepth = 0;
30
+ this.burstTimer = null;
31
+ /** True while a snapshot is being restored, so the restore records nothing. */
32
+ this.restoring = false;
33
+ this.canUndoSubject = new BehaviorSubject(false);
34
+ this.canRedoSubject = new BehaviorSubject(false);
35
+ /** Whether an undo step is available (drives the toolbar's Undo button). */
36
+ this.canUndo$ = this.canUndoSubject.asObservable();
37
+ /** Whether a redo step is available. */
38
+ this.canRedo$ = this.canRedoSubject.asObservable();
39
+ }
40
+ canUndo() {
41
+ return this.undoStack.length > 0;
42
+ }
43
+ canRedo() {
44
+ return this.redoStack.length > 0;
45
+ }
46
+ /**
47
+ * Record `before` — the state just before a change — unless the change
48
+ * folds into the step already open, or a restore is in progress.
49
+ */
50
+ record(before) {
51
+ if (this.restoring)
52
+ return;
53
+ const startsBurst = !this.burstOpen;
54
+ if (this.gestureDepth > 0)
55
+ this.burstOpen = true; // closed by endGesture()
56
+ else
57
+ this.armBurst();
58
+ if (!startsBurst)
59
+ return;
60
+ this.push(this.undoStack, before);
61
+ this.redoStack = [];
62
+ this.emit();
63
+ }
64
+ /**
65
+ * Step back: returns the state to restore (and keeps `current` for redo), or
66
+ * undefined when there is nothing to undo. Restore it inside {@link restore}.
67
+ */
68
+ undo(current) {
69
+ const snapshot = this.undoStack.pop();
70
+ if (snapshot === undefined)
71
+ return undefined;
72
+ this.push(this.redoStack, current);
73
+ this.closeBurst();
74
+ this.emit();
75
+ return snapshot;
76
+ }
77
+ /** Step forward again: the mirror of {@link undo}. */
78
+ redo(current) {
79
+ const snapshot = this.redoStack.pop();
80
+ if (snapshot === undefined)
81
+ return undefined;
82
+ this.push(this.undoStack, current);
83
+ this.closeBurst();
84
+ this.emit();
85
+ return snapshot;
86
+ }
87
+ /** Run `fn` (applying an undo/redo snapshot) without recording anything it triggers. */
88
+ restore(fn) {
89
+ this.restoring = true;
90
+ try {
91
+ fn();
92
+ }
93
+ finally {
94
+ this.restoring = false;
95
+ }
96
+ }
97
+ /** Forget every step (an image load/switch: history never crosses images). */
98
+ reset() {
99
+ this.undoStack = [];
100
+ this.redoStack = [];
101
+ this.closeBurst();
102
+ this.emit();
103
+ }
104
+ /** Start one user gesture: every commit until the matching {@link endGesture} is one step. Nests. */
105
+ beginGesture() {
106
+ if (this.gestureDepth++ === 0)
107
+ this.closeBurst();
108
+ }
109
+ /** End the gesture opened by {@link beginGesture}; the next commit starts a new step. */
110
+ endGesture() {
111
+ if (this.gestureDepth === 0)
112
+ return;
113
+ if (--this.gestureDepth === 0)
114
+ this.closeBurst();
115
+ }
116
+ push(stack, state) {
117
+ stack.push(state);
118
+ if (stack.length > this.limit)
119
+ stack.shift();
120
+ }
121
+ /** (Re)arm the idle timer that closes the current coalescing burst. */
122
+ armBurst() {
123
+ this.burstOpen = true;
124
+ if (this.burstTimer)
125
+ clearTimeout(this.burstTimer);
126
+ this.burstTimer = setTimeout(() => {
127
+ this.burstOpen = false;
128
+ this.burstTimer = null;
129
+ }, this.coalesceMs);
130
+ }
131
+ closeBurst() {
132
+ this.burstOpen = false;
133
+ if (this.burstTimer) {
134
+ clearTimeout(this.burstTimer);
135
+ this.burstTimer = null;
136
+ }
137
+ }
138
+ emit() {
139
+ const canUndo = this.canUndo(), canRedo = this.canRedo();
140
+ if (this.canUndoSubject.value !== canUndo)
141
+ this.canUndoSubject.next(canUndo);
142
+ if (this.canRedoSubject.value !== canRedo)
143
+ this.canRedoSubject.next(canRedo);
144
+ }
145
+ }
146
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLWhpc3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3N0b3JlL3JlZ2lvbi1oaXN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxlQUFlLEVBQWMsTUFBTSxNQUFNLENBQUM7QUFFbkQ7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUFheEIsWUFDbUIsUUFBUSxFQUFFLEVBQ1YsYUFBYSxHQUFHO1FBRGhCLFVBQUssR0FBTCxLQUFLLENBQUs7UUFDVixlQUFVLEdBQVYsVUFBVSxDQUFNO1FBZDNCLGNBQVMsR0FBUSxFQUFFLENBQUM7UUFDcEIsY0FBUyxHQUFRLEVBQUUsQ0FBQztRQUM1Qiw0RUFBNEU7UUFDcEUsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUMxQixzRkFBc0Y7UUFDOUUsaUJBQVksR0FBRyxDQUFDLENBQUM7UUFDakIsZUFBVSxHQUF5QyxJQUFJLENBQUM7UUFDaEUsK0VBQStFO1FBQ3ZFLGNBQVMsR0FBRyxLQUFLLENBQUM7UUFDVCxtQkFBYyxHQUFHLElBQUksZUFBZSxDQUFVLEtBQUssQ0FBQyxDQUFDO1FBQ3JELG1CQUFjLEdBQUcsSUFBSSxlQUFlLENBQVUsS0FBSyxDQUFDLENBQUM7UUFPdEUsNEVBQTRFO1FBQ25FLGFBQVEsR0FBd0IsSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUM1RSx3Q0FBd0M7UUFDL0IsYUFBUSxHQUF3QixJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBTHpFLENBQUM7SUFPSixPQUFPO1FBQ0wsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELE9BQU87UUFDTCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQ7OztPQUdHO0lB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QVU7WUFBRSxZQUFZLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNoQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztZQUN2QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN6QixDQUFDLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3RCLENBQUM7SUFFTyxVQUFVO1FBQ2hCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BCLFlBQVksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDOUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDekIsQ0FBQztJQUNILENBQUM7SUFFTyxJQUFJO1FBQ1YsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUM1QixPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzNCLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEtBQUssT0FBTztZQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzdFLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEtBQUssT0FBTztZQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQy9FLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuXG4vKipcbiAqIEJvdW5kZWQgdW5kby9yZWRvIGhpc3Rvcnkgb2YgaW1tdXRhYmxlIHNuYXBzaG90cyAocmV2aWV3IFJULTEzLCBSZWdpb25TdG9yZVxuICogc3BsaXQgXCJSZWdpb25IaXN0b3J5XCIpLlxuICpcbiAqIEhvbGRzIHNuYXBzaG90cyBieSByZWZlcmVuY2UuIFRoYXQgaXMgb25seSBzb3VuZCBiZWNhdXNlIHRoZSBzdG9yZSBuZXZlclxuICogY2hhbmdlcyBhIHNuYXBzaG90IGFmdGVyIHJlY29yZGluZyBpdCDigJQgYFJlZ2lvblN0b3JlYCBpcyBjb3B5LW9uLXdyaXRlOiBlYWNoXG4gKiBlZGl0IHJlcGxhY2VzIHRoZSBlZGl0ZWQgcmVnaW9uIChhbmQgdGhlIGFycmF5KSByYXRoZXIgdGhhbiBtdXRhdGluZyB0aGVtIOKAlFxuICogc28gYSBzbmFwc2hvdCBjb3N0cyBvbmUgYXJyYXkgb2YgcG9pbnRlcnMsIG5vdCBhIGRlZXAgY2xvbmUgb2YgZXZlcnkgdmVydGV4LlxuICpcbiAqIFJlY29yZGluZzogY2FsbCB7QGxpbmsgcmVjb3JkfSB3aXRoIHRoZSBzdGF0ZSBqdXN0IEJFRk9SRSBhIGNoYW5nZS4gQ29tbWl0c1xuICogY29hbGVzY2UgaW50byBvbmUgc3RlcDpcbiAqICAtIGJldHdlZW4ge0BsaW5rIGJlZ2luR2VzdHVyZX0gYW5kIHtAbGluayBlbmRHZXN0dXJlfSBldmVyeSBjb21taXQgZm9sZHMgaW50b1xuICogICAgdGhlIHN0ZXAgaXRzIGZpcnN0IGNvbW1pdCBvcGVuZWQsIGhvd2V2ZXIgbG9uZyB0aGUgcGF1c2VzLCBhbmQgYSBnZXN0dXJlXG4gKiAgICBuZXZlciBtZXJnZXMgd2l0aCBhIGNvbW1pdCBiZWZvcmUgb3IgYWZ0ZXIgaXQgKFJULTEyKTtcbiAqICAtIG91dHNpZGUgYSBnZXN0dXJlLCBlYWNoIGNvbW1pdCB3aXRoaW4gYGNvYWxlc2NlTXNgIG9mIHRoZSBwcmV2aW91cyBvbmVcbiAqICAgIGZvbGRzIGludG8gdGhlIHNhbWUgc3RlcC5cbiAqIEEgZnJlc2ggc3RlcCBkcm9wcyB0aGUgcmVkbyBmdXR1cmUuIFVwIHRvIGBsaW1pdGAgc3RlcHMgYXJlIGtlcHQgZWFjaCB3YXkuXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWdpb25IaXN0b3J5PFQ+IHtcbiAgcHJpdmF0ZSB1bmRvU3RhY2s6IFRbXSA9IFtdO1xuICBwcml2YXRlIHJlZG9TdGFjazogVFtdID0gW107XG4gIC8qKiBUcnVlIHdoaWxlIGEgY29hbGVzY2luZyBidXJzdCBpcyBvcGVuIChmdXJ0aGVyIGNvbW1pdHMgZm9sZCBpbnRvIGl0KS4gKi9cbiAgcHJpdmF0ZSBidXJzdE9wZW4gPSBmYWxzZTtcbiAgLyoqIE9wZW4gZ2VzdHVyZXMgKG5lc3RlZCBiZWdpbi9lbmQpOyB3aGlsZSA+IDAgdGhlIGJ1cnN0IHN0YXlzIG9wZW4gd2l0aCBubyB0aW1lci4gKi9cbiAgcHJpdmF0ZSBnZXN0dXJlRGVwdGggPSAwO1xuICBwcml2YXRlIGJ1cnN0VGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgbnVsbCA9IG51bGw7XG4gIC8qKiBUcnVlIHdoaWxlIGEgc25hcHNob3QgaXMgYmVpbmcgcmVzdG9yZWQsIHNvIHRoZSByZXN0b3JlIHJlY29yZHMgbm90aGluZy4gKi9cbiAgcHJpdmF0ZSByZXN0b3JpbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSByZWFkb25seSBjYW5VbmRvU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IGNhblJlZG9TdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBsaW1pdCA9IDEwLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY29hbGVzY2VNcyA9IDI1MCxcbiAgKSB7fVxuXG4gIC8qKiBXaGV0aGVyIGFuIHVuZG8gc3RlcCBpcyBhdmFpbGFibGUgKGRyaXZlcyB0aGUgdG9vbGJhcidzIFVuZG8gYnV0dG9uKS4gKi9cbiAgcmVhZG9ubHkgY2FuVW5kbyQ6IE9ic2VydmFibGU8Ym9vbGVhbj4gPSB0aGlzLmNhblVuZG9TdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICAvKiogV2hldGhlciBhIHJlZG8gc3RlcCBpcyBhdmFpbGFibGUuICovXG4gIHJlYWRvbmx5IGNhblJlZG8kOiBPYnNlcnZhYmxlPGJvb2xlYW4+ID0gdGhpcy5jYW5SZWRvU3ViamVjdC5hc09ic2VydmFibGUoKTtcblxuICBjYW5VbmRvKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnVuZG9TdGFjay5sZW5ndGggPiAwO1xuICB9XG5cbiAgY2FuUmVkbygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWRvU3RhY2subGVuZ3RoID4gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWNvcmQgYGJlZm9yZWAg4oCUIHRoZSBzdGF0ZSBqdXN0IGJlZm9yZSBhIGNoYW5nZSDigJQgdW5sZXNzIHRoZSBjaGFuZ2VcbiAgICogZm9sZHMgaW50byB0aGUgc3RlcCBhbHJlYWR5IG9wZW4sIG9yIGEgcmVzdG9yZSBpcyBpbiBwcm9ncmVzcy5cbiAgICovXG4gIHJlY29yZChiZWZvcmU6IFQpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5yZXN0b3JpbmcpIHJldHVybjtcbiAgICBjb25zdCBzdGFydHNCdXJzdCA9ICF0aGlzLmJ1cnN0T3BlbjtcbiAgICBpZiAodGhpcy5nZXN0dXJlRGVwdGggPiAwKVxuICAgICAgdGhpcy5idXJzdE9wZW4gPSB0cnVlOyAvLyBjbG9zZWQgYnkgZW5kR2VzdHVyZSgpXG4gICAgZWxzZSB0aGlzLmFybUJ1cnN0KCk7XG4gICAgaWYgKCFzdGFydHNCdXJzdCkgcmV0dXJuO1xuICAgIHRoaXMucHVzaCh0aGlzLnVuZG9TdGFjaywgYmVmb3JlKTtcbiAgICB0aGlzLnJlZG9TdGFjayA9IFtdO1xuICAgIHRoaXMuZW1pdCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0ZXAgYmFjazogcmV0dXJucyB0aGUgc3RhdGUgdG8gcmVzdG9yZSAoYW5kIGtlZXBzIGBjdXJyZW50YCBmb3IgcmVkbyksIG9yXG4gICAqIHVuZGVmaW5lZCB3aGVuIHRoZXJlIGlzIG5vdGhpbmcgdG8gdW5kby4gUmVzdG9yZSBpdCBpbnNpZGUge0BsaW5rIHJlc3RvcmV9LlxuICAgKi9cbiAgdW5kbyhjdXJyZW50OiBUKTogVCB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3Qgc25hcHNob3QgPSB0aGlzLnVuZG9TdGFjay5wb3AoKTtcbiAgICBpZiAoc25hcHNob3QgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB0aGlzLnB1c2godGhpcy5yZWRvU3RhY2ssIGN1cnJlbnQpO1xuICAgIHRoaXMuY2xvc2VCdXJzdCgpO1xuICAgIHRoaXMuZW1pdCgpO1xuICAgIHJldHVybiBzbmFwc2hvdDtcbiAgfVxuXG4gIC8qKiBTdGVwIGZvcndhcmQgYWdhaW46IHRoZSBtaXJyb3Igb2Yge0BsaW5rIHVuZG99LiAqL1xuICByZWRvKGN1cnJlbnQ6IFQpOiBUIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBzbmFwc2hvdCA9IHRoaXMucmVkb1N0YWNrLnBvcCgpO1xuICAgIGlmIChzbmFwc2hvdCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHRoaXMucHVzaCh0aGlzLnVuZG9TdGFjaywgY3VycmVudCk7XG4gICAgdGhpcy5jbG9zZUJ1cnN0KCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gICAgcmV0dXJuIHNuYXBzaG90O1xuICB9XG5cbiAgLyoqIFJ1biBgZm5gIChhcHBseWluZyBhbiB1bmRvL3JlZG8gc25hcHNob3QpIHdpdGhvdXQgcmVjb3JkaW5nIGFueXRoaW5nIGl0IHRyaWdnZXJzLiAqL1xuICByZXN0b3JlKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5yZXN0b3JpbmcgPSB0cnVlO1xuICAgIHRyeSB7XG4gICAgICBmbigpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLnJlc3RvcmluZyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBGb3JnZXQgZXZlcnkgc3RlcCAoYW4gaW1hZ2UgbG9hZC9zd2l0Y2g6IGhpc3RvcnkgbmV2ZXIgY3Jvc3NlcyBpbWFnZXMpLiAqL1xuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLnVuZG9TdGFjayA9IFtdO1xuICAgIHRoaXMucmVkb1N0YWNrID0gW107XG4gICAgdGhpcy5jbG9zZUJ1cnN0KCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICAvKiogU3RhcnQgb25lIHVzZXIgZ2VzdHVyZTogZXZlcnkgY29tbWl0IHVudGlsIHRoZSBtYXRjaGluZyB7QGxpbmsgZW5kR2VzdHVyZX0gaXMgb25lIHN0ZXAuIE5lc3RzLiAqL1xuICBiZWdpbkdlc3R1cmUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZ2VzdHVyZURlcHRoKysgPT09IDApIHRoaXMuY2xvc2VCdXJzdCgpO1xuICB9XG5cbiAgLyoqIEVuZCB0aGUgZ2VzdHVyZSBvcGVuZWQgYnkge0BsaW5rIGJlZ2luR2VzdHVyZX07IHRoZSBuZXh0IGNvbW1pdCBzdGFydHMgYSBuZXcgc3RlcC4gKi9cbiAgZW5kR2VzdHVyZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5nZXN0dXJlRGVwdGggPT09IDApIHJldHVybjtcbiAgICBpZiAoLS10aGlzLmdlc3R1cmVEZXB0aCA9PT0gMCkgdGhpcy5jbG9zZUJ1cnN0KCk7XG4gIH1cblxuICBwcml2YXRlIHB1c2goc3RhY2s6IFRbXSwgc3RhdGU6IFQpOiB2b2lkIHtcbiAgICBzdGFjay5wdXNoKHN0YXRlKTtcbiAgICBpZiAoc3RhY2subGVuZ3RoID4gdGhpcy5saW1pdCkgc3RhY2suc2hpZnQoKTtcbiAgfVxuXG4gIC8qKiAoUmUpYXJtIHRoZSBpZGxlIHRpbWVyIHRoYXQgY2xvc2VzIHRoZSBjdXJyZW50IGNvYWxlc2NpbmcgYnVyc3QuICovXG4gIHByaXZhdGUgYXJtQnVyc3QoKTogdm9pZCB7XG4gICAgdGhpcy5idXJzdE9wZW4gPSB0cnVlO1xuICAgIGlmICh0aGlzLmJ1cnN0VGltZXIpIGNsZWFyVGltZW91dCh0aGlzLmJ1cnN0VGltZXIpO1xuICAgIHRoaXMuYnVyc3RUaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5idXJzdE9wZW4gPSBmYWxzZTtcbiAgICAgIHRoaXMuYnVyc3RUaW1lciA9IG51bGw7XG4gICAgfSwgdGhpcy5jb2FsZXNjZU1zKTtcbiAgfVxuXG4gIHByaXZhdGUgY2xvc2VCdXJzdCgpOiB2b2lkIHtcbiAgICB0aGlzLmJ1cnN0T3BlbiA9IGZhbHNlO1xuICAgIGlmICh0aGlzLmJ1cnN0VGltZXIpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLmJ1cnN0VGltZXIpO1xuICAgICAgdGhpcy5idXJzdFRpbWVyID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGVtaXQoKTogdm9pZCB7XG4gICAgY29uc3QgY2FuVW5kbyA9IHRoaXMuY2FuVW5kbygpLFxuICAgICAgY2FuUmVkbyA9IHRoaXMuY2FuUmVkbygpO1xuICAgIGlmICh0aGlzLmNhblVuZG9TdWJqZWN0LnZhbHVlICE9PSBjYW5VbmRvKSB0aGlzLmNhblVuZG9TdWJqZWN0Lm5leHQoY2FuVW5kbyk7XG4gICAgaWYgKHRoaXMuY2FuUmVkb1N1YmplY3QudmFsdWUgIT09IGNhblJlZG8pIHRoaXMuY2FuUmVkb1N1YmplY3QubmV4dChjYW5SZWRvKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,144 @@
1
+ import { withRegionZ } from '../models/region-clone';
2
+ /**
3
+ * Where the region store's *live* set comes from and goes back to: a per-image
4
+ * cache (keyed by the image's first URL, else its file name) and, while a
5
+ * z-stack is loaded, a per-slice map for the current image (jit-ui#93).
6
+ *
7
+ * The owner holds the live array; every method that can change scope takes
8
+ * the current live array (to capture its edits) and returns the incoming
9
+ * live set, or null when nothing changes. It never changes a region: slice
10
+ * tags are applied to copies ({@link withRegionZ}).
11
+ */
12
+ export class RegionScopeCache {
13
+ constructor() {
14
+ this.byImage = new Map();
15
+ this.bySlice = new Map();
16
+ this.stack = false;
17
+ this.sliceZ = 0;
18
+ this.layout = 'combined';
19
+ /** Slices loaded with regions: a per-slice-file save re-writes them even when
20
+ * now empty, so clearing a slice and saving removes its geojson. */
21
+ this.initialNonEmpty = new Set();
22
+ }
23
+ /** The cache key for an image: its first URL, else its file name. */
24
+ static imageKey(imageInfo) {
25
+ if (!imageInfo)
26
+ return undefined;
27
+ if (imageInfo.urls && imageInfo.urls.length > 0 && imageInfo.urls[0]) {
28
+ return imageInfo.urls[0];
29
+ }
30
+ return imageInfo.fileName || undefined;
31
+ }
32
+ /** The active image's cache key (see {@link imageKey}). */
33
+ get activeImage() {
34
+ return this.imageKey;
35
+ }
36
+ /** True while a z-stack is loaded and regions are held per slice. */
37
+ get stackMode() {
38
+ return this.stack;
39
+ }
40
+ /** The current display slice (zero-based; 0 outside stack mode unless set). */
41
+ get displaySlice() {
42
+ return this.sliceZ;
43
+ }
44
+ /** How the current stack persists; meaningless outside stack mode. */
45
+ get saveLayout() {
46
+ return this.layout;
47
+ }
48
+ /** Record `live` as the current image's regions. */
49
+ sync(live) {
50
+ if (this.imageKey)
51
+ this.byImage.set(this.imageKey, live.slice());
52
+ }
53
+ /**
54
+ * Make `key` the active image: ends stack mode, caches `live` under the
55
+ * outgoing image, and returns the incoming image's regions (or []). Null when
56
+ * `key` already is the active image (repeated replots keep their regions).
57
+ */
58
+ switchImage(key, live) {
59
+ if (this.imageKey === key)
60
+ return null;
61
+ // The loader re-enters stack mode afterwards if the new image is a z-stack.
62
+ this.exitStack();
63
+ if (this.imageKey)
64
+ this.byImage.set(this.imageKey, live.slice());
65
+ this.imageKey = key;
66
+ const cached = key ? this.byImage.get(key) : undefined;
67
+ return cached ? cached.slice() : [];
68
+ }
69
+ /**
70
+ * Enter per-slice mode with `slices` (already admitted by the store, each
71
+ * region tagged with its slice) and return `initialZ`'s slice as the live set.
72
+ */
73
+ enterStack(slices, initialZ, layout) {
74
+ this.stack = true;
75
+ this.layout = layout;
76
+ this.sliceZ = initialZ || 0;
77
+ this.bySlice = new Map();
78
+ this.initialNonEmpty = new Set();
79
+ for (const [z, regs] of slices) {
80
+ this.bySlice.set(z, regs);
81
+ if (regs.length)
82
+ this.initialNonEmpty.add(z);
83
+ }
84
+ return (this.bySlice.get(this.sliceZ) ?? []).slice();
85
+ }
86
+ /** Leave stack mode; a no-op outside it. */
87
+ exitStack() {
88
+ if (!this.stack)
89
+ return;
90
+ this.stack = false;
91
+ this.sliceZ = 0;
92
+ this.bySlice = new Map();
93
+ this.initialNonEmpty = new Set();
94
+ }
95
+ /**
96
+ * Show slice `z`: capture `live` into the current slice and return slice
97
+ * `z`'s regions. Null when nothing swaps — the same slice, or outside stack
98
+ * mode (where the index is only recorded).
99
+ */
100
+ showSlice(z, live) {
101
+ const next = z || 0;
102
+ if (!this.stack) {
103
+ this.sliceZ = next;
104
+ return null;
105
+ }
106
+ if (this.sliceZ === next)
107
+ return null;
108
+ this.bySlice.set(this.sliceZ, live.slice());
109
+ this.sliceZ = next;
110
+ return (this.bySlice.get(next) ?? []).slice();
111
+ }
112
+ /** Every slice's regions (current one from `live`), each tagged with its z,
113
+ * in slice order; `live` itself outside stack mode. */
114
+ sliceRegions(live) {
115
+ if (!this.stack)
116
+ return live.slice();
117
+ this.bySlice.set(this.sliceZ, live.slice());
118
+ const out = [];
119
+ const zs = Array.from(this.bySlice.keys()).sort((a, b) => a - b);
120
+ for (const z of zs) {
121
+ for (const r of this.bySlice.get(z))
122
+ out.push(withRegionZ(r, z));
123
+ }
124
+ return out;
125
+ }
126
+ /** Slices to write on a per-slice-file save: every slice with regions plus
127
+ * every slice loaded non-empty (re-written empty when cleared). Empty
128
+ * outside stack mode. */
129
+ stackSaveSlices(live) {
130
+ const out = new Map();
131
+ if (!this.stack)
132
+ return out;
133
+ this.bySlice.set(this.sliceZ, live.slice());
134
+ const zs = new Set(this.initialNonEmpty);
135
+ for (const [z, regs] of this.bySlice)
136
+ if (regs.length)
137
+ zs.add(z);
138
+ for (const z of Array.from(zs).sort((a, b) => a - b)) {
139
+ out.set(z, (this.bySlice.get(z) ?? []).map((r) => withRegionZ(r, z)));
140
+ }
141
+ return out;
142
+ }
143
+ }
144
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLXNjb3BlLWNhY2hlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9zdG9yZS9yZWdpb24tc2NvcGUtY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBT3JEOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sT0FBTyxnQkFBZ0I7SUFBN0I7UUFDVSxZQUFPLEdBQUcsSUFBSSxHQUFHLEVBQW9CLENBQUM7UUFHdEMsWUFBTyxHQUFHLElBQUksR0FBRyxFQUFvQixDQUFDO1FBQ3RDLFVBQUssR0FBRyxLQUFLLENBQUM7UUFDZCxXQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsV0FBTSxHQUFvQixVQUFVLENBQUM7UUFDN0M7NkVBQ3FFO1FBQzdELG9CQUFlLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQTRIOUMsQ0FBQztJQTFIQyxxRUFBcUU7SUFDckUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxTQUFpQztRQUMvQyxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU8sU0FBUyxDQUFDO1FBQ2pDLElBQUksU0FBUyxDQUFDLElBQUksSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3JFLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzQixDQUFDO1FBQ0QsT0FBTyxTQUFTLENBQUMsUUFBUSxJQUFJLFNBQVMsQ0FBQztJQUN6QyxDQUFDO0lBRUQsMkRBQTJEO0lBQzNELElBQUksV0FBVztRQUNiLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN2QixDQUFDO0lBRUQscUVBQXFFO0lBQ3JFLElBQUksU0FBUztRQUNYLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNwQixDQUFDO0lBRUQsK0VBQStF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QUFJLEdBQUcsRUFBb0IsQ0FBQztRQUN4QyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPLEdBQUcsQ0FBQztRQUM1QixJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQzVDLE1BQU0sRUFBRSxHQUFHLElBQUksR0FBRyxDQUFTLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNqRCxLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLE9BQU87WUFBRSxJQUFJLElBQUksQ0FBQyxNQUFNO2dCQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakUsS0FBSyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3JELEdBQUcsQ0FBQyxHQUFHLENBQ0wsQ0FBQyxFQUNELENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQzFELENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJSW1hZ2VJbmZvIH0gZnJvbSAnLi4vY29udHJhY3RzL2ltYWdlLmNvbnRyYWN0JztcbmltcG9ydCB7IFJlZ2lvbiB9IGZyb20gJy4uL21vZGVscy9yZWdpb24nO1xuaW1wb3J0IHsgd2l0aFJlZ2lvblogfSBmcm9tICcuLi9tb2RlbHMvcmVnaW9uLWNsb25lJztcblxuLyoqIEhvdyBhIHN0YWNrJ3MgcmVnaW9ucyByb3VuZC10cmlwIHRvIGRpc2sgKGppdC11aSM5Myk6IGBjb21iaW5lZGAgd3JpdGVzIG9uZVxuICogIHotaW5kZXhlZCBnZW9qc29uIChzaW5nbGUtZmlsZSB6LXN0YWNrLCBRdVBhdGggc2NoZW1hKTsgYHBlci1zbGljZS1maWxlYFxuICogIHdyaXRlcyBvbmUgZ2VvanNvbiBwZXIgc2xpY2UtZmlsZSAoYSBmb2xkZXIgb2YgbnVtYmVyZWQgaW1hZ2VzKS4gKi9cbmV4cG9ydCB0eXBlIFN0YWNrU2F2ZUxheW91dCA9ICdjb21iaW5lZCcgfCAncGVyLXNsaWNlLWZpbGUnO1xuXG4vKipcbiAqIFdoZXJlIHRoZSByZWdpb24gc3RvcmUncyAqbGl2ZSogc2V0IGNvbWVzIGZyb20gYW5kIGdvZXMgYmFjayB0bzogYSBwZXItaW1hZ2VcbiAqIGNhY2hlIChrZXllZCBieSB0aGUgaW1hZ2UncyBmaXJzdCBVUkwsIGVsc2UgaXRzIGZpbGUgbmFtZSkgYW5kLCB3aGlsZSBhXG4gKiB6LXN0YWNrIGlzIGxvYWRlZCwgYSBwZXItc2xpY2UgbWFwIGZvciB0aGUgY3VycmVudCBpbWFnZSAoaml0LXVpIzkzKS5cbiAqXG4gKiBUaGUgb3duZXIgaG9sZHMgdGhlIGxpdmUgYXJyYXk7IGV2ZXJ5IG1ldGhvZCB0aGF0IGNhbiBjaGFuZ2Ugc2NvcGUgdGFrZXNcbiAqIHRoZSBjdXJyZW50IGxpdmUgYXJyYXkgKHRvIGNhcHR1cmUgaXRzIGVkaXRzKSBhbmQgcmV0dXJucyB0aGUgaW5jb21pbmdcbiAqIGxpdmUgc2V0LCBvciBudWxsIHdoZW4gbm90aGluZyBjaGFuZ2VzLiBJdCBuZXZlciBjaGFuZ2VzIGEgcmVnaW9uOiBzbGljZVxuICogdGFncyBhcmUgYXBwbGllZCB0byBjb3BpZXMgKHtAbGluayB3aXRoUmVnaW9uWn0pLlxuICovXG5leHBvcnQgY2xhc3MgUmVnaW9uU2NvcGVDYWNoZSB7XG4gIHByaXZhdGUgYnlJbWFnZSA9IG5ldyBNYXA8c3RyaW5nLCBSZWdpb25bXT4oKTtcbiAgcHJpdmF0ZSBpbWFnZUtleTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgYnlTbGljZSA9IG5ldyBNYXA8bnVtYmVyLCBSZWdpb25bXT4oKTtcbiAgcHJpdmF0ZSBzdGFjayA9IGZhbHNlO1xuICBwcml2YXRlIHNsaWNlWiA9IDA7XG4gIHByaXZhdGUgbGF5b3V0OiBTdGFja1NhdmVMYXlvdXQgPSAnY29tYmluZWQnO1xuICAvKiogU2xpY2VzIGxvYWRlZCB3aXRoIHJlZ2lvbnM6IGEgcGVyLXNsaWNlLWZpbGUgc2F2ZSByZS13cml0ZXMgdGhlbSBldmVuIHdoZW5cbiAgICogIG5vdyBlbXB0eSwgc28gY2xlYXJpbmcgYSBzbGljZSBhbmQgc2F2aW5nIHJlbW92ZXMgaXRzIGdlb2pzb24uICovXG4gIHByaXZhdGUgaW5pdGlhbE5vbkVtcHR5ID0gbmV3IFNldDxudW1iZXI+KCk7XG5cbiAgLyoqIFRoZSBjYWNoZSBrZXkgZm9yIGFuIGltYWdlOiBpdHMgZmlyc3QgVVJMLCBlbHNlIGl0cyBmaWxlIG5hbWUuICovXG4gIHN0YXRpYyBpbWFnZUtleShpbWFnZUluZm86IElJbWFnZUluZm8gfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICghaW1hZ2VJbmZvKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmIChpbWFnZUluZm8udXJscyAmJiBpbWFnZUluZm8udXJscy5sZW5ndGggPiAwICYmIGltYWdlSW5mby51cmxzWzBdKSB7XG4gICAgICByZXR1cm4gaW1hZ2VJbmZvLnVybHNbMF07XG4gICAgfVxuICAgIHJldHVybiBpbWFnZUluZm8uZmlsZU5hbWUgfHwgdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqIFRoZSBhY3RpdmUgaW1hZ2UncyBjYWNoZSBrZXkgKHNlZSB7QGxpbmsgaW1hZ2VLZXl9KS4gKi9cbiAgZ2V0IGFjdGl2ZUltYWdlKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuaW1hZ2VLZXk7XG4gIH1cblxuICAvKiogVHJ1ZSB3aGlsZSBhIHotc3RhY2sgaXMgbG9hZGVkIGFuZCByZWdpb25zIGFyZSBoZWxkIHBlciBzbGljZS4gKi9cbiAgZ2V0IHN0YWNrTW9kZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zdGFjaztcbiAgfVxuXG4gIC8qKiBUaGUgY3VycmVudCBkaXNwbGF5IHNsaWNlICh6ZXJvLWJhc2VkOyAwIG91dHNpZGUgc3RhY2sgbW9kZSB1bmxlc3Mgc2V0KS4gKi9cbiAgZ2V0IGRpc3BsYXlTbGljZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnNsaWNlWjtcbiAgfVxuXG4gIC8qKiBIb3cgdGhlIGN1cnJlbnQgc3RhY2sgcGVyc2lzdHM7IG1lYW5pbmdsZXNzIG91dHNpZGUgc3RhY2sgbW9kZS4gKi9cbiAgZ2V0IHNhdmVMYXlvdXQoKTogU3RhY2tTYXZlTGF5b3V0IHtcbiAgICByZXR1cm4gdGhpcy5sYXlvdXQ7XG4gIH1cblxuICAvKiogUmVjb3JkIGBsaXZlYCBhcyB0aGUgY3VycmVudCBpbWFnZSdzIHJlZ2lvbnMuICovXG4gIHN5bmMobGl2ZTogUmVnaW9uW10pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pbWFnZUtleSkgdGhpcy5ieUltYWdlLnNldCh0aGlzLmltYWdlS2V5LCBsaXZlLnNsaWNlKCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ha2UgYGtleWAgdGhlIGFjdGl2ZSBpbWFnZTogZW5kcyBzdGFjayBtb2RlLCBjYWNoZXMgYGxpdmVgIHVuZGVyIHRoZVxuICAgKiBvdXRnb2luZyBpbWFnZSwgYW5kIHJldHVybnMgdGhlIGluY29taW5nIGltYWdlJ3MgcmVnaW9ucyAob3IgW10pLiBOdWxsIHdoZW5cbiAgICogYGtleWAgYWxyZWFkeSBpcyB0aGUgYWN0aXZlIGltYWdlIChyZXBlYXRlZCByZXBsb3RzIGtlZXAgdGhlaXIgcmVnaW9ucykuXG4gICAqL1xuICBzd2l0Y2hJbWFnZShrZXk6IHN0cmluZyB8IHVuZGVmaW5lZCwgbGl2ZTogUmVnaW9uW10pOiBSZWdpb25bXSB8IG51bGwge1xuICAgIGlmICh0aGlzLmltYWdlS2V5ID09PSBrZXkpIHJldHVybiBudWxsO1xuICAgIC8vIFRoZSBsb2FkZXIgcmUtZW50ZXJzIHN0YWNrIG1vZGUgYWZ0ZXJ3YXJkcyBpZiB0aGUgbmV3IGltYWdlIGlzIGEgei1zdGFjay5cbiAgICB0aGlzLmV4aXRTdGFjaygpO1xuICAgIGlmICh0aGlzLmltYWdlS2V5KSB0aGlzLmJ5SW1hZ2Uuc2V0KHRoaXMuaW1hZ2VLZXksIGxpdmUuc2xpY2UoKSk7XG4gICAgdGhpcy5pbWFnZUtleSA9IGtleTtcbiAgICBjb25zdCBjYWNoZWQgPSBrZXkgPyB0aGlzLmJ5SW1hZ2UuZ2V0KGtleSkgOiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIGNhY2hlZCA/IGNhY2hlZC5zbGljZSgpIDogW107XG4gIH1cblxuICAvKipcbiAgICogRW50ZXIgcGVyLXNsaWNlIG1vZGUgd2l0aCBgc2xpY2VzYCAoYWxyZWFkeSBhZG1pdHRlZCBieSB0aGUgc3RvcmUsIGVhY2hcbiAgICogcmVnaW9uIHRhZ2dlZCB3aXRoIGl0cyBzbGljZSkgYW5kIHJldHVybiBgaW5pdGlhbFpgJ3Mgc2xpY2UgYXMgdGhlIGxpdmUgc2V0LlxuICAgKi9cbiAgZW50ZXJTdGFjayhzbGljZXM6IE1hcDxudW1iZXIsIFJlZ2lvbltdPiwgaW5pdGlhbFo6IG51bWJlciwgbGF5b3V0OiBTdGFja1NhdmVMYXlvdXQpOiBSZWdpb25bXSB7XG4gICAgdGhpcy5zdGFjayA9IHRydWU7XG4gICAgdGhpcy5sYXlvdXQgPSBsYXlvdXQ7XG4gICAgdGhpcy5zbGljZVogPSBpbml0aWFsWiB8fCAwO1xuICAgIHRoaXMuYnlTbGljZSA9IG5ldyBNYXA8bnVtYmVyLCBSZWdpb25bXT4oKTtcbiAgICB0aGlzLmluaXRpYWxOb25FbXB0eSA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgIGZvciAoY29uc3QgW3osIHJlZ3NdIG9mIHNsaWNlcykge1xuICAgICAgdGhpcy5ieVNsaWNlLnNldCh6LCByZWdzKTtcbiAgICAgIGlmIChyZWdzLmxlbmd0aCkgdGhpcy5pbml0aWFsTm9uRW1wdHkuYWRkKHopO1xuICAgIH1cbiAgICByZXR1cm4gKHRoaXMuYnlTbGljZS5nZXQodGhpcy5zbGljZVopID8/IFtdKS5zbGljZSgpO1xuICB9XG5cbiAgLyoqIExlYXZlIHN0YWNrIG1vZGU7IGEgbm8tb3Agb3V0c2lkZSBpdC4gKi9cbiAgZXhpdFN0YWNrKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5zdGFjaykgcmV0dXJuO1xuICAgIHRoaXMuc3RhY2sgPSBmYWxzZTtcbiAgICB0aGlzLnNsaWNlWiA9IDA7XG4gICAgdGhpcy5ieVNsaWNlID0gbmV3IE1hcDxudW1iZXIsIFJlZ2lvbltdPigpO1xuICAgIHRoaXMuaW5pdGlhbE5vbkVtcHR5ID0gbmV3IFNldDxudW1iZXI+KCk7XG4gIH1cblxuICAvKipcbiAgICogU2hvdyBzbGljZSBgemA6IGNhcHR1cmUgYGxpdmVgIGludG8gdGhlIGN1cnJlbnQgc2xpY2UgYW5kIHJldHVybiBzbGljZVxuICAgKiBgemAncyByZWdpb25zLiBOdWxsIHdoZW4gbm90aGluZyBzd2FwcyDigJQgdGhlIHNhbWUgc2xpY2UsIG9yIG91dHNpZGUgc3RhY2tcbiAgICogbW9kZSAod2hlcmUgdGhlIGluZGV4IGlzIG9ubHkgcmVjb3JkZWQpLlxuICAgKi9cbiAgc2hvd1NsaWNlKHo6IG51bWJlciwgbGl2ZTogUmVnaW9uW10pOiBSZWdpb25bXSB8IG51bGwge1xuICAgIGNvbnN0IG5leHQgPSB6IHx8IDA7XG4gICAgaWYgKCF0aGlzLnN0YWNrKSB7XG4gICAgICB0aGlzLnNsaWNlWiA9IG5leHQ7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKHRoaXMuc2xpY2VaID09PSBuZXh0KSByZXR1cm4gbnVsbDtcbiAgICB0aGlzLmJ5U2xpY2Uuc2V0KHRoaXMuc2xpY2VaLCBsaXZlLnNsaWNlKCkpO1xuICAgIHRoaXMuc2xpY2VaID0gbmV4dDtcbiAgICByZXR1cm4gKHRoaXMuYnlTbGljZS5nZXQobmV4dCkgPz8gW10pLnNsaWNlKCk7XG4gIH1cblxuICAvKiogRXZlcnkgc2xpY2UncyByZWdpb25zIChjdXJyZW50IG9uZSBmcm9tIGBsaXZlYCksIGVhY2ggdGFnZ2VkIHdpdGggaXRzIHosXG4gICAqICBpbiBzbGljZSBvcmRlcjsgYGxpdmVgIGl0c2VsZiBvdXRzaWRlIHN0YWNrIG1vZGUuICovXG4gIHNsaWNlUmVnaW9ucyhsaXZlOiBSZWdpb25bXSk6IFJlZ2lvbltdIHtcbiAgICBpZiAoIXRoaXMuc3RhY2spIHJldHVybiBsaXZlLnNsaWNlKCk7XG4gICAgdGhpcy5ieVNsaWNlLnNldCh0aGlzLnNsaWNlWiwgbGl2ZS5zbGljZSgpKTtcbiAgICBjb25zdCBvdXQ6IFJlZ2lvbltdID0gW107XG4gICAgY29uc3QgenMgPSBBcnJheS5mcm9tKHRoaXMuYnlTbGljZS5rZXlzKCkpLnNvcnQoKGEsIGIpID0+IGEgLSBiKTtcbiAgICBmb3IgKGNvbnN0IHogb2YgenMpIHtcbiAgICAgIGZvciAoY29uc3QgciBvZiB0aGlzLmJ5U2xpY2UuZ2V0KHopIGFzIFJlZ2lvbltdKSBvdXQucHVzaCh3aXRoUmVnaW9uWihyLCB6KSk7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG4gIH1cblxuICAvKiogU2xpY2VzIHRvIHdyaXRlIG9uIGEgcGVyLXNsaWNlLWZpbGUgc2F2ZTogZXZlcnkgc2xpY2Ugd2l0aCByZWdpb25zIHBsdXNcbiAgICogIGV2ZXJ5IHNsaWNlIGxvYWRlZCBub24tZW1wdHkgKHJlLXdyaXR0ZW4gZW1wdHkgd2hlbiBjbGVhcmVkKS4gRW1wdHlcbiAgICogIG91dHNpZGUgc3RhY2sgbW9kZS4gKi9cbiAgc3RhY2tTYXZlU2xpY2VzKGxpdmU6IFJlZ2lvbltdKTogTWFwPG51bWJlciwgUmVnaW9uW10+IHtcbiAgICBjb25zdCBvdXQgPSBuZXcgTWFwPG51bWJlciwgUmVnaW9uW10+KCk7XG4gICAgaWYgKCF0aGlzLnN0YWNrKSByZXR1cm4gb3V0O1xuICAgIHRoaXMuYnlTbGljZS5zZXQodGhpcy5zbGljZVosIGxpdmUuc2xpY2UoKSk7XG4gICAgY29uc3QgenMgPSBuZXcgU2V0PG51bWJlcj4odGhpcy5pbml0aWFsTm9uRW1wdHkpO1xuICAgIGZvciAoY29uc3QgW3osIHJlZ3NdIG9mIHRoaXMuYnlTbGljZSkgaWYgKHJlZ3MubGVuZ3RoKSB6cy5hZGQoeik7XG4gICAgZm9yIChjb25zdCB6IG9mIEFycmF5LmZyb20oenMpLnNvcnQoKGEsIGIpID0+IGEgLSBiKSkge1xuICAgICAgb3V0LnNldChcbiAgICAgICAgeixcbiAgICAgICAgKHRoaXMuYnlTbGljZS5nZXQoeikgPz8gW10pLm1hcCgocikgPT4gd2l0aFJlZ2lvbloociwgeikpLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbiAgfVxufVxuIl19
@@ -0,0 +1,82 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ /**
3
+ * Region selection, held by region *id* (stable across edits, reorders and
4
+ * delete/add cycles) and projected to array indices for the IRegionStore
5
+ * boundary. Changing the ids ({@link replace}, {@link retain}) is silent; the
6
+ * owner calls {@link sync} once the region array it projects onto is final,
7
+ * which prunes ids that no longer exist and emits {@link indices$} only when
8
+ * the index set changed.
9
+ */
10
+ export class RegionSelection {
11
+ constructor() {
12
+ this.selected = [];
13
+ this.indicesSubject = new BehaviorSubject([]);
14
+ /** The selected regions' current array indices (emits on change only). */
15
+ this.indices$ = this.indicesSubject.asObservable();
16
+ }
17
+ /** The selected indices as last projected by {@link sync}. */
18
+ get indices() {
19
+ return this.indicesSubject.value;
20
+ }
21
+ /** The selected ids, in selection order. */
22
+ get ids() {
23
+ return this.selected;
24
+ }
25
+ /** Replace the selected ids (no emit until {@link sync}). */
26
+ replace(ids) {
27
+ this.selected = ids.slice();
28
+ }
29
+ /** Keep only the ids `keep` accepts (no emit until {@link sync}). */
30
+ retain(keep) {
31
+ this.selected = this.selected.filter(keep);
32
+ }
33
+ /**
34
+ * Select by array index into `regions`: invalid and duplicate indices are
35
+ * dropped, the given order is kept. Projects and emits.
36
+ */
37
+ selectIndices(indices, regions) {
38
+ const ids = [];
39
+ const seen = new Set();
40
+ for (const i of indices || []) {
41
+ if (!Number.isFinite(i) || i < 0 || i >= regions.length)
42
+ continue;
43
+ const id = regions[i].id;
44
+ if (!seen.has(id)) {
45
+ seen.add(id);
46
+ ids.push(id);
47
+ }
48
+ }
49
+ this.selected = ids;
50
+ this.sync(regions);
51
+ }
52
+ /** Project the selected ids onto `regions`, pruning ids it no longer holds,
53
+ * and emit if the index set changed. */
54
+ sync(regions) {
55
+ const indexOf = new Map();
56
+ regions.forEach((r, i) => {
57
+ if (!indexOf.has(r.id))
58
+ indexOf.set(r.id, i);
59
+ });
60
+ const indices = [];
61
+ const live = [];
62
+ for (const id of this.selected) {
63
+ const idx = indexOf.get(id);
64
+ if (idx !== undefined) {
65
+ indices.push(idx);
66
+ live.push(id);
67
+ }
68
+ }
69
+ this.selected = live;
70
+ if (!sameIndices(this.indicesSubject.value, indices))
71
+ this.indicesSubject.next(indices);
72
+ }
73
+ }
74
+ function sameIndices(a, b) {
75
+ if (a.length !== b.length)
76
+ return false;
77
+ for (let i = 0; i < a.length; i++)
78
+ if (a[i] !== b[i])
79
+ return false;
80
+ return true;
81
+ }
82
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLXNlbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc3RvcmUvcmVnaW9uLXNlbGVjdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZUFBZSxFQUFjLE1BQU0sTUFBTSxDQUFDO0FBT25EOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQUE1QjtRQUNVLGFBQVEsR0FBYSxFQUFFLENBQUM7UUFDZixtQkFBYyxHQUFHLElBQUksZUFBZSxDQUFXLEVBQUUsQ0FBQyxDQUFDO1FBRXBFLDBFQUEwRTtRQUNqRSxhQUFRLEdBQXlCLElBQUksQ0FBQyxjQUFjLENBQUMsWUFBWSxFQUFFLENBQUM7SUE0RC9FLENBQUM7SUExREMsOERBQThEO0lBQzlELElBQUksT0FBTztRQUNULE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUM7SUFDbkMsQ0FBQztJQUVELDRDQUE0QztJQUM1QyxJQUFJLEdBQUc7UUFDTCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDdkIsQ0FBQztJQUVELDZEQUE2RDtJQUM3RCxPQUFPLENBQUMsR0FBYTtRQUNuQixJQUFJLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRUQscUVBQXFFO0lBQ3JFLE1BQU0sQ0FBQyxJQUE2QjtRQUNsQyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxhQUFhLENBQUMsT0FBaUIsRUFBRSxPQUF5QjtRQUN4RCxNQUFNLEdBQUcsR0FBYSxFQUFFLENBQUM7UUFDekIsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUMvQixLQUFLLE1BQU0sQ0FBQyxJQUFJLE9BQU8sSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUM5QixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxPQUFPLENBQUMsTUFBTTtnQkFBRSxTQUFTO1lBQ2xFLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDbEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDYixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2YsQ0FBQztRQUNILENBQUM7UUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3JCLENBQUM7SUFFRDs2Q0FDeUM7SUFDekMsSUFBSSxDQUFDLE9BQXlCO1FBQzVCLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO1FBQzFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDdkIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDL0MsQ0FBQyxDQUFDLENBQUM7UUFDSCxNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7UUFDN0IsTUFBTSxJQUFJLEdBQWEsRUFBRSxDQUFDO1FBQzFCLEtBQUssTUFBTSxFQUFFLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQy9CLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDNUIsSUFBSSxHQUFHLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ3RCLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2xCLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDaEIsQ0FBQztRQUNILENBQUM7UUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztRQUNyQixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQztZQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFGLENBQUM7Q0FDRjtBQUVELFNBQVMsV0FBVyxDQUFDLENBQVcsRUFBRSxDQUFXO0lBQzNDLElBQUksQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsTUFBTTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3hDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRTtRQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFBRSxPQUFPLEtBQUssQ0FBQztJQUNuRSxPQUFPLElBQUksQ0FBQztBQUNkLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcblxuLyoqIFRoZSBwYXJ0IG9mIGEgcmVnaW9uIHRoZSBzZWxlY3Rpb24gcmVhZHM6IGl0cyBzdGFibGUgaWQuICovXG5pbnRlcmZhY2UgSGFzSWQge1xuICBpZDogbnVtYmVyO1xufVxuXG4vKipcbiAqIFJlZ2lvbiBzZWxlY3Rpb24sIGhlbGQgYnkgcmVnaW9uICppZCogKHN0YWJsZSBhY3Jvc3MgZWRpdHMsIHJlb3JkZXJzIGFuZFxuICogZGVsZXRlL2FkZCBjeWNsZXMpIGFuZCBwcm9qZWN0ZWQgdG8gYXJyYXkgaW5kaWNlcyBmb3IgdGhlIElSZWdpb25TdG9yZVxuICogYm91bmRhcnkuIENoYW5naW5nIHRoZSBpZHMgKHtAbGluayByZXBsYWNlfSwge0BsaW5rIHJldGFpbn0pIGlzIHNpbGVudDsgdGhlXG4gKiBvd25lciBjYWxscyB7QGxpbmsgc3luY30gb25jZSB0aGUgcmVnaW9uIGFycmF5IGl0IHByb2plY3RzIG9udG8gaXMgZmluYWwsXG4gKiB3aGljaCBwcnVuZXMgaWRzIHRoYXQgbm8gbG9uZ2VyIGV4aXN0IGFuZCBlbWl0cyB7QGxpbmsgaW5kaWNlcyR9IG9ubHkgd2hlblxuICogdGhlIGluZGV4IHNldCBjaGFuZ2VkLlxuICovXG5leHBvcnQgY2xhc3MgUmVnaW9uU2VsZWN0aW9uIHtcbiAgcHJpdmF0ZSBzZWxlY3RlZDogbnVtYmVyW10gPSBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmRpY2VzU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyW10+KFtdKTtcblxuICAvKiogVGhlIHNlbGVjdGVkIHJlZ2lvbnMnIGN1cnJlbnQgYXJyYXkgaW5kaWNlcyAoZW1pdHMgb24gY2hhbmdlIG9ubHkpLiAqL1xuICByZWFkb25seSBpbmRpY2VzJDogT2JzZXJ2YWJsZTxudW1iZXJbXT4gPSB0aGlzLmluZGljZXNTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuXG4gIC8qKiBUaGUgc2VsZWN0ZWQgaW5kaWNlcyBhcyBsYXN0IHByb2plY3RlZCBieSB7QGxpbmsgc3luY30uICovXG4gIGdldCBpbmRpY2VzKCk6IG51bWJlcltdIHtcbiAgICByZXR1cm4gdGhpcy5pbmRpY2VzU3ViamVjdC52YWx1ZTtcbiAgfVxuXG4gIC8qKiBUaGUgc2VsZWN0ZWQgaWRzLCBpbiBzZWxlY3Rpb24gb3JkZXIuICovXG4gIGdldCBpZHMoKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGVkO1xuICB9XG5cbiAgLyoqIFJlcGxhY2UgdGhlIHNlbGVjdGVkIGlkcyAobm8gZW1pdCB1bnRpbCB7QGxpbmsgc3luY30pLiAqL1xuICByZXBsYWNlKGlkczogbnVtYmVyW10pOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGVkID0gaWRzLnNsaWNlKCk7XG4gIH1cblxuICAvKiogS2VlcCBvbmx5IHRoZSBpZHMgYGtlZXBgIGFjY2VwdHMgKG5vIGVtaXQgdW50aWwge0BsaW5rIHN5bmN9KS4gKi9cbiAgcmV0YWluKGtlZXA6IChpZDogbnVtYmVyKSA9PiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZCA9IHRoaXMuc2VsZWN0ZWQuZmlsdGVyKGtlZXApO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlbGVjdCBieSBhcnJheSBpbmRleCBpbnRvIGByZWdpb25zYDogaW52YWxpZCBhbmQgZHVwbGljYXRlIGluZGljZXMgYXJlXG4gICAqIGRyb3BwZWQsIHRoZSBnaXZlbiBvcmRlciBpcyBrZXB0LiBQcm9qZWN0cyBhbmQgZW1pdHMuXG4gICAqL1xuICBzZWxlY3RJbmRpY2VzKGluZGljZXM6IG51bWJlcltdLCByZWdpb25zOiByZWFkb25seSBIYXNJZFtdKTogdm9pZCB7XG4gICAgY29uc3QgaWRzOiBudW1iZXJbXSA9IFtdO1xuICAgIGNvbnN0IHNlZW4gPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgICBmb3IgKGNvbnN0IGkgb2YgaW5kaWNlcyB8fCBbXSkge1xuICAgICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUoaSkgfHwgaSA8IDAgfHwgaSA+PSByZWdpb25zLmxlbmd0aCkgY29udGludWU7XG4gICAgICBjb25zdCBpZCA9IHJlZ2lvbnNbaV0uaWQ7XG4gICAgICBpZiAoIXNlZW4uaGFzKGlkKSkge1xuICAgICAgICBzZWVuLmFkZChpZCk7XG4gICAgICAgIGlkcy5wdXNoKGlkKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5zZWxlY3RlZCA9IGlkcztcbiAgICB0aGlzLnN5bmMocmVnaW9ucyk7XG4gIH1cblxuICAvKiogUHJvamVjdCB0aGUgc2VsZWN0ZWQgaWRzIG9udG8gYHJlZ2lvbnNgLCBwcnVuaW5nIGlkcyBpdCBubyBsb25nZXIgaG9sZHMsXG4gICAqICBhbmQgZW1pdCBpZiB0aGUgaW5kZXggc2V0IGNoYW5nZWQuICovXG4gIHN5bmMocmVnaW9uczogcmVhZG9ubHkgSGFzSWRbXSk6IHZvaWQge1xuICAgIGNvbnN0IGluZGV4T2YgPSBuZXcgTWFwPG51bWJlciwgbnVtYmVyPigpO1xuICAgIHJlZ2lvbnMuZm9yRWFjaCgociwgaSkgPT4ge1xuICAgICAgaWYgKCFpbmRleE9mLmhhcyhyLmlkKSkgaW5kZXhPZi5zZXQoci5pZCwgaSk7XG4gICAgfSk7XG4gICAgY29uc3QgaW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgICBjb25zdCBsaXZlOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgaWQgb2YgdGhpcy5zZWxlY3RlZCkge1xuICAgICAgY29uc3QgaWR4ID0gaW5kZXhPZi5nZXQoaWQpO1xuICAgICAgaWYgKGlkeCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGluZGljZXMucHVzaChpZHgpO1xuICAgICAgICBsaXZlLnB1c2goaWQpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLnNlbGVjdGVkID0gbGl2ZTtcbiAgICBpZiAoIXNhbWVJbmRpY2VzKHRoaXMuaW5kaWNlc1N1YmplY3QudmFsdWUsIGluZGljZXMpKSB0aGlzLmluZGljZXNTdWJqZWN0Lm5leHQoaW5kaWNlcyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gc2FtZUluZGljZXMoYTogbnVtYmVyW10sIGI6IG51bWJlcltdKTogYm9vbGVhbiB7XG4gIGlmIChhLmxlbmd0aCAhPT0gYi5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSBpZiAoYVtpXSAhPT0gYltpXSkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gdHJ1ZTtcbn1cbiJdfQ==