@jbrowse/plugin-linear-genome-view 4.3.0 → 5.0.0-beta.10

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 (363) hide show
  1. package/esm/FeatureTrack/configSchema.d.ts +202 -71
  2. package/esm/FeatureTrack/configSchema.js +47 -1
  3. package/esm/FeatureTrack/index.js +1 -1
  4. package/esm/LaunchLinearGenomeView/index.d.ts +14 -0
  5. package/esm/LaunchLinearGenomeView/index.js +6 -12
  6. package/esm/LinearGenomeView/afterAttach.d.ts +20 -2
  7. package/esm/LinearGenomeView/afterAttach.js +265 -120
  8. package/esm/LinearGenomeView/components/CenterLine.d.ts +1 -1
  9. package/esm/LinearGenomeView/components/CenterLine.js +20 -9
  10. package/esm/LinearGenomeView/components/ConnectedHoverHighlight.d.ts +7 -0
  11. package/esm/LinearGenomeView/components/ConnectedHoverHighlight.js +22 -0
  12. package/esm/LinearGenomeView/components/CrisprGuidePanel.d.ts +3 -0
  13. package/esm/LinearGenomeView/components/CrisprGuidePanel.js +142 -0
  14. package/esm/LinearGenomeView/components/Cytobands.d.ts +6 -6
  15. package/esm/LinearGenomeView/components/Cytobands.js +76 -53
  16. package/esm/LinearGenomeView/components/ExportSvgDialog.d.ts +8 -3
  17. package/esm/LinearGenomeView/components/ExportSvgDialog.js +15 -67
  18. package/esm/LinearGenomeView/components/GetSequenceDialog.d.ts +5 -9
  19. package/esm/LinearGenomeView/components/GetSequenceDialog.js +84 -88
  20. package/esm/LinearGenomeView/components/Gridlines.d.ts +1 -1
  21. package/esm/LinearGenomeView/components/Gridlines.js +29 -58
  22. package/esm/LinearGenomeView/components/Header.d.ts +1 -1
  23. package/esm/LinearGenomeView/components/Header.js +42 -16
  24. package/esm/LinearGenomeView/components/HeaderClearHighlightButton.d.ts +21 -0
  25. package/esm/LinearGenomeView/components/HeaderClearHighlightButton.js +35 -0
  26. package/esm/LinearGenomeView/components/HeaderPanControls.d.ts +3 -2
  27. package/esm/LinearGenomeView/components/HeaderPanControls.js +18 -8
  28. package/esm/LinearGenomeView/components/HeaderRegionWidth.d.ts +1 -1
  29. package/esm/LinearGenomeView/components/HeaderRegionWidth.js +9 -6
  30. package/esm/LinearGenomeView/components/HeaderSearchBoxRow.d.ts +6 -0
  31. package/esm/LinearGenomeView/components/HeaderSearchBoxRow.js +27 -0
  32. package/esm/LinearGenomeView/components/HeaderSearchBoxes.d.ts +5 -0
  33. package/esm/LinearGenomeView/components/HeaderSearchBoxes.js +28 -0
  34. package/esm/LinearGenomeView/components/HeaderTrackSelectorButton.d.ts +3 -2
  35. package/esm/LinearGenomeView/components/HeaderTrackSelectorButton.js +11 -4
  36. package/esm/LinearGenomeView/components/HeaderZoomControls.d.ts +3 -2
  37. package/esm/LinearGenomeView/components/HeaderZoomControls.js +38 -52
  38. package/esm/LinearGenomeView/components/Highlight.d.ts +1 -1
  39. package/esm/LinearGenomeView/components/Highlight.js +21 -25
  40. package/esm/LinearGenomeView/components/HighlightBand.d.ts +3 -2
  41. package/esm/LinearGenomeView/components/HighlightBand.js +25 -8
  42. package/esm/LinearGenomeView/components/HighlightChip.d.ts +8 -0
  43. package/esm/LinearGenomeView/components/HighlightChip.js +13 -0
  44. package/esm/LinearGenomeView/components/HoverPositionHighlight.d.ts +12 -0
  45. package/esm/LinearGenomeView/components/HoverPositionHighlight.js +25 -0
  46. package/esm/LinearGenomeView/components/ImportForm.d.ts +3 -4
  47. package/esm/LinearGenomeView/components/ImportForm.js +95 -61
  48. package/esm/LinearGenomeView/components/LinearGenomeView.d.ts +1 -1
  49. package/esm/LinearGenomeView/components/LinearGenomeView.js +7 -6
  50. package/esm/LinearGenomeView/components/LinearGenomeViewContainer.d.ts +1 -1
  51. package/esm/LinearGenomeView/components/LinearGenomeViewContainer.js +88 -30
  52. package/esm/LinearGenomeView/components/MiniControls.d.ts +1 -1
  53. package/esm/LinearGenomeView/components/MiniControls.js +14 -10
  54. package/esm/LinearGenomeView/components/MotifListPanel.d.ts +3 -0
  55. package/esm/LinearGenomeView/components/MotifListPanel.js +59 -0
  56. package/esm/LinearGenomeView/components/NavigationAnnouncer.d.ts +32 -0
  57. package/esm/LinearGenomeView/components/NavigationAnnouncer.js +51 -0
  58. package/esm/LinearGenomeView/components/NoTracksActiveButton.d.ts +1 -1
  59. package/esm/LinearGenomeView/components/NoTracksActiveButton.js +1 -1
  60. package/esm/LinearGenomeView/components/OverviewHighlight.d.ts +2 -4
  61. package/esm/LinearGenomeView/components/OverviewHighlight.js +23 -44
  62. package/esm/LinearGenomeView/components/OverviewHighlightBand.d.ts +9 -0
  63. package/esm/LinearGenomeView/components/OverviewHighlightBand.js +25 -0
  64. package/esm/LinearGenomeView/components/OverviewRubberband.d.ts +3 -3
  65. package/esm/LinearGenomeView/components/OverviewRubberband.js +29 -67
  66. package/esm/LinearGenomeView/components/OverviewRubberbandHoverTooltip.d.ts +4 -5
  67. package/esm/LinearGenomeView/components/OverviewRubberbandHoverTooltip.js +13 -20
  68. package/esm/LinearGenomeView/components/OverviewScalebar.d.ts +3 -2
  69. package/esm/LinearGenomeView/components/OverviewScalebar.js +87 -83
  70. package/esm/LinearGenomeView/components/OverviewScalebarPolygon.d.ts +19 -5
  71. package/esm/LinearGenomeView/components/OverviewScalebarPolygon.js +57 -32
  72. package/esm/LinearGenomeView/components/OverviewScalebarTickLabels.d.ts +4 -5
  73. package/esm/LinearGenomeView/components/OverviewScalebarTickLabels.js +16 -18
  74. package/esm/LinearGenomeView/components/PaddingBlocks.d.ts +7 -0
  75. package/esm/LinearGenomeView/components/PaddingBlocks.js +56 -0
  76. package/esm/LinearGenomeView/components/RangeSelectOverlay.d.ts +9 -0
  77. package/esm/LinearGenomeView/components/RangeSelectOverlay.js +19 -0
  78. package/esm/LinearGenomeView/components/RegionWidthEditorDialog.d.ts +2 -3
  79. package/esm/LinearGenomeView/components/RegionWidthEditorDialog.js +19 -26
  80. package/esm/LinearGenomeView/components/ResizeAllTracksHandle.d.ts +5 -0
  81. package/esm/LinearGenomeView/components/ResizeAllTracksHandle.js +71 -0
  82. package/esm/LinearGenomeView/components/Rubberband.d.ts +2 -3
  83. package/esm/LinearGenomeView/components/Rubberband.js +15 -17
  84. package/esm/LinearGenomeView/components/SVGHighlightBand.d.ts +10 -0
  85. package/esm/LinearGenomeView/components/SVGHighlightBand.js +8 -0
  86. package/esm/LinearGenomeView/components/Scalebar.d.ts +2 -6
  87. package/esm/LinearGenomeView/components/Scalebar.js +20 -22
  88. package/esm/LinearGenomeView/components/ScalebarCoordinateLabels.d.ts +1 -1
  89. package/esm/LinearGenomeView/components/ScalebarCoordinateLabels.js +54 -35
  90. package/esm/LinearGenomeView/components/ScalebarRefNameLabels.d.ts +1 -1
  91. package/esm/LinearGenomeView/components/ScalebarRefNameLabels.js +157 -126
  92. package/esm/LinearGenomeView/components/SearchBox.d.ts +22 -2
  93. package/esm/LinearGenomeView/components/SearchBox.js +61 -68
  94. package/esm/LinearGenomeView/components/SearchPanelForm.d.ts +9 -0
  95. package/esm/LinearGenomeView/components/SearchPanelForm.js +18 -0
  96. package/esm/LinearGenomeView/components/SearchResultsDialog.d.ts +5 -4
  97. package/esm/LinearGenomeView/components/SearchResultsDialog.js +6 -8
  98. package/esm/LinearGenomeView/components/SearchResultsTable.d.ts +5 -3
  99. package/esm/LinearGenomeView/components/SearchResultsTable.js +31 -56
  100. package/esm/LinearGenomeView/components/SequenceFeatureHoverHighlight.d.ts +5 -0
  101. package/esm/LinearGenomeView/components/SequenceFeatureHoverHighlight.js +37 -0
  102. package/esm/LinearGenomeView/components/SequenceFeatureHoverHighlightExtension.d.ts +2 -0
  103. package/esm/LinearGenomeView/components/SequenceFeatureHoverHighlightExtension.js +5 -0
  104. package/esm/LinearGenomeView/components/SequencePatternPanel.d.ts +3 -0
  105. package/esm/LinearGenomeView/components/SequencePatternPanel.js +42 -0
  106. package/esm/LinearGenomeView/components/SequenceSearchDialog.d.ts +3 -5
  107. package/esm/LinearGenomeView/components/SequenceSearchDialog.js +31 -53
  108. package/esm/LinearGenomeView/components/StrandCheckboxes.d.ts +8 -0
  109. package/esm/LinearGenomeView/components/StrandCheckboxes.js +13 -0
  110. package/esm/LinearGenomeView/components/TrackContainer.d.ts +1 -1
  111. package/esm/LinearGenomeView/components/TrackContainer.js +136 -38
  112. package/esm/LinearGenomeView/components/TrackLabel.d.ts +2 -3
  113. package/esm/LinearGenomeView/components/TrackLabel.js +20 -26
  114. package/esm/LinearGenomeView/components/TrackLabelButtons.d.ts +7 -0
  115. package/esm/LinearGenomeView/components/TrackLabelButtons.js +33 -0
  116. package/esm/LinearGenomeView/components/TrackLabelDragHandle.d.ts +2 -5
  117. package/esm/LinearGenomeView/components/TrackLabelDragHandle.js +6 -2
  118. package/esm/LinearGenomeView/components/TrackLabelMenu.d.ts +1 -1
  119. package/esm/LinearGenomeView/components/TrackLabelMenu.js +35 -87
  120. package/esm/LinearGenomeView/components/TrackLabelRefNameWarning.d.ts +22 -0
  121. package/esm/LinearGenomeView/components/TrackLabelRefNameWarning.js +46 -0
  122. package/esm/LinearGenomeView/components/TrackRenderingContainer.d.ts +5 -2
  123. package/esm/LinearGenomeView/components/TrackRenderingContainer.js +66 -24
  124. package/esm/LinearGenomeView/components/TracksContainer.d.ts +1 -1
  125. package/esm/LinearGenomeView/components/TracksContainer.js +53 -32
  126. package/esm/LinearGenomeView/components/VerticalGuide.d.ts +2 -3
  127. package/esm/LinearGenomeView/components/VerticalGuide.js +6 -26
  128. package/esm/LinearGenomeView/components/ZoomButton.d.ts +7 -0
  129. package/esm/LinearGenomeView/components/ZoomButton.js +27 -0
  130. package/esm/LinearGenomeView/components/ZoomTransform.d.ts +9 -0
  131. package/esm/LinearGenomeView/components/ZoomTransform.js +37 -0
  132. package/esm/LinearGenomeView/components/defaultMotifs.d.ts +1 -0
  133. package/esm/LinearGenomeView/components/defaultMotifs.js +22 -0
  134. package/esm/LinearGenomeView/components/fetchSequence.d.ts +6 -8
  135. package/esm/LinearGenomeView/components/fetchSequence.js +17 -9
  136. package/esm/LinearGenomeView/components/recentLocationsMenu.d.ts +15 -0
  137. package/esm/LinearGenomeView/components/recentLocationsMenu.js +46 -0
  138. package/esm/LinearGenomeView/components/searchModes.d.ts +13 -0
  139. package/esm/LinearGenomeView/components/searchModes.js +22 -0
  140. package/esm/LinearGenomeView/components/trackLabelMenuItems.d.ts +7 -0
  141. package/esm/LinearGenomeView/components/trackLabelMenuItems.js +67 -0
  142. package/esm/LinearGenomeView/components/useRangeSelect.d.ts +9 -67
  143. package/esm/LinearGenomeView/components/useRangeSelect.js +54 -102
  144. package/esm/LinearGenomeView/components/useSearchBoxPrefs.d.ts +26 -0
  145. package/esm/LinearGenomeView/components/useSearchBoxPrefs.js +58 -0
  146. package/esm/LinearGenomeView/components/useSideScroll.d.ts +17 -3
  147. package/esm/LinearGenomeView/components/useSideScroll.js +163 -45
  148. package/esm/LinearGenomeView/components/util.d.ts +24 -6
  149. package/esm/LinearGenomeView/components/util.js +28 -5
  150. package/esm/LinearGenomeView/consts.d.ts +9 -2
  151. package/esm/LinearGenomeView/consts.js +20 -2
  152. package/esm/LinearGenomeView/containingLgv.d.ts +21 -0
  153. package/esm/LinearGenomeView/containingLgv.js +23 -0
  154. package/esm/LinearGenomeView/flyTo.d.ts +38 -0
  155. package/esm/LinearGenomeView/flyTo.js +135 -0
  156. package/esm/LinearGenomeView/headerFit.d.ts +29 -0
  157. package/esm/LinearGenomeView/headerFit.js +72 -0
  158. package/esm/LinearGenomeView/index.d.ts +28 -3
  159. package/esm/LinearGenomeView/index.js +13 -7
  160. package/esm/LinearGenomeView/keyboardHandler.d.ts +9 -0
  161. package/esm/LinearGenomeView/keyboardHandler.js +25 -1
  162. package/esm/LinearGenomeView/launchKeys.d.ts +2 -0
  163. package/esm/LinearGenomeView/launchKeys.js +27 -0
  164. package/esm/LinearGenomeView/lazyDialogs.d.ts +8 -14
  165. package/esm/LinearGenomeView/lazyDialogs.js +4 -3
  166. package/esm/LinearGenomeView/linkedViewSync.d.ts +12 -0
  167. package/esm/LinearGenomeView/linkedViewSync.js +36 -0
  168. package/esm/LinearGenomeView/menuItems.d.ts +25 -2
  169. package/esm/LinearGenomeView/menuItems.js +306 -179
  170. package/esm/LinearGenomeView/model.d.ts +3363 -164
  171. package/esm/LinearGenomeView/model.js +2548 -565
  172. package/esm/LinearGenomeView/sharedScaleContainer.d.ts +18 -0
  173. package/esm/LinearGenomeView/sharedScaleContainer.js +17 -0
  174. package/esm/LinearGenomeView/showRegionsWithUndo.d.ts +35 -0
  175. package/esm/LinearGenomeView/showRegionsWithUndo.js +50 -0
  176. package/esm/LinearGenomeView/stickyChrome.d.ts +15 -0
  177. package/esm/LinearGenomeView/stickyChrome.js +26 -0
  178. package/esm/LinearGenomeView/svgcomponents/SVGGridlines.d.ts +1 -1
  179. package/esm/LinearGenomeView/svgcomponents/SVGGridlines.js +17 -18
  180. package/esm/LinearGenomeView/svgcomponents/SVGHeader.d.ts +5 -3
  181. package/esm/LinearGenomeView/svgcomponents/SVGHeader.js +34 -35
  182. package/esm/LinearGenomeView/svgcomponents/SVGHighlights.d.ts +5 -0
  183. package/esm/LinearGenomeView/svgcomponents/SVGHighlights.js +26 -0
  184. package/esm/LinearGenomeView/svgcomponents/SVGHighlightsOverlay.d.ts +5 -0
  185. package/esm/LinearGenomeView/svgcomponents/SVGHighlightsOverlay.js +13 -0
  186. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.d.ts +1 -3
  187. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +73 -41
  188. package/esm/LinearGenomeView/svgcomponents/SVGRegionSeparators.d.ts +1 -1
  189. package/esm/LinearGenomeView/svgcomponents/SVGRegionSeparators.js +20 -3
  190. package/esm/LinearGenomeView/svgcomponents/SVGRowHeader.d.ts +8 -0
  191. package/esm/LinearGenomeView/svgcomponents/SVGRowHeader.js +36 -0
  192. package/esm/LinearGenomeView/svgcomponents/SVGRuler.d.ts +3 -3
  193. package/esm/LinearGenomeView/svgcomponents/SVGRuler.js +66 -39
  194. package/esm/LinearGenomeView/svgcomponents/SVGScalebar.d.ts +1 -1
  195. package/esm/LinearGenomeView/svgcomponents/SVGScalebar.js +9 -7
  196. package/esm/LinearGenomeView/svgcomponents/SVGStackedRow.d.ts +27 -0
  197. package/esm/LinearGenomeView/svgcomponents/SVGStackedRow.js +12 -0
  198. package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.d.ts +5 -3
  199. package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.js +54 -9
  200. package/esm/LinearGenomeView/svgcomponents/SVGTracks.d.ts +9 -15
  201. package/esm/LinearGenomeView/svgcomponents/SVGTracks.js +17 -21
  202. package/esm/LinearGenomeView/svgcomponents/SVGView.d.ts +18 -0
  203. package/esm/LinearGenomeView/svgcomponents/SVGView.js +13 -0
  204. package/esm/LinearGenomeView/svgcomponents/figureContract.d.ts +45 -0
  205. package/esm/LinearGenomeView/svgcomponents/figureContract.js +130 -0
  206. package/esm/LinearGenomeView/svgcomponents/renderViewTracks.d.ts +76 -0
  207. package/esm/LinearGenomeView/svgcomponents/renderViewTracks.js +66 -0
  208. package/esm/LinearGenomeView/svgcomponents/useViewSvgFigure.d.ts +70 -0
  209. package/esm/LinearGenomeView/svgcomponents/useViewSvgFigure.js +245 -0
  210. package/esm/LinearGenomeView/svgcomponents/util.d.ts +96 -5
  211. package/esm/LinearGenomeView/svgcomponents/util.js +242 -4
  212. package/esm/LinearGenomeView/types.d.ts +20 -37
  213. package/esm/LinearGenomeView/types.js +1 -0
  214. package/esm/LinearGenomeView/util.d.ts +347 -12
  215. package/esm/LinearGenomeView/util.js +577 -62
  216. package/esm/MultiLevelRubberband/MultiLevelRubberband.d.ts +6 -0
  217. package/esm/MultiLevelRubberband/MultiLevelRubberband.js +40 -0
  218. package/esm/MultiLevelRubberband/index.d.ts +4 -0
  219. package/esm/MultiLevelRubberband/index.js +3 -0
  220. package/esm/MultiLevelRubberband/menuItems.d.ts +34 -0
  221. package/esm/MultiLevelRubberband/menuItems.js +52 -0
  222. package/esm/MultiLevelRubberband/rowLabel.d.ts +22 -0
  223. package/esm/MultiLevelRubberband/rowLabel.js +27 -0
  224. package/esm/MultiLevelRubberband/types.d.ts +7 -0
  225. package/esm/MultiLevelRubberband/useRangeSelect.d.ts +25 -0
  226. package/esm/MultiLevelRubberband/useRangeSelect.js +120 -0
  227. package/esm/displayKitTests/perRegionTestEnv.d.ts +1391 -0
  228. package/esm/displayKitTests/perRegionTestEnv.js +142 -0
  229. package/esm/index.d.ts +50 -1245
  230. package/esm/index.js +88 -33
  231. package/esm/searchUtils.d.ts +62 -12
  232. package/esm/searchUtils.js +335 -48
  233. package/esm/shared/RubberbandSpan.d.ts +15 -0
  234. package/esm/shared/RubberbandSpan.js +34 -0
  235. package/esm/shared/coordLabels.d.ts +47 -0
  236. package/esm/shared/coordLabels.js +133 -0
  237. package/esm/shared/useWindowDrag.d.ts +18 -0
  238. package/esm/shared/useWindowDrag.js +45 -0
  239. package/package.json +18 -19
  240. package/esm/BaseLinearDisplay/SVGLegend.d.ts +0 -6
  241. package/esm/BaseLinearDisplay/SVGLegend.js +0 -17
  242. package/esm/BaseLinearDisplay/calculateSvgLegendWidth.d.ts +0 -2
  243. package/esm/BaseLinearDisplay/calculateSvgLegendWidth.js +0 -11
  244. package/esm/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +0 -8
  245. package/esm/BaseLinearDisplay/components/BaseLinearDisplay.js +0 -53
  246. package/esm/BaseLinearDisplay/components/Block.d.ts +0 -14
  247. package/esm/BaseLinearDisplay/components/Block.js +0 -45
  248. package/esm/BaseLinearDisplay/components/BlockErrorMessage.d.ts +0 -7
  249. package/esm/BaseLinearDisplay/components/BlockErrorMessage.js +0 -22
  250. package/esm/BaseLinearDisplay/components/BlockMsg.d.ts +0 -6
  251. package/esm/BaseLinearDisplay/components/BlockMsg.js +0 -26
  252. package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/CollapseIntronsDialog.d.ts +0 -9
  253. package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/CollapseIntronsDialog.js +0 -42
  254. package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/TranscriptTable.d.ts +0 -11
  255. package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/TranscriptTable.js +0 -40
  256. package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/util.d.ts +0 -19
  257. package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/util.js +0 -45
  258. package/esm/BaseLinearDisplay/components/FloatingLabels.d.ts +0 -5
  259. package/esm/BaseLinearDisplay/components/FloatingLabels.js +0 -75
  260. package/esm/BaseLinearDisplay/components/FloatingLegend.d.ts +0 -8
  261. package/esm/BaseLinearDisplay/components/FloatingLegend.js +0 -43
  262. package/esm/BaseLinearDisplay/components/LinearBlocks.d.ts +0 -5
  263. package/esm/BaseLinearDisplay/components/LinearBlocks.js +0 -23
  264. package/esm/BaseLinearDisplay/components/LoadingOverlay.d.ts +0 -5
  265. package/esm/BaseLinearDisplay/components/LoadingOverlay.js +0 -49
  266. package/esm/BaseLinearDisplay/components/MaxHeightReachedIndicator.d.ts +0 -4
  267. package/esm/BaseLinearDisplay/components/MaxHeightReachedIndicator.js +0 -26
  268. package/esm/BaseLinearDisplay/components/MenuPage.d.ts +0 -8
  269. package/esm/BaseLinearDisplay/components/MenuPage.js +0 -24
  270. package/esm/BaseLinearDisplay/components/NonBlockCanvasDisplayComponent.d.ts +0 -21
  271. package/esm/BaseLinearDisplay/components/NonBlockCanvasDisplayComponent.js +0 -52
  272. package/esm/BaseLinearDisplay/components/RenderedBlocks.d.ts +0 -12
  273. package/esm/BaseLinearDisplay/components/RenderedBlocks.js +0 -22
  274. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.d.ts +0 -12
  275. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +0 -18
  276. package/esm/BaseLinearDisplay/components/TooLargeMessage.d.ts +0 -10
  277. package/esm/BaseLinearDisplay/components/TooLargeMessage.js +0 -20
  278. package/esm/BaseLinearDisplay/components/Tooltip.d.ts +0 -13
  279. package/esm/BaseLinearDisplay/components/Tooltip.js +0 -22
  280. package/esm/BaseLinearDisplay/components/types.d.ts +0 -1
  281. package/esm/BaseLinearDisplay/components/util.d.ts +0 -21
  282. package/esm/BaseLinearDisplay/components/util.js +0 -107
  283. package/esm/BaseLinearDisplay/index.d.ts +0 -17
  284. package/esm/BaseLinearDisplay/index.js +0 -13
  285. package/esm/BaseLinearDisplay/model.d.ts +0 -1197
  286. package/esm/BaseLinearDisplay/model.js +0 -432
  287. package/esm/BaseLinearDisplay/models/FeatureDensityMixin.d.ts +0 -32
  288. package/esm/BaseLinearDisplay/models/FeatureDensityMixin.js +0 -113
  289. package/esm/BaseLinearDisplay/models/NonBlockCanvasDisplayMixin.d.ts +0 -26
  290. package/esm/BaseLinearDisplay/models/NonBlockCanvasDisplayMixin.js +0 -57
  291. package/esm/BaseLinearDisplay/models/SvgFloatingLabels.d.ts +0 -8
  292. package/esm/BaseLinearDisplay/models/SvgFloatingLabels.js +0 -19
  293. package/esm/BaseLinearDisplay/models/TrackHeightMixin.d.ts +0 -11
  294. package/esm/BaseLinearDisplay/models/TrackHeightMixin.js +0 -31
  295. package/esm/BaseLinearDisplay/models/autorunFeatureDensityStats.d.ts +0 -2
  296. package/esm/BaseLinearDisplay/models/autorunFeatureDensityStats.js +0 -29
  297. package/esm/BaseLinearDisplay/models/configSchema.d.ts +0 -29
  298. package/esm/BaseLinearDisplay/models/configSchema.js +0 -33
  299. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +0 -98
  300. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +0 -242
  301. package/esm/BaseLinearDisplay/models/util.d.ts +0 -9
  302. package/esm/BaseLinearDisplay/models/util.js +0 -43
  303. package/esm/BaseLinearDisplay/renderSvg.d.ts +0 -3
  304. package/esm/BaseLinearDisplay/renderSvg.js +0 -63
  305. package/esm/BaseLinearDisplay/types.d.ts +0 -43
  306. package/esm/BaseLinearDisplay/types.js +0 -3
  307. package/esm/BaseLinearDisplay/util.d.ts +0 -16
  308. package/esm/BaseLinearDisplay/util.js +0 -71
  309. package/esm/BasicTrack/configSchema.d.ts +0 -85
  310. package/esm/BasicTrack/configSchema.js +0 -8
  311. package/esm/BasicTrack/index.d.ts +0 -2
  312. package/esm/BasicTrack/index.js +0 -12
  313. package/esm/LinearBareDisplay/configSchema.d.ts +0 -32
  314. package/esm/LinearBareDisplay/configSchema.js +0 -11
  315. package/esm/LinearBareDisplay/index.d.ts +0 -4
  316. package/esm/LinearBareDisplay/index.js +0 -20
  317. package/esm/LinearBareDisplay/model.d.ts +0 -1196
  318. package/esm/LinearBareDisplay/model.js +0 -32
  319. package/esm/LinearBasicDisplay/components/LinearBasicDisplayComponent.d.ts +0 -5
  320. package/esm/LinearBasicDisplay/components/LinearBasicDisplayComponent.js +0 -9
  321. package/esm/LinearBasicDisplay/configSchema.d.ts +0 -32
  322. package/esm/LinearBasicDisplay/configSchema.js +0 -11
  323. package/esm/LinearBasicDisplay/index.d.ts +0 -4
  324. package/esm/LinearBasicDisplay/index.js +0 -20
  325. package/esm/LinearBasicDisplay/model.d.ts +0 -1391
  326. package/esm/LinearBasicDisplay/model.js +0 -158
  327. package/esm/LinearFeatureDisplay/components/AddFiltersDialog.d.ts +0 -9
  328. package/esm/LinearFeatureDisplay/components/AddFiltersDialog.js +0 -58
  329. package/esm/LinearFeatureDisplay/components/SetMaxHeightDialog.d.ts +0 -8
  330. package/esm/LinearFeatureDisplay/components/SetMaxHeightDialog.js +0 -26
  331. package/esm/LinearFeatureDisplay/configSchema.d.ts +0 -32
  332. package/esm/LinearFeatureDisplay/configSchema.js +0 -11
  333. package/esm/LinearFeatureDisplay/index.d.ts +0 -3
  334. package/esm/LinearFeatureDisplay/index.js +0 -2
  335. package/esm/LinearFeatureDisplay/model.d.ts +0 -1443
  336. package/esm/LinearFeatureDisplay/model.js +0 -305
  337. package/esm/LinearGenomeView/SVGErrorBox.d.ts +0 -5
  338. package/esm/LinearGenomeView/SVGErrorBox.js +0 -4
  339. package/esm/LinearGenomeView/components/ImportFormRefNameAutocomplete.d.ts +0 -11
  340. package/esm/LinearGenomeView/components/ImportFormRefNameAutocomplete.js +0 -27
  341. package/esm/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.d.ts +0 -5
  342. package/esm/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.js +0 -13
  343. package/esm/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.d.ts +0 -3
  344. package/esm/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.js +0 -17
  345. package/esm/LinearGenomeView/components/RefNameAutocomplete/HelpDialog.d.ts +0 -3
  346. package/esm/LinearGenomeView/components/RefNameAutocomplete/HelpDialog.js +0 -8
  347. package/esm/LinearGenomeView/components/RefNameAutocomplete/index.d.ts +0 -16
  348. package/esm/LinearGenomeView/components/RefNameAutocomplete/index.js +0 -101
  349. package/esm/LinearGenomeView/components/RefNameAutocomplete/util.d.ts +0 -10
  350. package/esm/LinearGenomeView/components/RefNameAutocomplete/util.js +0 -45
  351. package/esm/LinearGenomeView/components/RubberbandSpan.d.ts +0 -15
  352. package/esm/LinearGenomeView/components/RubberbandSpan.js +0 -32
  353. package/esm/LinearGenomeView/components/RubberbandTooltip.d.ts +0 -5
  354. package/esm/LinearGenomeView/components/RubberbandTooltip.js +0 -17
  355. package/esm/LinearGenomeView/components/TrackLabelContainer.d.ts +0 -8
  356. package/esm/LinearGenomeView/components/TrackLabelContainer.js +0 -25
  357. package/esm/LinearGenomeView/components/useWheelScroll.d.ts +0 -7
  358. package/esm/LinearGenomeView/components/useWheelScroll.js +0 -69
  359. package/esm/LinearGenomeView/svgExportUtil.d.ts +0 -9
  360. package/esm/LinearGenomeView/svgExportUtil.js +0 -6
  361. package/esm/LinearGenomeView/svgcomponents/SVGBackground.d.ts +0 -5
  362. package/esm/LinearGenomeView/svgcomponents/SVGBackground.js +0 -7
  363. /package/esm/{BaseLinearDisplay/components → MultiLevelRubberband}/types.js +0 -0
