react-msaview 6.5.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 (414) hide show
  1. package/README.md +13 -11
  2. package/bundle/index.js +122 -112
  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 +2 -2
  13. package/dist/components/Loading.js.map +1 -1
  14. package/dist/components/MSAView.js +17 -6
  15. package/dist/components/MSAView.js.map +1 -1
  16. package/dist/components/MSAViewer.d.ts +69 -4
  17. package/dist/components/MSAViewer.js +201 -8
  18. package/dist/components/MSAViewer.js.map +1 -1
  19. package/dist/components/PortalTooltip.d.ts +11 -0
  20. package/dist/components/PortalTooltip.js +29 -0
  21. package/dist/components/PortalTooltip.js.map +1 -0
  22. package/dist/components/ResizeHandles.d.ts +3 -3
  23. package/dist/components/ResizeHandles.js +13 -24
  24. package/dist/components/ResizeHandles.js.map +1 -1
  25. package/dist/components/SequenceTextArea.js +3 -3
  26. package/dist/components/SequenceTextArea.js.map +1 -1
  27. package/dist/components/Track.js +41 -22
  28. package/dist/components/Track.js.map +1 -1
  29. package/dist/components/dialogs/{InterProScanDialog.d.ts → AnnotationFileDialog.d.ts} +2 -2
  30. package/dist/components/dialogs/AnnotationFileDialog.js +92 -0
  31. package/dist/components/dialogs/AnnotationFileDialog.js.map +1 -0
  32. package/dist/components/dialogs/ExportSVGDialog.js +5 -3
  33. package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
  34. package/dist/components/dialogs/FeatureDialog.js +13 -9
  35. package/dist/components/dialogs/FeatureDialog.js.map +1 -1
  36. package/dist/components/dialogs/TrackInfoDialog.js +1 -1
  37. package/dist/components/dialogs/TrackInfoDialog.js.map +1 -1
  38. package/dist/components/header/GappynessSlider.js +6 -11
  39. package/dist/components/header/GappynessSlider.js.map +1 -1
  40. package/dist/components/header/Header.js +7 -0
  41. package/dist/components/header/Header.js.map +1 -1
  42. package/dist/components/header/HeaderStatusArea.js +0 -2
  43. package/dist/components/header/HeaderStatusArea.js.map +1 -1
  44. package/dist/components/header/LoadWarnings.d.ts +6 -0
  45. package/dist/components/header/LoadWarnings.js +35 -0
  46. package/dist/components/header/LoadWarnings.js.map +1 -0
  47. package/dist/components/header/MultiAlignmentSelector.js +0 -0
  48. package/dist/components/header/MultiAlignmentSelector.js.map +1 -1
  49. package/dist/components/header/ScrollZoomIcons.d.ts +6 -0
  50. package/dist/components/header/ScrollZoomIcons.js +35 -0
  51. package/dist/components/header/ScrollZoomIcons.js.map +1 -0
  52. package/dist/components/header/TreeSettingsMenu.js +7 -1
  53. package/dist/components/header/TreeSettingsMenu.js.map +1 -1
  54. package/dist/components/header/UnshareableDataWarning.d.ts +6 -0
  55. package/dist/components/header/UnshareableDataWarning.js +40 -0
  56. package/dist/components/header/UnshareableDataWarning.js.map +1 -0
  57. package/dist/components/header/ZoomControls.js +49 -6
  58. package/dist/components/header/ZoomControls.js.map +1 -1
  59. package/dist/components/header/getAnnotationsMenu.js +11 -14
  60. package/dist/components/header/getAnnotationsMenu.js.map +1 -1
  61. package/dist/components/header/settingsMenuItems.js +10 -7
  62. package/dist/components/header/settingsMenuItems.js.map +1 -1
  63. package/dist/components/import/ImportForm.js +1 -1
  64. package/dist/components/import/ImportForm.js.map +1 -1
  65. package/dist/components/import/ImportFormExamples.js +2 -6
  66. package/dist/components/import/ImportFormExamples.js.map +1 -1
  67. package/dist/components/import/util.js +2 -0
  68. package/dist/components/import/util.js.map +1 -1
  69. package/dist/components/minimap/Minimap.js +1 -2
  70. package/dist/components/minimap/Minimap.js.map +1 -1
  71. package/dist/components/msa/AnnotationLegend.js +27 -19
  72. package/dist/components/msa/AnnotationLegend.js.map +1 -1
  73. package/dist/components/msa/MSACanvas.js +1 -1
  74. package/dist/components/msa/MSACanvas.js.map +1 -1
  75. package/dist/components/msa/MSACanvasBlock.js +17 -20
  76. package/dist/components/msa/MSACanvasBlock.js.map +1 -1
  77. package/dist/components/msa/MSAMouseoverCanvas.js +2 -1
  78. package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
  79. package/dist/components/msa/domainBandCursor.d.ts +7 -11
  80. package/dist/components/msa/domainBandCursor.js +7 -11
  81. package/dist/components/msa/domainBandCursor.js.map +1 -1
  82. package/dist/components/msa/drawFeatureSpans.d.ts +53 -0
  83. package/dist/components/msa/drawFeatureSpans.js +78 -0
  84. package/dist/components/msa/drawFeatureSpans.js.map +1 -0
  85. package/dist/components/msa/legendRows.d.ts +8 -0
  86. package/dist/components/msa/legendRows.js +16 -0
  87. package/dist/components/msa/legendRows.js.map +1 -0
  88. package/dist/components/msa/msaRaster.d.ts +30 -27
  89. package/dist/components/msa/msaRaster.js +193 -90
  90. package/dist/components/msa/msaRaster.js.map +1 -1
  91. package/dist/components/msa/packDomainLanes.d.ts +20 -0
  92. package/dist/components/msa/packDomainLanes.js +33 -0
  93. package/dist/components/msa/packDomainLanes.js.map +1 -0
  94. package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +3 -1
  95. package/dist/components/msa/renderBoxFeatureCanvasBlock.js +51 -87
  96. package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
  97. package/dist/components/msa/renderHighlights.d.ts +44 -4
  98. package/dist/components/msa/renderHighlights.js +99 -11
  99. package/dist/components/msa/renderHighlights.js.map +1 -1
  100. package/dist/components/msa/renderMSABlock.d.ts +1 -2
  101. package/dist/components/msa/renderMSABlock.js +28 -31
  102. package/dist/components/msa/renderMSABlock.js.map +1 -1
  103. package/dist/components/msa/renderMSAMouseover.js +9 -30
  104. package/dist/components/msa/renderMSAMouseover.js.map +1 -1
  105. package/dist/components/msa/tileColor.js +4 -7
  106. package/dist/components/msa/tileColor.js.map +1 -1
  107. package/dist/components/msa/useMsaBlockMouse.d.ts +5 -3
  108. package/dist/components/msa/useMsaBlockMouse.js +6 -6
  109. package/dist/components/msa/useMsaBlockMouse.js.map +1 -1
  110. package/dist/components/renderCtx.d.ts +1 -1
  111. package/dist/components/rowpanels/RowPanelBlock.d.ts +9 -0
  112. package/dist/components/rowpanels/RowPanelBlock.js +86 -0
  113. package/dist/components/rowpanels/RowPanelBlock.js.map +1 -0
  114. package/dist/components/rowpanels/RowPanelHeaders.d.ts +12 -0
  115. package/dist/components/rowpanels/RowPanelHeaders.js +38 -0
  116. package/dist/components/rowpanels/RowPanelHeaders.js.map +1 -0
  117. package/dist/components/{msa/ColumnStats.d.ts → rowpanels/RowPanels.d.ts} +2 -2
  118. package/dist/components/rowpanels/RowPanels.js +32 -0
  119. package/dist/components/rowpanels/RowPanels.js.map +1 -0
  120. package/dist/components/rowpanels/headerLayout.d.ts +1 -0
  121. package/dist/components/rowpanels/headerLayout.js +5 -0
  122. package/dist/components/rowpanels/headerLayout.js.map +1 -0
  123. package/dist/components/rowpanels/renderFeaturePanel.d.ts +21 -0
  124. package/dist/components/rowpanels/renderFeaturePanel.js +37 -0
  125. package/dist/components/rowpanels/renderFeaturePanel.js.map +1 -0
  126. package/dist/components/rowpanels/renderRowPanel.d.ts +23 -0
  127. package/dist/components/rowpanels/renderRowPanel.js +22 -0
  128. package/dist/components/rowpanels/renderRowPanel.js.map +1 -0
  129. package/dist/components/rowpanels/renderStrip.d.ts +20 -0
  130. package/dist/components/rowpanels/renderStrip.js +26 -0
  131. package/dist/components/rowpanels/renderStrip.js.map +1 -0
  132. package/dist/components/tracks/TrackBlocks.js +13 -16
  133. package/dist/components/tracks/TrackBlocks.js.map +1 -1
  134. package/dist/components/tracks/TrackTooltipContent.d.ts +15 -0
  135. package/dist/components/tracks/TrackTooltipContent.js +109 -0
  136. package/dist/components/tracks/TrackTooltipContent.js.map +1 -0
  137. package/dist/components/tracks/drawTracks.d.ts +30 -12
  138. package/dist/components/tracks/drawTracks.js +127 -34
  139. package/dist/components/tracks/drawTracks.js.map +1 -1
  140. package/dist/components/tracks/useTrackHover.d.ts +22 -0
  141. package/dist/components/tracks/useTrackHover.js +30 -0
  142. package/dist/components/tracks/useTrackHover.js.map +1 -0
  143. package/dist/components/tree/CladeLabels.d.ts +12 -0
  144. package/dist/components/tree/CladeLabels.js +48 -0
  145. package/dist/components/tree/CladeLabels.js.map +1 -0
  146. package/dist/components/tree/TreeCanvas.js +6 -4
  147. package/dist/components/tree/TreeCanvas.js.map +1 -1
  148. package/dist/components/tree/TreeCanvasBlock.js +6 -21
  149. package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
  150. package/dist/components/tree/TreeOverview.d.ts +14 -0
  151. package/dist/components/tree/TreeOverview.js +75 -0
  152. package/dist/components/tree/TreeOverview.js.map +1 -0
  153. package/dist/components/tree/TreeRuler.js +11 -5
  154. package/dist/components/tree/TreeRuler.js.map +1 -1
  155. package/dist/components/tree/cladeBrackets.d.ts +25 -0
  156. package/dist/components/tree/cladeBrackets.js +51 -0
  157. package/dist/components/tree/cladeBrackets.js.map +1 -0
  158. package/dist/components/tree/dialogs/TreeNodeInfoDialog.js +2 -2
  159. package/dist/components/tree/dialogs/TreeNodeInfoDialog.js.map +1 -1
  160. package/dist/components/tree/renderTreeCanvas.d.ts +0 -1
  161. package/dist/components/tree/renderTreeCanvas.js +221 -47
  162. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  163. package/dist/components/tree/renderTreeOverview.d.ts +52 -0
  164. package/dist/components/tree/renderTreeOverview.js +138 -0
  165. package/dist/components/tree/renderTreeOverview.js.map +1 -0
  166. package/dist/components/tree/scaleBar.d.ts +10 -0
  167. package/dist/components/tree/scaleBar.js +24 -0
  168. package/dist/components/tree/scaleBar.js.map +1 -0
  169. package/dist/components/tree/useTreeHover.js +2 -4
  170. package/dist/components/tree/useTreeHover.js.map +1 -1
  171. package/dist/constants.d.ts +18 -1
  172. package/dist/constants.js +51 -8
  173. package/dist/constants.js.map +1 -1
  174. package/dist/createPaletteMap.d.ts +7 -6
  175. package/dist/createPaletteMap.js +10 -9
  176. package/dist/createPaletteMap.js.map +1 -1
  177. package/dist/element.d.ts +13 -0
  178. package/dist/element.js +269 -0
  179. package/dist/element.js.map +1 -0
  180. package/dist/featureFields.d.ts +11 -0
  181. package/dist/featureFields.js +17 -0
  182. package/dist/featureFields.js.map +1 -0
  183. package/dist/fetchUtils.d.ts +7 -7
  184. package/dist/fetchUtils.js +4 -32
  185. package/dist/fetchUtils.js.map +1 -1
  186. package/dist/flatToTree.js +1 -2
  187. package/dist/flatToTree.js.map +1 -1
  188. package/dist/ggplotPalettes.d.ts +10 -0
  189. package/dist/ggplotPalettes.js +58 -0
  190. package/dist/ggplotPalettes.js.map +1 -1
  191. package/dist/hierarchy.d.ts +29 -1
  192. package/dist/hierarchy.js +82 -19
  193. package/dist/hierarchy.js.map +1 -1
  194. package/dist/index.d.ts +10 -1
  195. package/dist/index.js +10 -2
  196. package/dist/index.js.map +1 -1
  197. package/dist/model/DataModel.js +4 -4
  198. package/dist/model/DataModel.js.map +1 -1
  199. package/dist/model/msaModel.d.ts +3 -2
  200. package/dist/model/msaModel.js +3 -2
  201. package/dist/model/msaModel.js.map +1 -1
  202. package/dist/model/treeModel.d.ts +30 -0
  203. package/dist/model/treeModel.js +37 -1
  204. package/dist/model/treeModel.js.map +1 -1
  205. package/dist/model.d.ts +792 -259
  206. package/dist/model.js +2092 -675
  207. package/dist/model.js.map +1 -1
  208. package/dist/mount.d.ts +11 -0
  209. package/dist/mount.js +22 -0
  210. package/dist/mount.js.map +1 -0
  211. package/dist/neighborJoining.js +8 -32
  212. package/dist/neighborJoining.js.map +1 -1
  213. package/dist/renderToStaticMarkup.d.ts +15 -13
  214. package/dist/renderToStaticMarkup.js +37 -25
  215. package/dist/renderToStaticMarkup.js.map +1 -1
  216. package/dist/renderToSvg.js +198 -68
  217. package/dist/renderToSvg.js.map +1 -1
  218. package/dist/rowCoordinateCalculations.d.ts +26 -28
  219. package/dist/rowCoordinateCalculations.js +13 -39
  220. package/dist/rowCoordinateCalculations.js.map +1 -1
  221. package/dist/scales.d.ts +22 -0
  222. package/dist/scales.js +30 -0
  223. package/dist/scales.js.map +1 -0
  224. package/dist/seqPosToGlobalCol.d.ts +2 -3
  225. package/dist/seqPosToGlobalCol.js +5 -4
  226. package/dist/seqPosToGlobalCol.js.map +1 -1
  227. package/dist/sequenceLogo.d.ts +6 -11
  228. package/dist/sequenceLogo.js +6 -11
  229. package/dist/sequenceLogo.js.map +1 -1
  230. package/dist/stripDefault.d.ts +7 -14
  231. package/dist/stripDefault.js +7 -14
  232. package/dist/stripDefault.js.map +1 -1
  233. package/dist/svgTestUtil.d.ts +306 -124
  234. package/dist/types.d.ts +295 -3
  235. package/dist/umd.d.ts +2 -0
  236. package/dist/umd.js +4 -2
  237. package/dist/umd.js.map +1 -1
  238. package/dist/useCanvasAutorun.d.ts +5 -10
  239. package/dist/useCanvasAutorun.js +5 -10
  240. package/dist/useCanvasAutorun.js.map +1 -1
  241. package/dist/useMsaSvgFigure.d.ts +20 -0
  242. package/dist/useMsaSvgFigure.js +46 -0
  243. package/dist/useMsaSvgFigure.js.map +1 -0
  244. package/dist/util.d.ts +10 -4
  245. package/dist/util.js +37 -10
  246. package/dist/util.js.map +1 -1
  247. package/dist/version.d.ts +1 -1
  248. package/dist/version.js +1 -1
  249. package/dist/wuss.d.ts +14 -0
  250. package/dist/wuss.js +55 -0
  251. package/dist/wuss.js.map +1 -0
  252. package/package.json +23 -14
  253. package/src/colorSchemes.ts +1 -2
  254. package/src/columnStats.ts +58 -0
  255. package/src/components/DragHandle.tsx +18 -7
  256. package/src/components/Loading.tsx +14 -8
  257. package/src/components/MSAView.tsx +19 -5
  258. package/src/components/MSAViewer.tsx +326 -10
  259. package/src/components/PortalTooltip.tsx +47 -0
  260. package/src/components/ResizeHandles.tsx +21 -36
  261. package/src/components/SequenceTextArea.tsx +3 -3
  262. package/src/components/Track.tsx +55 -18
  263. package/src/components/dialogs/AnnotationFileDialog.tsx +162 -0
  264. package/src/components/dialogs/ExportSVGDialog.tsx +7 -2
  265. package/src/components/dialogs/FeatureDialog.tsx +13 -9
  266. package/src/components/dialogs/TrackInfoDialog.tsx +1 -1
  267. package/src/components/header/GappynessSlider.tsx +6 -11
  268. package/src/components/header/Header.tsx +10 -0
  269. package/src/components/header/HeaderStatusArea.tsx +0 -5
  270. package/src/components/header/LoadWarnings.tsx +48 -0
  271. package/src/components/header/MultiAlignmentSelector.tsx +0 -0
  272. package/src/components/header/ScrollZoomIcons.tsx +52 -0
  273. package/src/components/header/TreeSettingsMenu.tsx +7 -1
  274. package/src/components/header/UnshareableDataWarning.tsx +56 -0
  275. package/src/components/header/ZoomControls.tsx +74 -14
  276. package/src/components/header/getAnnotationsMenu.ts +13 -17
  277. package/src/components/header/settingsMenuItems.ts +11 -6
  278. package/src/components/import/ImportForm.tsx +2 -2
  279. package/src/components/import/ImportFormExamples.tsx +4 -8
  280. package/src/components/import/util.ts +2 -0
  281. package/src/components/minimap/Minimap.tsx +1 -2
  282. package/src/components/msa/AnnotationLegend.tsx +48 -38
  283. package/src/components/msa/MSACanvas.tsx +3 -5
  284. package/src/components/msa/MSACanvasBlock.tsx +17 -21
  285. package/src/components/msa/MSAMouseoverCanvas.tsx +2 -1
  286. package/src/components/msa/domainBandCursor.ts +7 -11
  287. package/src/components/msa/drawFeatureSpans.ts +150 -0
  288. package/src/components/msa/legendRows.ts +24 -0
  289. package/src/components/msa/msaRaster.ts +236 -88
  290. package/src/components/msa/packDomainLanes.ts +36 -0
  291. package/src/components/msa/renderBoxFeatureCanvasBlock.ts +69 -123
  292. package/src/components/msa/renderHighlights.ts +141 -10
  293. package/src/components/msa/renderMSABlock.ts +29 -38
  294. package/src/components/msa/renderMSAMouseover.ts +9 -39
  295. package/src/components/msa/tileColor.ts +4 -7
  296. package/src/components/msa/useMsaBlockMouse.ts +6 -6
  297. package/src/components/renderCtx.ts +1 -0
  298. package/src/components/rowpanels/RowPanelBlock.tsx +139 -0
  299. package/src/components/rowpanels/RowPanelHeaders.tsx +57 -0
  300. package/src/components/rowpanels/RowPanels.tsx +77 -0
  301. package/src/components/rowpanels/headerLayout.ts +5 -0
  302. package/src/components/rowpanels/renderFeaturePanel.ts +66 -0
  303. package/src/components/rowpanels/renderRowPanel.ts +41 -0
  304. package/src/components/rowpanels/renderStrip.ts +46 -0
  305. package/src/components/tracks/TrackBlocks.tsx +13 -18
  306. package/src/components/tracks/TrackTooltipContent.tsx +156 -0
  307. package/src/components/tracks/drawTracks.ts +169 -38
  308. package/src/components/tracks/useTrackHover.ts +42 -0
  309. package/src/components/tree/CladeLabels.tsx +77 -0
  310. package/src/components/tree/TreeCanvas.tsx +4 -3
  311. package/src/components/tree/TreeCanvasBlock.tsx +10 -32
  312. package/src/components/tree/TreeOverview.tsx +106 -0
  313. package/src/components/tree/TreeRuler.tsx +29 -5
  314. package/src/components/tree/cladeBrackets.ts +73 -0
  315. package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +2 -2
  316. package/src/components/tree/renderTreeCanvas.ts +312 -48
  317. package/src/components/tree/renderTreeOverview.ts +212 -0
  318. package/src/components/tree/scaleBar.ts +23 -0
  319. package/src/components/tree/useTreeHover.ts +2 -4
  320. package/src/constants.ts +61 -8
  321. package/src/createPaletteMap.ts +10 -9
  322. package/src/element.ts +321 -0
  323. package/src/featureFields.ts +19 -0
  324. package/src/fetchUtils.ts +7 -40
  325. package/src/flatToTree.ts +1 -2
  326. package/src/ggplotPalettes.ts +60 -0
  327. package/src/hierarchy.ts +97 -20
  328. package/src/index.ts +46 -6
  329. package/src/model/DataModel.ts +5 -4
  330. package/src/model/msaModel.ts +3 -2
  331. package/src/model/treeModel.ts +42 -0
  332. package/src/model.ts +2492 -793
  333. package/src/mount.tsx +32 -0
  334. package/src/neighborJoining.ts +8 -32
  335. package/src/rawImports.d.ts +9 -0
  336. package/src/renderToStaticMarkup.ts +41 -25
  337. package/src/renderToSvg.tsx +365 -92
  338. package/src/rowCoordinateCalculations.ts +16 -62
  339. package/src/scales.ts +47 -0
  340. package/src/seqPosToGlobalCol.ts +5 -4
  341. package/src/sequenceLogo.ts +6 -11
  342. package/src/stripDefault.ts +7 -14
  343. package/src/types.ts +352 -12
  344. package/src/umd.ts +4 -2
  345. package/src/useCanvasAutorun.ts +5 -10
  346. package/src/useMsaSvgFigure.ts +72 -0
  347. package/src/util.ts +40 -14
  348. package/src/version.ts +1 -1
  349. package/src/wuss.ts +62 -0
  350. package/dist/components/dialogs/InterProScanDialog.js +0 -137
  351. package/dist/components/dialogs/InterProScanDialog.js.map +0 -1
  352. package/dist/components/dialogs/InterProScanFileDialog.d.ts +0 -7
  353. package/dist/components/dialogs/InterProScanFileDialog.js +0 -64
  354. package/dist/components/dialogs/InterProScanFileDialog.js.map +0 -1
  355. package/dist/components/msa/ColumnStats.js +0 -42
  356. package/dist/components/msa/ColumnStats.js.map +0 -1
  357. package/dist/launchInterProScan.d.ts +0 -13
  358. package/dist/launchInterProScan.js +0 -110
  359. package/dist/launchInterProScan.js.map +0 -1
  360. package/dist/useColorContrast.d.ts +0 -10
  361. package/dist/useColorContrast.js +0 -13
  362. package/dist/useColorContrast.js.map +0 -1
  363. package/src/clustalX.test.ts +0 -74
  364. package/src/colSpace.test.ts +0 -67
  365. package/src/collapseLogic.test.ts +0 -115
  366. package/src/colorSchemes.docs.test.ts +0 -57
  367. package/src/columnCounts.test.ts +0 -73
  368. package/src/columnStats.test.ts +0 -94
  369. package/src/columnTracks.test.ts +0 -97
  370. package/src/components/dialogs/InterProScanDialog.tsx +0 -214
  371. package/src/components/dialogs/InterProScanFileDialog.tsx +0 -138
  372. package/src/components/minimap/minimapLayout.test.ts +0 -71
  373. package/src/components/msa/ColumnStats.tsx +0 -54
  374. package/src/components/msa/msaRaster.test.ts +0 -145
  375. package/src/components/msa/renderBoxFeatureCanvasBlock.test.ts +0 -51
  376. package/src/components/tree/renderTreeCanvas.test.ts +0 -296
  377. package/src/dataInitialized.test.ts +0 -42
  378. package/src/domainBands.test.ts +0 -122
  379. package/src/domainLetterColor.test.ts +0 -80
  380. package/src/exportFileName.test.ts +0 -40
  381. package/src/fetchUtils.test.ts +0 -83
  382. package/src/flatToTree.test.ts +0 -51
  383. package/src/hierarchy.test.ts +0 -228
  384. package/src/highlights.test.ts +0 -70
  385. package/src/impgRender.test.tsx +0 -68
  386. package/src/largeTree.test.ts +0 -67
  387. package/src/launchInterProScan.ts +0 -167
  388. package/src/loadErrorDisplay.test.tsx +0 -102
  389. package/src/modelFilehandleLoaders.test.ts +0 -137
  390. package/src/modelReset.test.ts +0 -120
  391. package/src/neighborJoining.test.ts +0 -164
  392. package/src/parseAsn1.test.ts +0 -36
  393. package/src/propertyConservation.test.ts +0 -36
  394. package/src/renderColumnTracksSvg.test.tsx +0 -108
  395. package/src/renderDomainsSvg.test.tsx +0 -118
  396. package/src/renderHighlightsSvg.test.tsx +0 -85
  397. package/src/renderMinimapSvg.test.tsx +0 -62
  398. package/src/renderRasterSvg.test.tsx +0 -144
  399. package/src/renderSequenceLogoSvg.test.tsx +0 -165
  400. package/src/renderToSvg.test.tsx +0 -65
  401. package/src/reset.test.ts +0 -61
  402. package/src/rowCoordinateCalculations.test.ts +0 -211
  403. package/src/rowSpace.test.ts +0 -46
  404. package/src/segmentOverlay.test.ts +0 -70
  405. package/src/seqPosToGlobalCol.test.ts +0 -59
  406. package/src/sequenceLogo.test.ts +0 -88
  407. package/src/setFontSize.test.ts +0 -33
  408. package/src/stripDefault.test.ts +0 -48
  409. package/src/stripDefaultSnapshot.test.ts +0 -87
  410. package/src/treeMetadata.test.ts +0 -39
  411. package/src/useCanvasAutorun.test.tsx +0 -98
  412. package/src/useColorContrast.ts +0 -18
  413. package/src/viewChrome.test.tsx +0 -134
  414. package/src/wheelZoom.test.ts +0 -46
