react-msaview 7.0.0 → 8.0.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 (310) hide show
  1. package/README.md +11 -10
  2. package/bundle/index.js +122 -111
  3. package/bundle/index.js.map +4 -4
  4. package/dist/colorSchemes.js +1 -2
  5. package/dist/colorSchemes.js.map +1 -1
  6. package/dist/columnStats.d.ts +28 -0
  7. package/dist/columnStats.js +34 -0
  8. package/dist/columnStats.js.map +1 -0
  9. package/dist/components/DragHandle.d.ts +3 -2
  10. package/dist/components/DragHandle.js +11 -5
  11. package/dist/components/DragHandle.js.map +1 -1
  12. package/dist/components/Loading.js.map +1 -1
  13. package/dist/components/MSAView.js +17 -6
  14. package/dist/components/MSAView.js.map +1 -1
  15. package/dist/components/MSAViewer.d.ts +64 -7
  16. package/dist/components/MSAViewer.js +128 -23
  17. package/dist/components/MSAViewer.js.map +1 -1
  18. package/dist/components/PortalTooltip.d.ts +11 -0
  19. package/dist/components/PortalTooltip.js +29 -0
  20. package/dist/components/PortalTooltip.js.map +1 -0
  21. package/dist/components/ResizeHandles.js +11 -29
  22. package/dist/components/ResizeHandles.js.map +1 -1
  23. package/dist/components/SequenceTextArea.js +3 -3
  24. package/dist/components/SequenceTextArea.js.map +1 -1
  25. package/dist/components/Track.js +41 -22
  26. package/dist/components/Track.js.map +1 -1
  27. package/dist/components/dialogs/ExportSVGDialog.js +5 -3
  28. package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
  29. package/dist/components/dialogs/TrackInfoDialog.js +1 -1
  30. package/dist/components/dialogs/TrackInfoDialog.js.map +1 -1
  31. package/dist/components/header/GappynessSlider.js +6 -11
  32. package/dist/components/header/GappynessSlider.js.map +1 -1
  33. package/dist/components/header/Header.js +3 -0
  34. package/dist/components/header/Header.js.map +1 -1
  35. package/dist/components/header/LoadWarnings.js +3 -4
  36. package/dist/components/header/LoadWarnings.js.map +1 -1
  37. package/dist/components/header/ScrollZoomIcons.d.ts +6 -0
  38. package/dist/components/header/ScrollZoomIcons.js +35 -0
  39. package/dist/components/header/ScrollZoomIcons.js.map +1 -0
  40. package/dist/components/header/TreeSettingsMenu.js +1 -3
  41. package/dist/components/header/TreeSettingsMenu.js.map +1 -1
  42. package/dist/components/header/UnshareableDataWarning.js +2 -4
  43. package/dist/components/header/UnshareableDataWarning.js.map +1 -1
  44. package/dist/components/header/ZoomControls.js +49 -6
  45. package/dist/components/header/ZoomControls.js.map +1 -1
  46. package/dist/components/header/getAnnotationsMenu.js +3 -6
  47. package/dist/components/header/getAnnotationsMenu.js.map +1 -1
  48. package/dist/components/header/settingsMenuItems.js +10 -7
  49. package/dist/components/header/settingsMenuItems.js.map +1 -1
  50. package/dist/components/import/util.js +1 -2
  51. package/dist/components/import/util.js.map +1 -1
  52. package/dist/components/minimap/Minimap.js +1 -2
  53. package/dist/components/minimap/Minimap.js.map +1 -1
  54. package/dist/components/msa/AnnotationLegend.js +27 -19
  55. package/dist/components/msa/AnnotationLegend.js.map +1 -1
  56. package/dist/components/msa/MSACanvas.js +1 -1
  57. package/dist/components/msa/MSACanvas.js.map +1 -1
  58. package/dist/components/msa/MSACanvasBlock.js +13 -15
  59. package/dist/components/msa/MSACanvasBlock.js.map +1 -1
  60. package/dist/components/msa/MSAMouseoverCanvas.js +2 -1
  61. package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
  62. package/dist/components/msa/domainBandCursor.d.ts +7 -11
  63. package/dist/components/msa/domainBandCursor.js +7 -11
  64. package/dist/components/msa/domainBandCursor.js.map +1 -1
  65. package/dist/components/msa/drawFeatureSpans.d.ts +53 -0
  66. package/dist/components/msa/drawFeatureSpans.js +78 -0
  67. package/dist/components/msa/drawFeatureSpans.js.map +1 -0
  68. package/dist/components/msa/legendRows.d.ts +8 -0
  69. package/dist/components/msa/legendRows.js +16 -0
  70. package/dist/components/msa/legendRows.js.map +1 -0
  71. package/dist/components/msa/msaRaster.d.ts +24 -31
  72. package/dist/components/msa/msaRaster.js +30 -39
  73. package/dist/components/msa/msaRaster.js.map +1 -1
  74. package/dist/components/msa/packDomainLanes.d.ts +20 -0
  75. package/dist/components/msa/packDomainLanes.js +33 -0
  76. package/dist/components/msa/packDomainLanes.js.map +1 -0
  77. package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +3 -1
  78. package/dist/components/msa/renderBoxFeatureCanvasBlock.js +51 -87
  79. package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
  80. package/dist/components/msa/renderHighlights.d.ts +15 -13
  81. package/dist/components/msa/renderHighlights.js +43 -20
  82. package/dist/components/msa/renderHighlights.js.map +1 -1
  83. package/dist/components/msa/renderMSABlock.js +5 -4
  84. package/dist/components/msa/renderMSABlock.js.map +1 -1
  85. package/dist/components/msa/tileColor.js +4 -7
  86. package/dist/components/msa/tileColor.js.map +1 -1
  87. package/dist/components/msa/useMsaBlockMouse.d.ts +5 -3
  88. package/dist/components/msa/useMsaBlockMouse.js +6 -6
  89. package/dist/components/msa/useMsaBlockMouse.js.map +1 -1
  90. package/dist/components/rowpanels/RowPanelBlock.d.ts +9 -0
  91. package/dist/components/rowpanels/RowPanelBlock.js +86 -0
  92. package/dist/components/rowpanels/RowPanelBlock.js.map +1 -0
  93. package/dist/components/rowpanels/RowPanelHeaders.d.ts +12 -0
  94. package/dist/components/rowpanels/RowPanelHeaders.js +38 -0
  95. package/dist/components/rowpanels/RowPanelHeaders.js.map +1 -0
  96. package/dist/components/{msa/ColumnStats.d.ts → rowpanels/RowPanels.d.ts} +2 -2
  97. package/dist/components/rowpanels/RowPanels.js +32 -0
  98. package/dist/components/rowpanels/RowPanels.js.map +1 -0
  99. package/dist/components/rowpanels/headerLayout.d.ts +1 -0
  100. package/dist/components/rowpanels/headerLayout.js +5 -0
  101. package/dist/components/rowpanels/headerLayout.js.map +1 -0
  102. package/dist/components/rowpanels/renderFeaturePanel.d.ts +21 -0
  103. package/dist/components/rowpanels/renderFeaturePanel.js +37 -0
  104. package/dist/components/rowpanels/renderFeaturePanel.js.map +1 -0
  105. package/dist/components/rowpanels/renderRowPanel.d.ts +23 -0
  106. package/dist/components/rowpanels/renderRowPanel.js +22 -0
  107. package/dist/components/rowpanels/renderRowPanel.js.map +1 -0
  108. package/dist/components/rowpanels/renderStrip.d.ts +20 -0
  109. package/dist/components/rowpanels/renderStrip.js +26 -0
  110. package/dist/components/rowpanels/renderStrip.js.map +1 -0
  111. package/dist/components/tracks/TrackBlocks.js +3 -5
  112. package/dist/components/tracks/TrackBlocks.js.map +1 -1
  113. package/dist/components/tracks/TrackTooltipContent.d.ts +15 -0
  114. package/dist/components/tracks/TrackTooltipContent.js +109 -0
  115. package/dist/components/tracks/TrackTooltipContent.js.map +1 -0
  116. package/dist/components/tracks/drawTracks.d.ts +4 -4
  117. package/dist/components/tracks/drawTracks.js +17 -34
  118. package/dist/components/tracks/drawTracks.js.map +1 -1
  119. package/dist/components/tracks/useTrackHover.d.ts +22 -0
  120. package/dist/components/tracks/useTrackHover.js +30 -0
  121. package/dist/components/tracks/useTrackHover.js.map +1 -0
  122. package/dist/components/tree/CladeLabels.d.ts +12 -0
  123. package/dist/components/tree/CladeLabels.js +48 -0
  124. package/dist/components/tree/CladeLabels.js.map +1 -0
  125. package/dist/components/tree/TreeCanvas.js +4 -1
  126. package/dist/components/tree/TreeCanvas.js.map +1 -1
  127. package/dist/components/tree/TreeCanvasBlock.js +4 -21
  128. package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
  129. package/dist/components/tree/TreeOverview.d.ts +14 -0
  130. package/dist/components/tree/TreeOverview.js +75 -0
  131. package/dist/components/tree/TreeOverview.js.map +1 -0
  132. package/dist/components/tree/TreeRuler.js +9 -13
  133. package/dist/components/tree/TreeRuler.js.map +1 -1
  134. package/dist/components/tree/cladeBrackets.d.ts +25 -0
  135. package/dist/components/tree/cladeBrackets.js +51 -0
  136. package/dist/components/tree/cladeBrackets.js.map +1 -0
  137. package/dist/components/tree/dialogs/TreeNodeInfoDialog.js +2 -2
  138. package/dist/components/tree/dialogs/TreeNodeInfoDialog.js.map +1 -1
  139. package/dist/components/tree/renderTreeCanvas.js +158 -24
  140. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  141. package/dist/components/tree/renderTreeOverview.d.ts +52 -0
  142. package/dist/components/tree/renderTreeOverview.js +138 -0
  143. package/dist/components/tree/renderTreeOverview.js.map +1 -0
  144. package/dist/components/tree/useTreeHover.js +2 -4
  145. package/dist/components/tree/useTreeHover.js.map +1 -1
  146. package/dist/constants.d.ts +15 -0
  147. package/dist/constants.js +48 -22
  148. package/dist/constants.js.map +1 -1
  149. package/dist/createPaletteMap.d.ts +7 -6
  150. package/dist/createPaletteMap.js +10 -9
  151. package/dist/createPaletteMap.js.map +1 -1
  152. package/dist/element.d.ts +13 -0
  153. package/dist/element.js +269 -0
  154. package/dist/element.js.map +1 -0
  155. package/dist/featureFields.d.ts +11 -0
  156. package/dist/featureFields.js +17 -0
  157. package/dist/featureFields.js.map +1 -0
  158. package/dist/flatToTree.js +1 -2
  159. package/dist/flatToTree.js.map +1 -1
  160. package/dist/ggplotPalettes.d.ts +10 -0
  161. package/dist/ggplotPalettes.js +58 -0
  162. package/dist/ggplotPalettes.js.map +1 -1
  163. package/dist/hierarchy.d.ts +27 -0
  164. package/dist/hierarchy.js +66 -9
  165. package/dist/hierarchy.js.map +1 -1
  166. package/dist/index.d.ts +9 -1
  167. package/dist/index.js +5 -3
  168. package/dist/index.js.map +1 -1
  169. package/dist/model/DataModel.js +2 -5
  170. package/dist/model/DataModel.js.map +1 -1
  171. package/dist/model/msaModel.d.ts +3 -2
  172. package/dist/model/msaModel.js +3 -2
  173. package/dist/model/msaModel.js.map +1 -1
  174. package/dist/model/treeModel.d.ts +30 -0
  175. package/dist/model/treeModel.js +37 -1
  176. package/dist/model/treeModel.js.map +1 -1
  177. package/dist/model.d.ts +531 -275
  178. package/dist/model.js +1295 -547
  179. package/dist/model.js.map +1 -1
  180. package/dist/mount.d.ts +11 -0
  181. package/dist/mount.js +22 -0
  182. package/dist/mount.js.map +1 -0
  183. package/dist/neighborJoining.js +8 -32
  184. package/dist/neighborJoining.js.map +1 -1
  185. package/dist/renderToStaticMarkup.d.ts +10 -19
  186. package/dist/renderToStaticMarkup.js +13 -24
  187. package/dist/renderToStaticMarkup.js.map +1 -1
  188. package/dist/renderToSvg.js +180 -56
  189. package/dist/renderToSvg.js.map +1 -1
  190. package/dist/rowCoordinateCalculations.d.ts +4 -6
  191. package/dist/rowCoordinateCalculations.js +4 -6
  192. package/dist/rowCoordinateCalculations.js.map +1 -1
  193. package/dist/scales.d.ts +22 -0
  194. package/dist/scales.js +30 -0
  195. package/dist/scales.js.map +1 -0
  196. package/dist/seqPosToGlobalCol.d.ts +2 -3
  197. package/dist/seqPosToGlobalCol.js +2 -3
  198. package/dist/seqPosToGlobalCol.js.map +1 -1
  199. package/dist/sequenceLogo.d.ts +6 -11
  200. package/dist/sequenceLogo.js +6 -11
  201. package/dist/sequenceLogo.js.map +1 -1
  202. package/dist/stripDefault.d.ts +7 -14
  203. package/dist/stripDefault.js +7 -14
  204. package/dist/stripDefault.js.map +1 -1
  205. package/dist/svgTestUtil.d.ts +172 -52
  206. package/dist/types.d.ts +219 -21
  207. package/dist/umd.d.ts +2 -0
  208. package/dist/umd.js +4 -2
  209. package/dist/umd.js.map +1 -1
  210. package/dist/useCanvasAutorun.d.ts +5 -10
  211. package/dist/useCanvasAutorun.js +5 -10
  212. package/dist/useCanvasAutorun.js.map +1 -1
  213. package/dist/useMsaSvgFigure.d.ts +20 -0
  214. package/dist/useMsaSvgFigure.js +46 -0
  215. package/dist/useMsaSvgFigure.js.map +1 -0
  216. package/dist/util.d.ts +5 -6
  217. package/dist/util.js +13 -6
  218. package/dist/util.js.map +1 -1
  219. package/dist/version.d.ts +1 -1
  220. package/dist/version.js +1 -1
  221. package/package.json +19 -12
  222. package/src/colorSchemes.ts +1 -2
  223. package/src/columnStats.ts +58 -0
  224. package/src/components/DragHandle.tsx +18 -7
  225. package/src/components/Loading.tsx +2 -6
  226. package/src/components/MSAView.tsx +19 -5
  227. package/src/components/MSAViewer.tsx +240 -28
  228. package/src/components/PortalTooltip.tsx +47 -0
  229. package/src/components/ResizeHandles.tsx +17 -32
  230. package/src/components/SequenceTextArea.tsx +3 -3
  231. package/src/components/Track.tsx +55 -18
  232. package/src/components/dialogs/ExportSVGDialog.tsx +7 -2
  233. package/src/components/dialogs/TrackInfoDialog.tsx +1 -1
  234. package/src/components/header/GappynessSlider.tsx +6 -11
  235. package/src/components/header/Header.tsx +6 -0
  236. package/src/components/header/LoadWarnings.tsx +3 -4
  237. package/src/components/header/ScrollZoomIcons.tsx +52 -0
  238. package/src/components/header/TreeSettingsMenu.tsx +1 -3
  239. package/src/components/header/UnshareableDataWarning.tsx +2 -4
  240. package/src/components/header/ZoomControls.tsx +74 -14
  241. package/src/components/header/getAnnotationsMenu.ts +3 -6
  242. package/src/components/header/settingsMenuItems.ts +11 -6
  243. package/src/components/import/ImportFormExamples.tsx +2 -2
  244. package/src/components/import/util.ts +1 -2
  245. package/src/components/minimap/Minimap.tsx +1 -2
  246. package/src/components/msa/AnnotationLegend.tsx +48 -38
  247. package/src/components/msa/MSACanvas.tsx +3 -5
  248. package/src/components/msa/MSACanvasBlock.tsx +13 -16
  249. package/src/components/msa/MSAMouseoverCanvas.tsx +2 -1
  250. package/src/components/msa/domainBandCursor.ts +7 -11
  251. package/src/components/msa/drawFeatureSpans.ts +150 -0
  252. package/src/components/msa/legendRows.ts +24 -0
  253. package/src/components/msa/msaRaster.ts +30 -39
  254. package/src/components/msa/packDomainLanes.ts +36 -0
  255. package/src/components/msa/renderBoxFeatureCanvasBlock.ts +69 -123
  256. package/src/components/msa/renderHighlights.ts +53 -20
  257. package/src/components/msa/renderMSABlock.ts +5 -3
  258. package/src/components/msa/tileColor.ts +4 -7
  259. package/src/components/msa/useMsaBlockMouse.ts +6 -6
  260. package/src/components/rowpanels/RowPanelBlock.tsx +139 -0
  261. package/src/components/rowpanels/RowPanelHeaders.tsx +57 -0
  262. package/src/components/rowpanels/RowPanels.tsx +77 -0
  263. package/src/components/rowpanels/headerLayout.ts +5 -0
  264. package/src/components/rowpanels/renderFeaturePanel.ts +66 -0
  265. package/src/components/rowpanels/renderRowPanel.ts +41 -0
  266. package/src/components/rowpanels/renderStrip.ts +46 -0
  267. package/src/components/tracks/TrackBlocks.tsx +3 -5
  268. package/src/components/tracks/TrackTooltipContent.tsx +156 -0
  269. package/src/components/tracks/drawTracks.ts +17 -34
  270. package/src/components/tracks/useTrackHover.ts +42 -0
  271. package/src/components/tree/CladeLabels.tsx +77 -0
  272. package/src/components/tree/TreeCanvas.tsx +2 -0
  273. package/src/components/tree/TreeCanvasBlock.tsx +8 -32
  274. package/src/components/tree/TreeOverview.tsx +106 -0
  275. package/src/components/tree/TreeRuler.tsx +11 -22
  276. package/src/components/tree/cladeBrackets.ts +73 -0
  277. package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +2 -2
  278. package/src/components/tree/renderTreeCanvas.ts +240 -20
  279. package/src/components/tree/renderTreeOverview.ts +212 -0
  280. package/src/components/tree/useTreeHover.ts +2 -4
  281. package/src/constants.ts +56 -22
  282. package/src/createPaletteMap.ts +10 -9
  283. package/src/element.ts +321 -0
  284. package/src/featureFields.ts +19 -0
  285. package/src/flatToTree.ts +1 -2
  286. package/src/ggplotPalettes.ts +60 -0
  287. package/src/hierarchy.ts +77 -9
  288. package/src/index.ts +31 -7
  289. package/src/model/DataModel.ts +2 -5
  290. package/src/model/msaModel.ts +3 -2
  291. package/src/model/treeModel.ts +42 -0
  292. package/src/model.ts +1523 -560
  293. package/src/mount.tsx +32 -0
  294. package/src/neighborJoining.ts +8 -32
  295. package/src/renderToStaticMarkup.ts +13 -24
  296. package/src/renderToSvg.tsx +335 -68
  297. package/src/rowCoordinateCalculations.ts +4 -6
  298. package/src/scales.ts +47 -0
  299. package/src/seqPosToGlobalCol.ts +2 -3
  300. package/src/sequenceLogo.ts +6 -11
  301. package/src/stripDefault.ts +7 -14
  302. package/src/types.ts +258 -45
  303. package/src/umd.ts +4 -2
  304. package/src/useCanvasAutorun.ts +5 -10
  305. package/src/useMsaSvgFigure.ts +72 -0
  306. package/src/util.ts +15 -6
  307. package/src/version.ts +1 -1
  308. package/dist/components/msa/ColumnStats.js +0 -42
  309. package/dist/components/msa/ColumnStats.js.map +0 -1
  310. package/src/components/msa/ColumnStats.tsx +0 -54