@@ -1,4 +1,47 @@
1
- import { assembleLocString, parseLocString } from '@jbrowse/core/util';
1
+ import { UnknownRefNameError, assembleLocStrings, getTickDisplayStr, measureText, parseBpString, parseLocString, } from '@jbrowse/core/util';
2
+ import { bpOffsetInRegion } from '@jbrowse/core/util/Base1DUtils';
3
+ import { chooseGridPitch } from '@jbrowse/core/util/chooseGridPitch';
4
+ import { tickLabelsWorthDrawing } from '@jbrowse/core/util/tickLabels';
5
+ /**
6
+ * The stored viewport of a view showing `totalBp` of displayed regions fitted to
7
+ * `width` — the regions filling it edge to edge, and centered in it only where
8
+ * they are too narrow to fill it.
9
+ *
10
+ * **This is where the fit-to-width rule is written.** `fitAllRegions` takes its
11
+ * scale from here rather than restating it, so the two cannot drift; a second
12
+ * spelling of `max(minBpPerPx * width, totalBp)` reading `MIN_BP_PER_PX` where
13
+ * the action reads the `minBpPerPx` GETTER would agree only for as long as
14
+ * nothing overrides it.
15
+ *
16
+ * The reason it is a function at all is `windowStartBp`, which `fitAllRegions`
17
+ * does not need (it centers in pixels, through `scrollTo`, which also clamps).
18
+ * A caller building a view SNAPSHOT does: it has no model to call
19
+ * `fitAllRegions()` on, and naming `bpPerPx`/`offsetPx` instead is dropped
20
+ * whenever the snapshot also carries a `windowWidthBp` — which one copied off an
21
+ * existing view always does. plugin-canvas's collapsed-intron launch is that
22
+ * caller. A live view calls `fitAllRegions()`.
23
+ *
24
+ * `width` enters only through the zoom-in floor, which bites for a region set
25
+ * narrower than `width * minBpPerPx`; the window itself is in bp and needs no
26
+ * width, which is why a snapshot can carry it at all.
27
+ */
28
+ export function fitAllRegionsWindow(totalBp, width, minBpPerPx) {
29
+ const windowWidthBp = Math.max(minBpPerPx * width, totalBp);
30
+ // the same centering as getCenteredOffsetPx: half the width the content leaves
31
+ // unfilled, which is zero whenever the fit above is exact
32
+ return { windowWidthBp, windowStartBp: (totalBp - windowWidthBp) / 2 };
33
+ }
34
+ /**
35
+ * Expand a region by a grow factor, adding padding on each side.
36
+ *
37
+ * @param start - region start coordinate
38
+ * @param end - region end coordinate
39
+ * @param grow - multiplier for expansion (e.g., 0.2 adds 20% padding on each
40
+ * side)
41
+ * @param minBound - minimum bound to clamp start to (default 0)
42
+ * @param maxBound - maximum bound to clamp end to (default Infinity)
43
+ * @returns object with expanded start and end coordinates
44
+ */
2
45
  export function expandRegion(start, end, grow, minBound = 0, maxBound = Infinity) {
3
46
  const len = end - start;
4
47
  const margin = len * grow;
@@ -7,57 +50,513 @@ export function expandRegion(start, end, grow, minBound = 0, maxBound = Infinity
7
50
  end: Math.min(maxBound, end + margin),
8
51
  };
9
52
  }