@@ -0,0 +1,156 @@
1
+ import React from 'react'
2
+
3
+ import { observer } from 'mobx-react'
4
+
5
+ import { columnLogoStack } from '../../sequenceLogo.ts'
6
+ import { barTrackValues } from './drawTracks.ts'
7
+
8
+ import type { MsaViewModel } from '../../model.ts'
9
+ import type { BasicTrack } from '../../types.ts'
10
+
11
+ const pct = (n: number) => `${Math.round(n * 100)}%`
12
+
13
+ const MAX_PARTNERS = 8
14
+
15
+ function ColumnLabel({ model, col }: { model: MsaViewModel; col: number }) {
16
+ const { relativeTo } = model
17
+ const pos = relativeTo
18
+ ? model.visibleColToSeqPosOneBased(relativeTo, col)
19
+ : undefined
20
+ return (
21
+ <b>
22
+ Column {col + 1}
23
+ {pos === undefined ? null : ` (${relativeTo}:${pos})`}
24
+ </b>
25
+ )
26
+ }
27
+
28
+ function BarTooltip({
29
+ model,
30
+ track,
31
+ col,
32
+ }: {
33
+ model: MsaViewModel
34
+ track: BasicTrack
35
+ col: number
36
+ }) {
37
+ const { id, name } = track.model
38
+ const value = barTrackValues(model, id)[col]
39
+ return value === undefined ? null : (
40
+ <div>
41
+ <ColumnLabel model={model} col={col} />
42
+ <br />
43
+ {name}: {value.toFixed(2)}
44
+ </div>
45
+ )
46
+ }
47
+
48
+ function LogoTooltip({ model, col }: { model: MsaViewModel; col: number }) {
49
+ const stats = model.columnStatsAt(col)
50
+ if (!stats) {
51
+ return null
52
+ }
53
+ const { total, consensusLetter, consensusFraction, gapFraction } = stats
54
+ const stack = columnLogoStack(model.colStats, col, model.alphabetMaxBits)
55
+ const bits = stack.reduce((a, b) => a + b.bits, 0)
56
+ return (
57
+ <div>
58
+ <ColumnLabel model={model} col={col} /> ({total} seqs)
59
+ <br />
60
+ Information: {bits.toFixed(2)} bits
61
+ <br />
62
+ Consensus: {consensusLetter || '-'} ({pct(consensusFraction)})
63
+ <br />
64
+ Gaps: {pct(gapFraction)}
65
+ <br />
66
+ {stats.distribution.slice(0, 6).map(([letter, count]) => (
67
+ <span key={letter} style={{ marginRight: 8 }}>
68
+ {letter} {pct(count / total)}
69
+ </span>
70
+ ))}
71
+ </div>
72
+ )
73
+ }
74
+
75
+ function TextTooltip({
76
+ model,
77
+ track,
78
+ col,
79
+ }: {
80
+ model: MsaViewModel
81
+ track: BasicTrack
82
+ col: number
83
+ }) {
84
+ const { name, data } = track.model
85
+ const letter = data?.[col]
86
+ return letter === undefined ? null : (
87
+ <div>
88
+ <ColumnLabel model={model} col={col} />
89
+ <br />
90
+ {name}: {letter === ' ' ? 'blank' : letter}
91
+ </div>
92
+ )
93
+ }
94
+
95
+ function ArcTooltip({
96
+ model,
97
+ track,
98
+ col,
99
+ }: {
100
+ model: MsaViewModel
101
+ track: BasicTrack
102
+ col: number
103
+ }) {
104
+ const { name, arcs } = track.model
105
+ const partners = (arcs ?? [])
106
+ .filter(arc => arc.start === col || arc.end === col)
107
+ .map(arc => (arc.start === col ? arc.end : arc.start) + 1)
108
+ return partners.length === 0 ? null : (
109
+ <div>
110
+ <ColumnLabel model={model} col={col} />
111
+ <br />
112
+ {name}: pairs with {partners.slice(0, MAX_PARTNERS).join(', ')}
113
+ {partners.length > MAX_PARTNERS ? '...' : null}
114
+ </div>
115
+ )
116
+ }
117
+
118
+ /**
119
+ * One track's reading at the hovered column: a bar track's value, the logo's
120
+ * information content and composition, the columns an arc joins, the letter on a
121
+ * text track. `drawTrackBlock` dispatches on the same `kind`, so a new kind
122
+ * needs a case in both.
123
+ */
124
+ const TrackTooltipContent = observer(function ({
125
+ model,
126
+ track,
127
+ col,
128
+ }: {
129
+ model: MsaViewModel
130
+ track: BasicTrack
131
+ col: number
132
+ }) {
133
+ switch (track.model.kind) {
134
+ case 'bar': {
135
+ return <BarTooltip model={model} track={track} col={col} />
136
+ }
137
+ case 'logo': {
138
+ return <LogoTooltip model={model} col={col} />
139
+ }
140
+ case 'text': {
141
+ return <TextTooltip model={model} track={track} col={col} />
142
+ }
143
+ case 'arc': {
144
+ return <ArcTooltip model={model} track={track} col={col} />
145
+ }
146
+ case 'ruler': {
147
+ return (
148
+ <div>
149
+ <ColumnLabel model={model} col={col} />
150
+ </div>
151
+ )
152
+ }
153
+ }
154
+ })
155
+
156
+ export default TrackTooltipContent
@@ -1,10 +1,11 @@
1
1
  import { columnLogoStack } from '../../sequenceLogo.ts'