@@ -3,9 +3,9 @@ import React, { useState } from 'react'
3
3
  import { makeStyles } from '@jbrowse/core/util/tss-react'
4
4
  import { useTheme } from '@mui/material'
5
5
  import { observer } from 'mobx-react'
6
- import { createPortal } from 'react-dom'
7
6
 
8
7
  import { useCanvasAutorun } from '../../useCanvasAutorun.ts'
8
+ import PortalTooltip from '../PortalTooltip.tsx'
9
9
  import TreeBranchMenu from './TreeBranchMenu.tsx'
10
10
  import TreeNodeMenu from './TreeNodeMenu.tsx'
11
11
  import { renderTreeCanvas } from './renderTreeCanvas.ts'
@@ -13,21 +13,7 @@ import { useTreeHover } from './useTreeHover.ts'
13
13
 
14
14
  import type { MsaViewModel } from '../../model.ts'
15
15
 
16
- const useStyles = makeStyles()(theme => ({
17
- tooltip: {
18
- position: 'fixed',
19
- pointerEvents: 'none',
20
- zIndex: 10000,
21
- backgroundColor: theme.palette.grey[700],
22
- color: theme.palette.common.white,
23
- padding: '4px 8px',
24
- borderRadius: 4,
25
- fontSize: 12,
26
- whiteSpace: 'nowrap',
27
- maxWidth: 300,
28
- overflow: 'hidden',
29
- textOverflow: 'ellipsis',
30
- },
16
+ const useStyles = makeStyles()(() => ({
31
17
  hover: {
32
18
  position: 'absolute',
33
19
  pointerEvents: 'none',
@@ -58,8 +44,7 @@ const TreeCanvasBlock = observer(function ({
58
44
  useTreeHover({ model, offsetY })
59
45
 
60
46
  const { treeAreaWidth, blockSize, highResScaleFactor } = model
61
- // TreePanel clips to treeAreaWidth, so anything wider is backing store the
62
- // viewer never sees -- it was 600px of it per block, at dpr squared
47
+ // TreePanel clips to treeAreaWidth, so a wider canvas is wasted backing store
63
48
  const width = treeAreaWidth
64
49
  const height = blockSize
65
50
 
@@ -154,20 +139,11 @@ const TreeCanvasBlock = observer(function ({
154
139
  />
155
140
  ) : null}
156
141
 
157
- {/* portaled: the block set sits under a transform, which would otherwise
158
- make this fixed tooltip position against the scrolled tree instead of the
159
- window */}
160
- {hovered
161
- ? createPortal(
162
- <div
163
- className={classes.tooltip}
164
- style={{ left: hovered.clientX + 12, top: hovered.clientY + 12 }}
165
- >
166
- {hovered.name}
167
- </div>,
168
- document.body,
169
- )
170
- : null}
142
+ {hovered ? (
143
+ <PortalTooltip clientX={hovered.clientX} clientY={hovered.clientY}>
144
+ {hovered.name}
145
+ </PortalTooltip>
146
+ ) : null}
171
147
  </>
172
148
  )
173
149
  })
@@ -0,0 +1,106 @@
1
+ import React, { useState } from 'react'
2
+
3
+ import { useTheme } from '@mui/material'
4
+ import { observer } from 'mobx-react'
5
+
6
+ import { useCanvasAutorun } from '../../useCanvasAutorun.ts'
7
+ import {
8
+ drawTreeOverview,
9
+ drawTreeOverviewBox,
10
+ treeOverviewImage,
11
+ } from './renderTreeOverview.ts'
12
+
13
+ import type { MsaViewModel } from '../../model.ts'
14
+
15
+ /**
16
+ * The brush on the row scale: the whole tree drawn small above the tree panel,
17
+ * with the focused subtree boxed. A click focuses the subtree under the
18
+ * pointer, and a click inside the box clears the focus.
19
+ *
20
+ * The tree itself comes off a cached offscreen canvas, so the frames a pointer
21
+ * moving across it costs are a blit and two boxes.
22
+ */
23
+ const TreeOverview = observer(function ({ model }: { model: MsaViewModel }) {
24
+ const { treeAreaWidth, overviewHeight, highResScaleFactor } = model
25
+ const theme = useTheme()
26
+ const [hover, setHover] = useState<{ id: string; rows: [number, number] }>()
27
+ const width = Math.round(treeAreaWidth * highResScaleFactor)
28
+ const height = Math.round(overviewHeight * highResScaleFactor)
29
+
30
+ const ref = useCanvasAutorun({
31
+ draw: ctx => {
32
+ ctx.resetTransform()
33
+ ctx.clearRect(0, 0, width, height)
34
+ const image = treeOverviewImage({
35
+ model,
36
+ theme,
37
+ width: treeAreaWidth,
38
+ height: overviewHeight,
39
+ scale: highResScaleFactor,
40
+ })
41
+ ctx.scale(highResScaleFactor, highResScaleFactor)
42
+ const box = { model, ctx, width: treeAreaWidth, height: overviewHeight }
43
+ if (image) {
44
+ ctx.drawImage(
45
+ image,
46
+ 0,
47
+ 0,
48
+ image.width,
49
+ image.height,
50
+ 0,
51
+ 0,
52
+ box.width,
53
+ box.height,
54
+ )
55
+ } else {
56
+ drawTreeOverview({ ...box, theme })
57
+ }
58
+ if (hover) {
59
+ drawTreeOverviewBox({
60
+ ...box,
61
+ rows: hover.rows,
62
+ color: theme.palette.text.secondary,
63
+ })
64
+ }
65
+ const focus = model.treeOverviewFocusRows
66
+ if (focus) {
67
+ drawTreeOverviewBox({
68
+ ...box,
69
+ rows: focus,
70
+ color: theme.palette.text.primary,
71
+ })
72
+ }
73
+ },
74
+ width,
75
+ height,
76
+ deps: [model, theme, hover],
77
+ })
78
+
79
+ return (
80
+ <canvas
81
+ data-testid="tree_overview"
82
+ ref={ref}
83
+ width={width}
84
+ height={height}
85
+ style={{
86
+ display: 'block',
87
+ flexShrink: 0,
88
+ cursor: 'pointer',
89
+ width: treeAreaWidth,
90
+ height: overviewHeight,
91
+ }}
92
+ onMouseMove={event => {
93
+ const hit = model.treeOverviewHit(event.nativeEvent.offsetY)
94
+ setHover(prev => (prev?.id === hit?.id ? prev : hit))
95
+ }}
96
+ onMouseLeave={() => {
97
+ setHover(undefined)
98
+ }}
99
+ onClick={event => {
100
+ model.treeOverviewClick(event.nativeEvent.offsetY)
101
+ }}
102
+ />
103
+ )
104
+ })
105
+
106
+ export default TreeOverview
@@ -3,43 +3,32 @@ import React from 'react'
3
3
  import { useTheme } from '@mui/material'
4
4
  import { observer } from 'mobx-react'
5
5
 
6
- import { scaleBarLength } from './scaleBar.ts'
6
+ import { treeScaleBarHeight as h } from '../../constants.ts'
7
7
 
8
8
  import type { MsaViewModel } from '../../model.ts'
9
9
 
10
- const BAR_HEIGHT = 22
11
-
12
- // The gutter above the tree panel. It spans the resize handle too, so whatever
13
- // follows it in the top row starts exactly where the alignment canvas does --
14
- // MainArea has TreePanel + VerticalResizeHandle before the alignment. A
15
- // phylogram fills it with a scale bar: without one the branch lengths are drawn
16
- // to a scale nothing states.
10
+ // The gutter above the tree panel, the width of the tree area, so the strip
11
+ // headers beside it start where the strips do. A phylogram fills it with a
12
+ // scale bar: without one the branch lengths are drawn to a scale nothing
13
+ // states.
17
14
  const TreeRuler = observer(({ model }: { model: MsaViewModel }) => {
18
- const { treeAreaWidth, resizeHandleWidth, marginLeft, pxPerBranchLength } =
19
- model
15
+ const { treeAreaWidth, marginLeft, treeScaleBar: bar } = model
20
16
  const theme = useTheme()
21
- const width = treeAreaWidth + resizeHandleWidth
22
- const bar = scaleBarLength(pxPerBranchLength, treeAreaWidth - marginLeft * 2)
23
17
 
24
18
  return (
25
- <div style={{ flexShrink: 0, width }}>
19
+ <div style={{ flexShrink: 0, width: treeAreaWidth }}>
26
20
  {bar ? (
27
21
  <svg
28
- width={width}
29
- height={BAR_HEIGHT}
22
+ width={treeAreaWidth}
23
+ height={h}
30
24
  style={{ display: 'block' }}
31
25
  color={theme.palette.text.primary}
32
26
  >
33
- <text
34
- x={marginLeft}
35
- y={BAR_HEIGHT - 9}
36
- fontSize={10}
37
- fill="currentColor"
38
- >
27
+ <text x={marginLeft} y={h - 9} fontSize={10} fill="currentColor">
39
28
  {bar.label}
40
29
  </text>
41
30
  <path
42
- d={`M${marginLeft} ${BAR_HEIGHT - 7} v6 h${bar.px} v-6`}
31
+ d={`M${marginLeft} ${h - 7} v6 h${bar.px} v-6`}
43
32
  fill="none"
44
33
  stroke="currentColor"
45
34
  />
@@ -0,0 +1,73 @@
1
+ import { measureTextCanvas } from '../../measureTextCanvas.ts'
2
+
3
+ import type { ResolvedClade } from '../../types.ts'
4
+
5
+ // The bar of the bracket mark and the space around it, in px.
6
+ export const bracketBarWidth = 3
7
+ export const bracketGap = 4
8
+
9
+ // The widest gutter the bracket mark takes. A longer label is clipped, so one
10
+ // long name cannot squeeze the tree it annotates.
11
+ export const maxCladeGutterWidth = 140
12
+
13
+ /** whether a clade draws in the gutter: a bracket, or a highlight with a label */
14
+ export function cladeInGutter(clade: ResolvedClade) {
15
+ return (
16
+ clade.mark === 'bracket' || (clade.mark === 'highlight' && !!clade.label)
17
+ )
18
+ }
19
+
20
+ /** the pixel height of the rows a clade covers */
21
+ export function cladeHeight(clade: ResolvedClade, rowHeight: number) {
22
+ return (clade.rows[1] - clade.rows[0] + 1) * rowHeight
23
+ }
24
+
25
+ /**
26
+ * Whether a label reads across the rows. It does where they are taller than the
27
+ * font, and runs up the bar where they are not.
28
+ */
29
+ export function cladeLabelHorizontal(
30
+ clade: ResolvedClade,
31
+ rowHeight: number,
32
+ fontSize: number,
33
+ ) {
34
+ return cladeHeight(clade, rowHeight) >= fontSize
35
+ }
36
+
37
+ /** the px between the left edge of the gutter and the label's own column */
38
+ export function cladeLabelOffset(clade: ResolvedClade) {
39
+ return clade.mark === 'bracket'
40
+ ? bracketGap + bracketBarWidth + bracketGap
41
+ : bracketGap
42
+ }
43
+
44
+ /**
45
+ * The gutter the bracket mark needs at the right of the tree area: the bar plus
46
+ * the widest label at the tree font, zero where no clade draws there, and at
47
+ * most maxCladeGutterWidth.
48
+ */
49
+ export function cladeGutterWidth({
50
+ clades,
51
+ rowHeight,
52
+ fontSize,
53
+ }: {
54
+ clades: ResolvedClade[]
55
+ rowHeight: number
56
+ fontSize: number
57
+ }) {
58
+ let widest = 0
59
+ for (const clade of clades) {
60
+ if (!cladeInGutter(clade)) {
61
+ continue
62
+ }
63
+ const text = clade.label
64
+ ? cladeLabelHorizontal(clade, rowHeight, fontSize)
65
+ ? measureTextCanvas(clade.label, fontSize)
66
+ : fontSize
67
+ : 0
68
+ widest = Math.max(widest, cladeLabelOffset(clade) + text + bracketGap)
69
+ }
70
+ // a whole pixel, so the room the renderers measure against covers the label
71
+ // the measurement here sized the gutter for
72
+ return Math.min(maxCladeGutterWidth, Math.ceil(widest))
73
+ }
@@ -21,8 +21,8 @@ const TreeNodeInfoDialog = observer(function ({
21
21
  nodeName: string
22
22
  onClose: () => void
23
23
  }) {
24
- const { treeMetadata, rows } = model
25
- const metadata = treeMetadata[nodeName]
24
+ const { rows } = model
25
+ const metadata = model.rowDataOf(nodeName)
26
26
  const res = rows.find(f => f[0] === nodeName)
27
27
  return (
28
28
  <Dialog