10
- export function chooseGridPitch(scale, minMajorPitchPx, minMinorPitchPx) {
11
- scale = Math.abs(scale);
12
- const minMajorPitchBp = minMajorPitchPx * scale;
13
- const majorMagnitude = +minMajorPitchBp.toExponential().split(/e/i)[1];
14
- let majorPitch = 10 ** majorMagnitude;
15
- while (majorPitch < minMajorPitchBp) {
16
- majorPitch *= 2;
17
- if (majorPitch >= minMajorPitchBp) {
18
- break;
53
+ /**
54
+ * Generate tick positions for the overview scalebar. Anchors at the first neat
55
+ * majorPitch multiple strictly inside the block so ticks land on round numbers
56
+ * regardless of where the block starts/ends.
57
+ */
58
+ export function makeOverviewTicks(start, end, bpPerPx, reversed = false) {
59
+ // A zero (or negative) scale has no tick pitch to speak of, and this loop is
60
+ // sized in bp: chooseGridPitch bottoms out at 5bp, so a chromosome-length
61
+ // region would ask for tens of millions of ticks and hang. createOverviewLayout
62
+ // reports bpPerPx 0 whenever the overview's width collapses to 0 or less —
63
+ // a view narrower than its own chromosome-name gutter, or a caller that sets
64
+ // width directly (jbrowse-img) rather than through useWidthSetter, which
65
+ // filters 0 out.
66
+ if (!(bpPerPx > 0)) {
67
+ return [];
68
+ }
69
+ const { majorPitch } = chooseGridPitch(bpPerPx, 120, 15);
70
+ const firstTick = reversed
71
+ ? Math.floor((end - 1) / majorPitch) * majorPitch
72
+ : Math.ceil((start + 1) / majorPitch) * majorPitch;
73
+ const numTicks = reversed
74
+ ? Math.floor((firstTick - start - 1) / majorPitch) + 1
75
+ : Math.floor((end - firstTick) / majorPitch) + 1;
76
+ return Array.from({ length: Math.max(0, numTicks) }, (_, i) => {
77
+ const genomicCoord = reversed
78
+ ? firstTick - i * majorPitch
79
+ : firstTick + i * majorPitch;
80
+ const offsetPx = bpOffsetInRegion({ start, end, reversed }, genomicCoord) / bpPerPx;
81
+ return { genomicCoord, offsetPx };
82
+ });
83
+ }
84
+ /**
85
+ * Ticks for one span of the ruler. Not the dotplot's same-named function, which
86
+ * walks static blocks into a single continuous axis and therefore has to dedupe
87
+ * the shared block seam and carry each tick's px. Here every block draws its own
88
+ * clipped ruler, so this overscans its span instead of deduping and leaves px to
89
+ * `makeBlockTicks`. What the two do share is already shared: `chooseGridPitch`,
90
+ * and `base` as the 0-based coordinate that `getTickDisplayStr` labels `base+1`.
91
+ */
92
+ export function makeTicks(start, end, bpPerPx, includeMinor = true) {
93
+ // Ask for the ~200px spacing this ruler actually wants, and mark majors at
94
+ // that pitch. This used to ask for 60px and then mark majors every *two*
95
+ // pitches, which spaced them the same but off chooseGridPitch's 1/2/5 ladder:
96
+ // doubling a ladder value yields 4×10ⁿ half the time, so the scalebar numbered
97
+ // 4000/8000/12000 rather than 5000/10000/15000. The overview scalebar
98
+ // (makeOverviewTicks) and the dotplot's ruler both already read majorPitch
99
+ // straight, which is the contract chooseGridPitch documents.
100
+ const { majorPitch, minorPitch } = chooseGridPitch(bpPerPx, 120, 15);
101
+ // pad 20px on each side so label ends that spill slightly outside the region
102
+ // still draw
103
+ const margin = 20 * bpPerPx;
104
+ const minBase = start - margin + 1;
105
+ const maxBase = end + margin + 1;
106
+ const iterPitch = minorPitch || majorPitch;
107
+ const ticks = [];
108
+ for (let base = Math.floor(minBase / iterPitch) * iterPitch; base < Math.ceil(maxBase / iterPitch) * iterPitch + 1; base += iterPitch) {
109
+ if (!(base % majorPitch)) {
110
+ ticks.push({ type: 'major', base: base - 1 });
111
+ }
112
+ else if (includeMinor) {
113
+ ticks.push({ type: 'minor', base: base - 1 });
19
114
  }
20
- majorPitch *= 2.5;
21
115
  }
22
- majorPitch = Math.max(majorPitch, 5);
23
- const majorPitchPx = majorPitch / scale;
24
- let minorPitch = 0;
25
- if (!(majorPitch % 10) && majorPitchPx / 10 >= minMinorPitchPx) {
26
- minorPitch = majorPitch / 10;
116
+ return ticks;
117
+ }
118
+ /** A block's refName, or undefined for non-content (elided/padding) blocks. */
119
+ export function getBlockRefName(block) {
120
+ return block.type === 'ContentBlock' ? block.refName : undefined;
121
+ }
122
+ /**
123
+ * For blocks in display order, returns whether each block's refName should be
124
+ * labeled: true only for the first block of each run of same-refName regions,
125
+ * so a refName is shown once instead of repeated at every region boundary (e.g.
126
+ * collapsed introns produce many adjacent same-refName regions).
127
+ *
128
+ * A block with no refName ends the run. What an elided block hides is *other
129
+ * chromosomes*, so the same name reappearing on its far side starts a region the
130
+ * reader needs named again, not a continuation of the one before it. Regions lay
131
+ * out contiguously, so an elided run is the only nameless block that can fall
132
+ * between two content blocks — the boundary pads only bracket the whole set,
133
+ * where ending a run changes nothing.
134
+ */
135
+ export function showRefNameLabels(blocks, getRefName) {
136
+ let prev;
137
+ return blocks.map(block => {
138
+ const refName = getRefName(block);
139
+ const show = refName !== undefined && refName !== prev;
140
+ prev = refName;
141
+ return show;
142
+ });
143
+ }
144
+ function refNameRuns(blocks) {
145
+ const runs = [];
146
+ let current;
147
+ for (const block of blocks) {
148
+ if (block.type !== 'ContentBlock' ||
149
+ block.displayedRegionIndex === undefined) {
150
+ current = undefined;
151
+ }
152
+ else if (
153
+ // orientation is part of a run's identity, not just its refName: one
154
+ // label carries one direction (a `[rev]` marker under mixed orientation
155
+ // has to mean the whole of what it sits on), and two regions of one
156
+ // chromosome laid out in opposite directions are two things to name
157
+ // anyway, however they are marked
158
+ current?.refName === block.refName &&
159
+ current.reversed === !!block.reversed) {
160
+ current.endPx = block.offsetPx + block.widthPx;
161
+ current.lastRegionIndex = block.displayedRegionIndex;
162
+ }
163
+ else {
164
+ current = {
165
+ key: block.key,
166
+ refName: block.refName,
167
+ reversed: !!block.reversed,
168
+ offsetPx: block.offsetPx,
169
+ endPx: block.offsetPx + block.widthPx,
170
+ firstRegionIndex: block.displayedRegionIndex,
171
+ lastRegionIndex: block.displayedRegionIndex,
172
+ isLeftEndOfDisplayedRegion: !!block.isLeftEndOfDisplayedRegion,
173
+ };
174
+ runs.push(current);
175
+ }
27
176
  }
28
- else if (!(majorPitch % 5) && majorPitchPx / 5 >= minMinorPitchPx) {
29
- minorPitch = majorPitch / 5;
177
+ return runs;
178
+ }
179
+ /**
180
+ * Index of the run carrying the "sticky" refName label pinned to the strip's
181
+ * left edge: the rightmost run starting left of `leftEdgePx` (block frame), or
182
+ * the first run when none does.
183
+ */
184
+ function stickyRunIndex(runs, leftEdgePx) {
185
+ return Math.max(0, runs.findLastIndex(run => run.offsetPx < leftEdgePx));
186
+ }
187
+ export function regionsOrientation(regions) {
188
+ const first = !!regions[0]?.reversed;
189
+ return regions.every(r => !!r.reversed === first)
190
+ ? first
191
+ ? 'reversed'
192
+ : 'forward'
193
+ : 'mixed';
194
+ }
195
+ /**
196
+ * What a reversed region's label says after its name. `[rev]` rather than a
197
+ * glyph, and not only because it is the spelling `assembleLocString` already
198
+ * writes into every locstring the search box shows: `measureText`'s width table
199
+ * is indexed by char code and covers ASCII only, so an arrow falls through to
200
+ * the average advance and measures ~6px against a real ~11px. The fit test
201
+ * upstream is whole-or-nothing, and it would go on believing a glyph fits.
202
+ */
203
+ const REV_MARKER = ' [rev]';
204
+ /** Clearance between the caption chip and the sticky label after it. */
205
+ const CAPTION_GAP = 4;
206
+ /**
207
+ * Left inset of a non-sticky refName label from its region's left edge, clear
208
+ * of the 3px region divider drawn there.
209
+ */
210
+ const REF_NAME_LABEL_PADDING_PX = 7;
211
+ /**
212
+ * Builds the refName labels drawn along the scalebar as plain data (no JSX): one
213
+ * label per run of same-refName regions, the leftmost of them "sticky" — pinned
214
+ * so the run under the left edge stays named once its own left edge scrolls off.
215
+ *
216
+ * `caption` is the row-level chip at the viewport's left edge: which assembly
217
+ * the row is (`prefix`, synteny only) and whether the whole row is flipped. The
218
+ * chip takes `captionSpanPx` of the strip and the labels get the rest, so the
219
+ * sticky label pins to the chip's right edge ("hg38" then "chr1") and rides the
220
+ * run under THAT edge. A run the chip covers entirely goes unnamed, and the
221
+ * chip is not shortened to uncover it: a width fitted to the run under it
222
+ * changes with every run that pans past, and a fixed cap short enough to
223
+ * uncover a 55px chromosome cuts ordinary names. The assembly's `displayName`
224
+ * is where a long name gets shortened.
225
+ *
226
+ * `orientation` decides the ` [rev]` marker, following `assembleLocStrings`: say
227
+ * it where it distinguishes, once where it does not.
228
+ *
229
+ * - `reversed`: the caption carries the marker and no name does. A marker on a
230
+ * chromosome name is how the mixed case flags that one region.
231
+ * - `mixed`: every reversed run is marked. A marked label that fails the fit
232
+ * test falls back to the bare name rather than dropping.
233
+ * - `forward`: no marker.
234
+ *
235
+ * `maxWidth` is the whole label box, `paddingLeft` included — both consumers
236
+ * clip from the box's left edge. A name is drawn whole or not at all: clipped
237
+ * mid-glyph, "chr16" reads as "chr1".
238
+ */
239
+ export function getScalebarRefNameLabels({ blocks, offsetPx, prefix, orientation = 'forward', }) {
240
+ const caption = [prefix, orientation === 'reversed' ? REV_MARKER.trim() : undefined]
241
+ .filter(Boolean)
242
+ .join(' ') || undefined;
243
+ const captionSpanPx = caption ? refNameLabelWidth(caption) + CAPTION_GAP : 0;
244
+ const runs = refNameRuns(blocks);
245
+ const stickyIdx = stickyRunIndex(runs, offsetPx + captionSpanPx);
246
+ const labels = [];
247
+ for (const [i, run] of runs.entries()) {
248
+ const sticky = i === stickyIdx;
249
+ // runs left of the sticky one end under the caption or off screen
250
+ if (i < stickyIdx || !(sticky || run.isLeftEndOfDisplayedRegion)) {
251
+ continue;
252
+ }
253
+ const runStartPx = run.offsetPx - offsetPx;
254
+ const transform = sticky
255
+ ? Math.max(captionSpanPx, runStartPx)
256
+ : runStartPx - 1;
257
+ const paddingLeft = sticky ? 0 : REF_NAME_LABEL_PADDING_PX;
258
+ const maxWidth = run.endPx - offsetPx - transform - 1;
259
+ const text = (orientation === 'mixed' && run.reversed
260
+ ? [`${run.refName}${REV_MARKER}`, run.refName]
261
+ : [run.refName]).find(candidate => maxWidth >= paddingLeft + refNameLabelWidth(candidate));
262
+ if (text !== undefined) {
263
+ labels.push({
264
+ key: run.key,
265
+ refName: run.refName,
266
+ displayedRegionIndex: run.firstRegionIndex,
267
+ lastDisplayedRegionIndex: run.lastRegionIndex,
268
+ sticky,
269
+ transform,
270
+ maxWidth,
271
+ paddingLeft,
272
+ text,
273
+ });
274
+ }
30
275
  }
31
- else if (!(majorPitch % 2) && majorPitchPx / 2 >= minMinorPitchPx) {
32
- minorPitch = majorPitch / 2;
276
+ return { labels, caption, captionSpanPx };
277
+ }
278
+ /**
279
+ * Screen-x span a refName label paints over: its padding and its glyphs, which
280
+ * is the whole of it, since the box shrinks to its text rather than filling the
281
+ * `maxWidth` it was fitted against. Anything drawn under this span is hidden by
282
+ * the label's opaque backing, so the coordinate numbers use it to stay out from
283
+ * under the sticky label the way `runRefNameLabelPx` keeps them out from under
284
+ * the others.
285
+ */
286
+ export function refNameLabelSpanPx(label) {
287
+ return {
288
+ left: label.transform,
289
+ right: label.transform + label.paddingLeft + refNameLabelWidth(label.text),
290
+ };
291
+ }
292
+ /**
293
+ * Whether a label from getScalebarRefNameLabels is drawn whole within a
294
+ * viewport `widthPx` wide. The labels themselves are only fitted to their own
295
+ * *run of regions*, which routinely runs past the right edge of the view, so
296
+ * one starting a few px before that edge passes the run fit and is then cut by
297
+ * the viewport clip. On screen that reads as a name scrolled partly out of
298
+ * frame, but a static SVG export has no frame to scroll — there a cut "LG2"
299
+ * just names a chromosome that doesn't exist, so the export drops it instead,
300
+ * as it already does for tick numbers at the same edge.
301
+ */
302
+ export function refNameLabelFitsInView(label, widthPx) {
303
+ return refNameLabelSpanPx(label).right <= widthPx;
304
+ }
305
+ /**
306
+ * The reorder entries the refName-label menu offers for the region at `idx` of
307
+ * `numRegions`, each already carrying the index it moves to. The "far" moves
308
+ * need a gap of more than one between `idx` and the end — otherwise "Move to
309
+ * far left/right" targets the same index as "Move left/right" and duplicates
310
+ * the entry.
311
+ */
312
+ export function regionMoveActions(idx, numRegions) {
313
+ return [
314
+ { when: idx > 0, label: 'Move left', to: idx - 1 },
315
+ { when: idx < numRegions - 1, label: 'Move right', to: idx + 1 },
316
+ { when: idx > 1, label: 'Move to far left', to: 0 },
317
+ {
318
+ when: idx < numRegions - 2,
319
+ label: 'Move to far right',
320
+ to: numRegions - 1,
321
+ },
322
+ ].flatMap(({ when, label, to }) => (when ? [{ label, to }] : []));
323
+ }
324
+ export function withRegionMoved(regions, from, to) {
325
+ const out = [...regions];
326
+ const [moved] = out.splice(from, 1);
327
+ out.splice(to, 0, moved);
328
+ return {
329
+ regions: out,
330
+ newIndexOf: i => i === from
331
+ ? to
332
+ : i - (i > from && i <= to ? 1 : 0) + (i >= to && i < from ? 1 : 0),
333
+ };
334
+ }
335
+ export function withRegionRemoved(regions, index) {
336
+ return {
337
+ regions: regions.filter((_, i) => i !== index),
338
+ newIndexOf: i => (i === index ? -1 : i > index ? i - 1 : i),
339
+ };
340
+ }
341
+ export function withRegionsKept(regions, first, last) {
342
+ return {
343
+ regions: regions.slice(first, last + 1),
344
+ newIndexOf: i => (i >= first && i <= last ? i - first : -1),
345
+ };
346
+ }
347
+ export function withRegionReversed(regions, index) {
348
+ return {
349
+ regions: regions.map((region, i) => i === index ? { ...region, reversed: !region.reversed } : region),
350
+ newIndexOf: i => i,
351
+ };
352
+ }
353
+ /**
354
+ * Apply a region edit and keep the base under the middle of the viewport
355
+ * there, where the edit kept its region. `setDisplayedRegions` alone carries
356
+ * `offsetPx` into a coordinate space the edit redefined, which lands on
357
+ * whatever region now sits at that offset.
358
+ */
359
+ export function setDisplayedRegionsKeepingCenter(model, { regions, newIndexOf }) {
360
+ const center = model.displayedRegions.length
361
+ ? model.pxToBp(model.width / 2)
362
+ : undefined;
363
+ model.setDisplayedRegions(regions);
364
+ const index = center ? newIndexOf(center.index) : -1;
365
+ if (center && index !== -1) {
366
+ model.centerAt(center.coord0, center.refName, index);
367
+ }
368
+ }
369
+ /**
370
+ * The full run of same-orientation regions on one refName that a scalebar
371
+ * label's `firstRegionIndex`..`lastRegionIndex` sits inside. Those come off the
372
+ * static blocks, which are clipped to the viewport and broken by an elided
373
+ * block, so a zoomed-in collapsed-introns view brackets only the exons on
374
+ * screen — which is the wrong answer for anything acting on the whole run.
375
+ */
376
+ export function regionRunBounds(regions, firstIndex, lastIndex) {
377
+ const anchor = regions[firstIndex];
378
+ const inRun = (r) => r !== undefined &&
379
+ anchor !== undefined &&
380
+ r.refName === anchor.refName &&
381
+ r.assemblyName === anchor.assemblyName &&
382
+ !!r.reversed === !!anchor.reversed;
383
+ let first = firstIndex;
384
+ let last = lastIndex;
385
+ while (inRun(regions[first - 1])) {
386
+ first--;
33
387
  }
34
- return { majorPitch, minorPitch };
35
- }
36
- export function makeTicks(start, end, bpPerPx, emitMajor = true, emitMinor = true) {
37
- const gridPitch = chooseGridPitch(bpPerPx, 60, 15);
38
- let minBase = start;
39
- let maxBase = end;
40
- if (bpPerPx < 0) {
41
- ;
42
- [minBase, maxBase] = [maxBase, minBase];
388
+ while (inRun(regions[last + 1])) {
389
+ last++;
43
390
  }
44
- minBase -= Math.abs(20 * bpPerPx) - 1;
45
- maxBase += Math.abs(20 * bpPerPx) + 1;
46
- const iterPitch = gridPitch.minorPitch || gridPitch.majorPitch;
47
- let index = 0;
48
- const ticks = [];
49
- for (let base = Math.floor(minBase / iterPitch) * iterPitch; base < Math.ceil(maxBase / iterPitch) * iterPitch + 1; base += iterPitch) {
50
- if (emitMinor && base % (gridPitch.majorPitch * 2)) {
51
- ticks.push({ type: 'minor', base: base - 1, index });
52
- index += 1;
391
+ return { first, last };
392
+ }
393
+ /**
394
+ * Whether a label occupying [leftPx, leftPx + labelWidth] fits within a block
395
+ * of the given pixel width, used to skip tick labels that would be clipped at a
396
+ * region edge (common with small collapsed-intron regions).
397
+ */
398
+ export function labelFitsInBlock(leftPx, labelWidth, widthPx) {
399
+ return leftPx >= 0 && leftPx + labelWidth <= widthPx;
400
+ }
401
+ /** Font size of coordinate tick labels on the scalebar and overview scalebar. */
402
+ export const TICK_LABEL_FONT_SIZE = 11;
403
+ /**
404
+ * On-screen width of a coordinate tick label: the text plus 2px of horizontal
405
+ * padding on each side. Single-sourced so the HTML scalebar and the SVG export
406
+ * agree on when a label is too wide to fit inside its block.
407
+ */
408
+ export function tickLabelWidth(label) {
409
+ return measureText(label, TICK_LABEL_FONT_SIZE) + 4;
410
+ }
411
+ /** Font size of the bold refName label drawn at the left edge of its block, on
412
+ * the scalebar and the overview scalebar alike. */
413
+ export const REF_NAME_LABEL_FONT_SIZE = 11;
414
+ /**
415
+ * measureText's width table is for the regular weight; refName labels are bold,
416
+ * which runs a few percent wider. Under-measuring here would clip the last glyph
417
+ * off a name that was judged to fit, so round up rather than down.
418
+ */
419
+ const BOLD_WIDTH_FACTOR = 1.05;
420
+ /** On-screen width of a bold refName label. */
421
+ function refNameLabelWidth(refName) {
422
+ return measureText(refName, REF_NAME_LABEL_FONT_SIZE) * BOLD_WIDTH_FACTOR;
423
+ }
424
+ /** Left inset of the overview refName label within its block. */
425
+ const REF_NAME_LABEL_INSET_PX = 3;
426
+ /**
427
+ * Horizontal space the overview refName label occupies at a block's left edge.
428
+ * Overview tick labels use this to avoid drawing underneath the refName, which
429
+ * otherwise collide when zoomed far out (ticks bunch up near the block start).
430
+ */
431
+ export function overviewRefNameLabelWidth(refName) {
432
+ return (REF_NAME_LABEL_INSET_PX +
433
+ refNameLabelWidth(refName) +
434
+ REF_NAME_LABEL_INSET_PX);
435
+ }
436
+ /**
437
+ * Breathing room between the chromosome name and the ideogram to its right, on
438
+ * top of the space the name itself needs.
439
+ */
440
+ const CYTOBAND_LABEL_GAP_PX = 9;
441
+ /**
442
+ * How far right the ideogram starts, i.e. the gutter the chromosome name drawn
443
+ * to its left gets to itself. Shares overviewRefNameLabelWidth with the tick
444
+ * labels that dodge the same name, rather than measuring it again at a font size
445
+ * (12) the label is not actually drawn at (REF_NAME_LABEL_FONT_SIZE).
446
+ */
447
+ export function cytobandLabelGutterWidth(refName) {
448
+ return overviewRefNameLabelWidth(refName) + CYTOBAND_LABEL_GAP_PX;
449
+ }
450
+ /**
451
+ * Coordinate labels drawn inside one overview-scalebar block: tick text plus its
452
+ * x within the block. Labels that can't be drawn whole between the block's bold
453
+ * refName label and its right edge are dropped by the same
454
+ * tickLabelWidth/labelFitsInBlock test the main scalebar and SVG export use; if
455
+ * too few survive to make a ruler, the block goes unnumbered.
456
+ */
457
+ export function makeOverviewTickLabels({ block, bpPerPx, refNameLabelPx, }) {
458
+ const { start, end, reversed, widthPx } = block;
459
+ const labels = makeOverviewTicks(start, end, bpPerPx, reversed).flatMap(({ genomicCoord, offsetPx }) => {
460
+ const label = getTickDisplayStr(genomicCoord, bpPerPx);
461
+ const fits = offsetPx >= refNameLabelPx &&
462
+ labelFitsInBlock(offsetPx, tickLabelWidth(label), widthPx);
463
+ return fits ? [{ genomicCoord, offsetPx, label }] : [];
464
+ });
465
+ return tickLabelsWorthDrawing(labels.length) ? labels : [];
466
+ }
467
+ export function groupContiguousBlocks(blocks) {
468
+ const runs = [];
469
+ let current;
470
+ let currentRegionIndex;
471
+ for (const block of blocks) {
472
+ if (block.type === 'ContentBlock') {
473
+ if (current !== undefined &&
474
+ currentRegionIndex === block.displayedRegionIndex) {
475
+ current.widthPx += block.widthPx;
476
+ current.start = Math.min(current.start, block.start);
477
+ current.end = Math.max(current.end, block.end);
478
+ }
479
+ else {
480
+ const reversed = !!block.reversed;
481
+ current = {
482
+ offsetPx: block.offsetPx,
483
+ widthPx: block.widthPx,
484
+ start: block.start,
485
+ end: block.end,
486
+ reversed,
487
+ refName: block.refName,
488
+ isLeftEndOfDisplayedRegion: !!block.isLeftEndOfDisplayedRegion,
489
+ labeled: current?.refName !== block.refName || current.reversed !== reversed,
490
+ };
491
+ currentRegionIndex = block.displayedRegionIndex;
492
+ runs.push(current);
493
+ }
53
494
  }
54
- else if (emitMajor && !(base % (gridPitch.majorPitch * 2))) {
55
- ticks.push({ type: 'major', base: base - 1, index });
56
- index += 1;
495
+ else {
496
+ current = undefined;
497
+ currentRegionIndex = undefined;
57
498
  }
58
499
  }
59
- return ticks;
500
+ return runs;
501
+ }
502
+ /**
503
+ * Horizontal space reserved at each run's left edge for the bold refName label
504
+ * drawn there, or 0 for runs that get none. Coordinate labels use this to stay
505
+ * out from under the name, the way the overview scalebar's already do via
506
+ * overviewRefNameLabelWidth: the refName label is opaque and painted after the
507
+ * numbers, so one underneath it isn't merely crowded but invisible — and since
508
+ * both sit in the block frame and scroll together, invisible at every scroll
509
+ * position rather than only while passing behind.
510
+ *
511
+ * Which runs get a label follows getScalebarRefNameLabels: only where a region
512
+ * genuinely begins, and only the first of a run of one refName (collapsed
513
+ * introns make many adjacent regions of the same name). It deliberately drops
514
+ * that function's offsetPx term so the reservation — and with it scalebarLabels
515
+ * — stays stable while scrolling; a run scrolled off the left reserves space
516
+ * that is off-screen anyway. Where the two disagree the reservation is the
517
+ * conservative side: at worst a coordinate is dropped from a region too narrow
518
+ * to have kept MIN_TICK_LABELS_PER_BLOCK of them.
519
+ *
520
+ * `orientation` enters because under `mixed` a reversed run's label carries the
521
+ * ` [rev]` marker and so is wider than its name. Under a uniformly `reversed`
522
+ * row only the sticky label is marked, and that one is dodged on screen instead
523
+ * (`refNameLabelSpanPx`), its x being a function of the scroll rather than of
524
+ * this frame.
525
+ */
526
+ export function runRefNameLabelPx(runs, orientation = 'forward') {
527
+ return runs.map(run => run.labeled && run.isLeftEndOfDisplayedRegion
528
+ ? REF_NAME_LABEL_PADDING_PX +
529
+ refNameLabelWidth(orientation === 'mixed' && run.reversed
530
+ ? `${run.refName}${REV_MARKER}`
531
+ : run.refName)
532
+ : 0);
533
+ }
534
+ /**
535
+ * makeTicks plus each tick's pixel x within its block, accounting for reversed
536
+ * regions. Single source of the tick→px formula shared by gridlines, the
537
+ * scalebar coordinate labels, and SVG export so their positions can't drift.
538
+ */
539
+ export function makeBlockTicks({ start, end, reversed = false, }, bpPerPx, includeMinor = true) {
540
+ return makeTicks(start, end, bpPerPx, includeMinor).map(tick => ({
541
+ ...tick,
542
+ x: bpOffsetInRegion({ start, end, reversed }, tick.base) / bpPerPx,
543
+ }));
60
544
  }
545
+ /**
546
+ * Generate location objects for a set of parsed locstrings, which includes
547
+ * translating the refNames to assembly-canonical refNames and adding the
548
+ * 'parentRegion'
549
+ *
550
+ * Used by navToLocations and navToLocString
551
+ *
552
+ * @param regions - array of parsed location strings to generate locations for
553
+ * @param assemblyManager - the assembly manager instance
554
+ * @param assemblyName - optional assembly name to use for regions that don't
555
+ * specify one
556
+ * @param grow - optional multiplier to expand regions by (e.g., 0.2 adds 20%
557
+ * padding on each side of the region). Useful for adding visual padding when
558
+ * navigating to a feature
559
+ */
61
560
  export async function generateLocations({ regions, assemblyManager, assemblyName, grow, }) {
62
561
  return Promise.all(regions.map(async (region) => {
63
562
  const asmName = region.assemblyName || assemblyName;
@@ -73,10 +572,13 @@ export async function generateLocations({ regions, assemblyManager, assemblyName
73
572
  if (!regions) {
74
573
  throw new Error(`regions not loaded yet for ${asmName}`);
75
574
  }
76
- const canonicalRefName = asm.getCanonicalRefName(region.refName);
575
+ const canonicalRefName = asm.getCanonicalRefName(refName);
77
576
  if (!canonicalRefName) {
78
577
  throw new Error(`Could not find refName ${refName} in ${asm.name}`);
79
578
  }
579
+ // scans rather than calling getRegionForRefName: this runs once per typed
580
+ // locstring, not per frame, and the assembly here is duck-typed by several
581
+ // navigation tests that would each have to grow the method
80
582
  const parentRegion = regions.find(r => r.refName === canonicalRefName);
81
583
  if (!parentRegion) {
82
584
  throw new Error(`Could not find refName ${refName} in ${asmName}`);
@@ -93,19 +595,40 @@ export async function generateLocations({ regions, assemblyManager, assemblyName
93
595
  };
94
596
  }));
95
597
  }
598
+ /**
599
+ * Parses locString or space separated set of locStrings into location objects
600
+ * Example inputs:
601
+ * "chr1"
602
+ * "chr1:1-100"
603
+ * "chr1:1..100"
604
+ * "chr1 chr2"
605
+ * "chr1:1-100 chr2:1-100"
606
+ * "chr1 100 200" equivalent to "chr1:100-200"
607
+ * "chr1:34M-35M" equivalent to "chr1:34000000-35000000"
608
+ *
609
+ * Used by navToLocString
610
+ */
96
611
  export function parseLocStrings(input, assemblyName, isValidRefName) {
97
612
  const inputs = input
98
613
  .split(/(\s+)/)
99
614
  .map(f => f.trim())
100
615
  .filter(f => !!f);
616
+ // first try interpreting as a whitespace-separated sequence of
617
+ // multiple locstrings
101
618
  try {
102
619
  return inputs.map(loc => parseLocString(loc, ref => isValidRefName(ref, assemblyName)));
103
620
  }
104
621
  catch (e) {
105
- const [refName, start, end] = inputs;
106
- if (/Unknown feature or sequence/.exec(`${e}`) &&
107
- Number.isInteger(+start) &&
108
- Number.isInteger(+end)) {
622
+ // if this fails, try interpreting as a whitespace-separated refname,
623
+ // start, end if start and end are base-pair quantities. The tokens are
624
+ // handed on verbatim rather than as the numbers they parsed to, so the
625
+ // shorthands parseLocString accepts ("34M", "1,000") mean the same thing
626
+ // in this form as in the colon form.
627
+ const [refName, start = '', end = ''] = inputs;
628
+ if (e instanceof UnknownRefNameError &&
629
+ inputs.length === 3 &&
630
+ parseBpString(start) !== undefined &&
631
+ parseBpString(end) !== undefined) {
109
632
  return [
110
633
  parseLocString(`${refName}:${start}..${end}`, ref => isValidRefName(ref, assemblyName)),
111
634
  ];
@@ -114,19 +637,11 @@ export function parseLocStrings(input, assemblyName, isValidRefName) {
114
637
  }
115
638
  }
116
639
  export function calculateVisibleLocStrings(contentBlocks) {
117
- if (!contentBlocks.length) {
118
- return '';
119
- }
120
- else {
121
- const isSingleAssemblyName = contentBlocks.every(b => b.assemblyName === contentBlocks[0].assemblyName);
122
- return contentBlocks
123
- .map(block => assembleLocString({
124
- refName: block.refName,
125
- start: Math.round(block.start),
126
- end: Math.round(block.end),
127
- assemblyName: isSingleAssemblyName ? undefined : block.assemblyName,
128
- reversed: block.reversed,
129
- }))
130
- .join(' ');
131
- }
640
+ return assembleLocStrings(contentBlocks.map(block => ({
641
+ refName: block.refName,
642
+ start: Math.round(block.start),
643
+ end: Math.round(block.end),
644
+ assemblyName: block.assemblyName,
645
+ reversed: block.reversed,
646
+ })));
132
647
  }