2
2
  import { setFontSize } from '../../setFontSize.ts'
3
+ import { contrastTextFn } from '../../util.ts'
3
4
  import { visibleColRange } from '../msa/visibleColRange.ts'
4
5
 
5
6
  import type { ColumnCounts } from '../../columnCounts.ts'
6
7
  import type { MsaViewModel } from '../../model.ts'
7
- import type { BasicTrack } from '../../types.ts'
8
+ import type { Arc, BasicTrack } from '../../types.ts'
8
9
  import type { RenderCtx } from '../renderCtx.ts'
9
10
  import type { Theme } from '@mui/material'
10
11
 
@@ -40,8 +41,8 @@ export function drawConservationBars({
40
41
  }
41
42
  }
42
43
 
43
- // the bar-track values live on model getters (kept off the plain track object so
44
- // the live canvas autorun stays reactive); select the right one by track id
44
+ // bar-track values are model getters, off the plain track object, so the canvas
45
+ // autorun stays reactive
45
46
  export function barTrackValues(model: MsaViewModel, trackId: string) {
46
47
  const supplied = model.columnTrackContent.get(trackId)?.values
47
48
  if (supplied) {
@@ -52,13 +53,63 @@ export function barTrackValues(model: MsaViewModel, trackId: string) {
52
53
  : model.conservation
53
54
  }
54
55
 
56
+ // An arc's apex scales with the square root of its span. Contact-map spans skew
57
+ // short, and a linear scale flattens them along the baseline.
58
+ export function drawArcs({
59
+ ctx,
60
+ arcs,
61
+ color,
62
+ colWidth,
63
+ trackHeight,
64
+ offsetX,
65
+ blockSize,
66
+ }: {
67
+ ctx: RenderCtx
68
+ arcs: Arc[] | undefined
69
+ color: string
70
+ colWidth: number
71
+ trackHeight: number
72
+ offsetX: number
73
+ blockSize: number
74
+ }) {
75
+ if (!arcs?.length) {
76
+ return
77
+ }
78
+ const { xStart, xEnd } = visibleColRange({
79
+ offsetX,
80
+ blockWidth: blockSize,
81
+ colWidth,
82
+ })
83
+ let maxSpan = 1
84
+ for (const arc of arcs) {
85
+ maxSpan = Math.max(maxSpan, arc.end - arc.start)
86
+ }
87
+ // a full-height apex would put the stroke half outside the track
88
+ const apexRoom = trackHeight - 1
89
+ ctx.lineWidth = 1
90
+ for (const arc of arcs) {
91
+ // an arc that spans the block draws even though neither foot is inside it
92
+ if (arc.end < xStart || arc.start > xEnd) {
93
+ continue
94
+ }
95
+ const x1 = (arc.start + 0.5) * colWidth
96
+ const x2 = (arc.end + 0.5) * colWidth
97
+ const apex = apexRoom * Math.sqrt((arc.end - arc.start) / maxSpan)
98
+ ctx.strokeStyle = arc.color ?? color
99
+ ctx.beginPath()
100
+ ctx.moveTo(x1, trackHeight)
101
+ ctx.quadraticCurveTo((x1 + x2) / 2, trackHeight - 2 * apex, x2, trackHeight)
102
+ ctx.stroke()
103
+ }
104
+ }
105
+
55
106
  export function drawTextTrackContent({
56
107
  ctx,
57
108
  data,
58
109
  colorScheme,
59
- contrastScheme,
110
+ contrastText,
60
111
  bgColor,
61
- textColor,
112
+ drawLetters,
62
113
  colWidth,
63
114
  rowHeight,
64
115
  offsetX,
@@ -67,9 +118,9 @@ export function drawTextTrackContent({
67
118
  ctx: RenderCtx
68
119
  data: string | undefined
69
120
  colorScheme: Record<string, string>
70
- contrastScheme: Record<string, string>
121
+ contrastText: (color: string | undefined) => string
71
122
  bgColor: boolean
72
- textColor: string
123
+ drawLetters: boolean
73
124
  colWidth: number
74
125
  rowHeight: number
75
126
  offsetX: number
@@ -81,7 +132,6 @@ export function drawTextTrackContent({
81
132
  colWidth,
82
133
  })
83
134
  const str = data?.slice(xStart, xEnd)
84
- const drawLetters = rowHeight >= 10 && colWidth >= rowHeight / 2
85
135
 
86
136
  for (let i = 0; str && i < str.length; i++) {
87
137
  const letter = str[i]!
@@ -93,25 +143,77 @@ export function drawTextTrackContent({
93
143
  ctx.fillRect(x, 0, colWidth, rowHeight)
94
144
  }
95
145
  if (drawLetters) {
96
- // a letter on a colored tile needs the tile's contrast color; otherwise it
97
- // sits on the plain background and takes the theme's text color
98
- ctx.fillStyle = fill ? (contrastScheme[upper] ?? 'black') : textColor
99
- ctx.fillText(letter, x + colWidth / 2, rowHeight / 2 + 1)
146
+ ctx.fillStyle = contrastText(fill)
147
+ ctx.fillText(letter, x + colWidth / 2, rowHeight / 2)
148
+ }
149
+ }
150
+ }
151
+
152
+ // the smallest 1/2/5 x 10^n column step that leaves room for a label
153
+ export function rulerStep(colWidth: number, minPixels = 55) {
154
+ let step = 1
155
+ const mantissas = [1, 2, 5]
156
+ for (let i = 0; step * colWidth < minPixels; i++) {
157
+ step = mantissas[i % 3]! * 10 ** Math.floor(i / 3)
158
+ }
159
+ return step
160
+ }
161
+
162
+ const RULER_FONT_SIZE = 10
163
+ const TICK_HEIGHT = 4
164
+
165
+ export function drawColumnRuler({
166
+ ctx,
167
+ numColumns,
168
+ label,
169
+ textColor,
170
+ colWidth,
171
+ trackHeight,
172
+ offsetX,
173
+ blockSize,
174
+ }: {
175
+ ctx: RenderCtx
176
+ numColumns: number
177
+ label: (col: number) => string | undefined
178
+ textColor: string
179
+ colWidth: number
180
+ trackHeight: number
181
+ offsetX: number
182
+ blockSize: number
183
+ }) {
184
+ const { xStart, xEnd } = visibleColRange({
185
+ offsetX,
186
+ blockWidth: blockSize,
187
+ colWidth,
188
+ })
189
+ const step = rulerStep(colWidth)
190
+ const end = Math.min(xEnd, numColumns)
191
+ setFontSize(ctx, RULER_FONT_SIZE)
192
+ ctx.textAlign = 'center'
193
+ ctx.textBaseline = 'alphabetic'
194
+ ctx.fillStyle = textColor
195
+ ctx.strokeStyle = textColor
196
+ ctx.lineWidth = 1
197
+
198
+ for (let col = Math.ceil(xStart / step) * step; col < end; col += step) {
199
+ const text = label(col)
200
+ if (text === undefined) {
201
+ continue
100
202
  }
203
+ const x = (col + 0.5) * colWidth
204
+ ctx.fillText(text, x, trackHeight - TICK_HEIGHT - 2)
205
+ ctx.beginPath()
206
+ ctx.moveTo(x, trackHeight - TICK_HEIGHT)
207
+ ctx.lineTo(x, trackHeight)
208
+ ctx.stroke()
101
209
  }
102
210
  }
103
211
 
104
- // Cap height as a fraction of the font size. Every logo letter is scaled from
105
- // one reference font size to the height its frequency earns, and that scale is
106
- // only right if we know how tall the glyph actually draws. Measuring per letter
107
- // would be exact but `measureText` reports no vertical box in the SVG export
108
- // backend, so the ratio is a constant: the cap height of the sans-serif faces
109
- // both backends use, within a percent or two. It only has to be consistent --
110
- // the same ratio for every letter is what makes the slices sum to the stack
111
- // height instead of drifting apart.
212
+ // Cap height as a fraction of the font size, within a percent or two for the
213
+ // sans-serif faces both backends use. `measureText` reports no vertical box in
214
+ // the SVG export backend, so one constant ratio scales every logo letter, and
215
+ // the slices sum to the stack height.
112
216
  const CAP_HEIGHT_RATIO = 0.72
113
- // letters below this many pixels are noise, and a stack that thin reads better
114
- // as the bar chart it approximates
115
217
  const MIN_LETTER_PX = 3
116
218
 
117
219
  export function drawSequenceLogo({
@@ -142,8 +244,8 @@ export function drawSequenceLogo({
142
244
  })
143
245
  const end = Math.min(xEnd, colStats.numColumns)
144
246
 
145
- // one reference size for every glyph; each letter's own transform takes it
146
- // from here to the height it earned, so the font is set once for the block
247
+ // one reference font size for the block; each letter's transform scales it to
248
+ // a height proportional to its frequency
147
249
  const referenceFontSize = trackHeight
148
250
  setFontSize(ctx, referenceFontSize)
149
251
  ctx.textAlign = 'left'
@@ -156,9 +258,7 @@ export function drawSequenceLogo({
156
258
  continue
157
259
  }
158
260
  const x = col * colWidth
159
- // stack up from the baseline: the array is ascending, so the tallest letter
160
- // lands on top, which is the convention that makes a logo readable at a
161
- // glance
261
+ // the stack is ascending, so the tallest letter lands on top
162
262
  let bottom = trackHeight
163
263
  for (const { letter, bits } of stack) {
164
264
  const h = (bits / maxBits) * trackHeight
@@ -186,9 +286,9 @@ export function drawSequenceLogo({
186
286
 
187
287
  /**
188
288
  * Draw one track's content into a block of the alignment's column space, at
189
- * `offsetY` within the ctx. Owns the transform, so both callers -- the live
190
- * canvas blocks and the SVG export -- draw into the same coordinate space, and
191
- * adding a track kind means a `kind`, a draw function above, and a case here.
289
+ * `offsetY` within the ctx. Owns the transform, so the live canvas blocks and
290
+ * the SVG export draw into the same coordinate space. A new track kind needs a
291
+ * `kind`, a draw function above, and a case here.
192
292
  */
193
293
  export function drawTrackBlock({
194
294
  model,
@@ -197,7 +297,6 @@ export function drawTrackBlock({
197
297
  offsetX,
198
298
  offsetY = 0,
199
299
  theme,
200
- contrastScheme,
201
300
  blockSizeXOverride,
202
301
  highResScaleFactorOverride,
203
302
  }: {
@@ -207,7 +306,6 @@ export function drawTrackBlock({
207
306
  offsetX: number
208
307
  offsetY?: number
209
308
  theme: Theme
210
- contrastScheme: Record<string, string>
211
309
  blockSizeXOverride?: number
212
310
  highResScaleFactorOverride?: number
213
311
  }) {
@@ -219,6 +317,7 @@ export function drawTrackBlock({
219
317
  colorScheme: modelColorScheme,
220
318
  fontSize,
221
319
  rowHeight,
320
+ showMsaLetters,
222
321
  alphabetMaxBits,
223
322
  highResScaleFactor,
224
323
  } = model
@@ -227,6 +326,8 @@ export function drawTrackBlock({
227
326
  kind,
228
327
  height: trackHeight,
229
328
  barColor,
329
+ arcColor,
330
+ arcs,
230
331
  customColorScheme,
231
332
  data,
232
333
  } = track.model
@@ -251,6 +352,18 @@ export function drawTrackBlock({
251
352
  })
252
353
  break
253
354
  }
355
+ case 'arc': {
356
+ drawArcs({
357
+ ctx,
358
+ arcs,
359
+ color: arcColor ?? theme.palette.text.primary,
360
+ colWidth,
361
+ trackHeight,
362
+ offsetX,
363
+ blockSize: blockSizeX,
364
+ })
365
+ break
366
+ }
254
367
  case 'logo': {
255
368
  drawSequenceLogo({
256
369
  ctx,
@@ -265,16 +378,37 @@ export function drawTrackBlock({
265
378
  })
266
379
  break
267
380
  }
381
+ case 'ruler': {
382
+ const { relativeTo, numColumns } = model
383
+ drawColumnRuler({
384
+ ctx,
385
+ numColumns,
386
+ // with relativeTo set, number by the reference row's residues
387
+ label: relativeTo
388
+ ? col => {
389
+ const pos = model.visibleColToSeqPosOneBased(relativeTo, col)
390
+ return pos === undefined ? undefined : `${pos}`
391
+ }
392
+ : col => `${col + 1}`,
393
+ textColor,
394
+ colWidth,
395
+ trackHeight,
396
+ offsetX,
397
+ blockSize: blockSizeX,
398
+ })
399
+ break
400
+ }
268
401
  case 'text': {
269
402
  ctx.textAlign = 'center'
403
+ ctx.textBaseline = 'middle'
270
404
  setFontSize(ctx, fontSize)
271
405
  drawTextTrackContent({
272
406
  ctx,
273
407
  data,
274
408
  colorScheme: customColorScheme ?? modelColorScheme,
275
- contrastScheme,
409
+ contrastText: contrastTextFn(theme),
276
410
  bgColor,
277
- textColor,
411
+ drawLetters: showMsaLetters,
278
412
  colWidth,
279
413
  rowHeight,
280
414
  offsetX,
@@ -289,13 +423,12 @@ export function drawTrackBlock({
289
423
 
290
424
  /**
291
425
  * Every turned-on track stacked top to bottom, for the SVG export. The live
292
- * view draws the same content one canvas block at a time -- see TrackBlocks.
426
+ * view draws the same content one canvas block at a time in TrackBlocks.
293
427
  */
294
428
  export function renderAllTracks({
295
429
  model,
296
430
  ctx,
297
431
  offsetX,
298
- contrastScheme,
299
432
  theme,
300
433
  blockSizeXOverride,
301
434
  highResScaleFactorOverride,
@@ -303,7 +436,6 @@ export function renderAllTracks({
303
436
  model: MsaViewModel
304
437
  ctx: RenderCtx
305
438
  offsetX: number
306
- contrastScheme: Record<string, string>
307
439
  theme: Theme
308
440
  blockSizeXOverride?: number
309
441
  highResScaleFactorOverride?: number
@@ -317,7 +449,6 @@ export function renderAllTracks({
317
449
  offsetX,
318
450
  offsetY: currentY,
319
451
  theme,
320
- contrastScheme,
321
452
  blockSizeXOverride,
322
453
  highResScaleFactorOverride,
323
454
  })
@@ -0,0 +1,42 @@
1
+ import { useState } from 'react'
2
+
3
+ import type { MsaViewModel } from '../../model.ts'
4
+ import type React from 'react'
5
+
6
+ /**
7
+ * Translates pointer events over a track's row into the hovered column and a
8
+ * tooltip anchor. The track shares the alignment's columns, so hovering it sets
9
+ * the model's mouse column too and the alignment's hover band follows along.
10
+ *
11
+ * `tooltip` off skips the anchor, so a track whose tooltip is turned off still
12
+ * drives the hover band without re-rendering on every mouse move.
13
+ */
14
+ export function useTrackHover({
15
+ model,
16
+ tooltip,
17
+ }: {
18
+ model: MsaViewModel
19
+ tooltip: boolean
20
+ }) {
21
+ const [hover, setHover] = useState<{ col: number; x: number; y: number }>()
22
+
23
+ // the blocks are laid out in column space and scrolled by a transform on
24
+ // their container, so the pointer's column comes off the untransformed row
25
+ function onMouseMove(event: React.MouseEvent, el: HTMLElement) {
26
+ const { colWidth, scrollX, numColumns } = model
27
+ const { left } = el.getBoundingClientRect()
28
+ const col = Math.floor((event.clientX - left - scrollX) / colWidth)
29
+ const hit = col >= 0 && col < numColumns
30
+ model.setMousePos(hit ? col : undefined, undefined)
31
+ if (tooltip) {
32
+ setHover(hit ? { col, x: event.clientX, y: event.clientY } : undefined)
33
+ }
34
+ }
35
+
36
+ function onMouseLeave() {
37
+ setHover(undefined)
38
+ model.setMousePos(undefined, undefined)
39
+ }
40
+
41
+ return { hover: tooltip ? hover : undefined, onMouseMove, onMouseLeave }
42
+ }
@@ -0,0 +1,77 @@
1
+ import React from 'react'
2
+
3
+ import { useTheme } from '@mui/material'
4
+ import { observer } from 'mobx-react'
5
+
6
+ import {
7
+ bracketGap,
8
+ cladeHeight,
9
+ cladeInGutter,
10
+ cladeLabelHorizontal,
11
+ cladeLabelOffset,
12
+ } from './cladeBrackets.ts'
13
+
14
+ import type { MsaViewModel } from '../../model.ts'
15
+
16
+ /**
17
+ * The label of each bracket, in the gutter beside its bar, where the canvas
18
+ * draws the bar itself. The text is DOM text, turned on its side for a clade
19
+ * shorter than the font, the way the strip headers are; the SVG export draws
20
+ * the same labels with a `rotate(-90)`.
21
+ */
22
+ const CladeLabels = observer(function ({ model }: { model: MsaViewModel }) {
23
+ const {
24
+ resolvedClades,
25
+ cladeGutterWidth,
26
+ rowHeight,
27
+ treeAreaWidth,
28
+ fontSize,
29
+ } = model
30
+ const theme = useTheme()
31
+ if (cladeGutterWidth === 0) {
32
+ return null
33
+ }
34
+ const gutterLeft = treeAreaWidth - cladeGutterWidth
35
+ return (
36
+ <>
37
+ {resolvedClades.map((clade, index) => {
38
+ const { label, markColor, rows } = clade
39
+ if (!label || !cladeInGutter(clade)) {
40
+ return null
41
+ }
42
+ const left = gutterLeft + cladeLabelOffset(clade)
43
+ const horizontal = cladeLabelHorizontal(clade, rowHeight, fontSize)
44
+ return (
45
+ <div
46
+ key={`${rows[0]}-${rows[1]}-${index}`}
47
+ title={label}
48
+ style={{
49
+ position: 'absolute',
50
+ left,
51
+ top: rows[0] * rowHeight,
52
+ width: treeAreaWidth - left - bracketGap,
53
+ height: cladeHeight(clade, rowHeight),
54
+ display: 'flex',
55
+ alignItems: 'center',
56
+ color: markColor ?? theme.palette.text.primary,
57
+ fontSize,
58
+ overflow: 'hidden',
59
+ textOverflow: 'ellipsis',
60
+ whiteSpace: 'nowrap',
61
+ pointerEvents: 'none',
62
+ // vertical-rl reads top to bottom, and the half turn makes it
63
+ // read upwards, which is what rotate(-90) exports
64
+ ...(horizontal
65
+ ? {}
66
+ : { writingMode: 'vertical-rl', transform: 'rotate(180deg)' }),
67
+ }}
68
+ >
69
+ {label}
70
+ </div>
71
+ )
72
+ })}
73
+ </>
74
+ )
75
+ })
76
+
77
+ export default CladeLabels
@@ -6,14 +6,14 @@ import { observer } from 'mobx-react'
6
6
  import { useCanvasAutorun } from '../../useCanvasAutorun.ts'
7
7
  import { useWheelScroll } from '../../useWheelScroll.ts'
8
8
  import { referenceColor, treeHoverColor } from '../overlayColors.ts'
9
+ import CladeLabels from './CladeLabels.tsx'
9
10
  import TreeCanvasBlock from './TreeCanvasBlock.tsx'
10
- import { padding } from './renderTreeCanvas.ts'
11
11
 
12
12
  import type { MsaViewModel } from '../../model.ts'
13
13
 
14
14
  const TreeCanvas = observer(function ({ model }: { model: MsaViewModel }) {
15
15
  const ref = useRef<HTMLDivElement>(null)
16
- const { treeWidth, height, blocksY, treeAreaWidth, scrollY } = model
16
+ const { height, blocksY, treeAreaWidth, scrollY } = model
17
17
  const onScrollY = useCallback(
18
18
  (d: number) => {
19
19
  model.doScrollY(d)
@@ -77,7 +77,7 @@ const TreeCanvas = observer(function ({ model }: { model: MsaViewModel }) {
77
77
  style={{
78
78
  height,
79
79
  position: 'relative',
80
- width: treeWidth + padding,
80
+ width: treeAreaWidth,
81
81
  }}
82
82
  >
83
83
  {/* one transform for the whole block set, matching MSACanvas: the tree
@@ -94,6 +94,7 @@ const TreeCanvas = observer(function ({ model }: { model: MsaViewModel }) {
94
94
  {blocksY.map(block => (
95
95
  <TreeCanvasBlock key={block} model={model} offsetY={block} />
96
96
  ))}
97
+ <CladeLabels model={model} />
97
98
  </div>
98
99
  <canvas
99
100
  ref={mouseoverRef}