react-msaview 9.0.0 → 9.1.1

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 (352) hide show
  1. package/README.md +19 -10
  2. package/bundle/index.js +111 -115
  3. package/bundle/index.js.map +4 -4
  4. package/dist/blosum62.d.ts +3 -0
  5. package/dist/blosum62.js +43 -0
  6. package/dist/blosum62.js.map +1 -0
  7. package/dist/colorSchemes.js +2 -3
  8. package/dist/colorSchemes.js.map +1 -1
  9. package/dist/columnCounts.d.ts +0 -1
  10. package/dist/columnCounts.js +1 -1
  11. package/dist/columnCounts.js.map +1 -1
  12. package/dist/components/Loading.d.ts +3 -2
  13. package/dist/components/Loading.js +7 -7
  14. package/dist/components/Loading.js.map +1 -1
  15. package/dist/components/MSAView.d.ts +3 -2
  16. package/dist/components/MSAView.js +7 -4
  17. package/dist/components/MSAView.js.map +1 -1
  18. package/dist/components/MSAViewer.d.ts +1941 -4
  19. package/dist/components/MSAViewer.js +144 -201
  20. package/dist/components/MSAViewer.js.map +1 -1
  21. package/dist/components/MetadataTable.d.ts +4 -1
  22. package/dist/components/MetadataTable.js +55 -16
  23. package/dist/components/MetadataTable.js.map +1 -1
  24. package/dist/components/ResizeHandles.js +3 -2
  25. package/dist/components/ResizeHandles.js.map +1 -1
  26. package/dist/components/Track.js +8 -1
  27. package/dist/components/Track.js.map +1 -1
  28. package/dist/components/controls.d.ts +11 -0
  29. package/dist/components/controls.js +49 -0
  30. package/dist/components/controls.js.map +1 -0
  31. package/dist/components/dialogs/AnnotationFileDialog.js +12 -18
  32. package/dist/components/dialogs/AnnotationFileDialog.js.map +1 -1
  33. package/dist/components/dialogs/ExportSVGDialog.js +5 -7
  34. package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
  35. package/dist/components/dialogs/FeatureDialog.js +2 -2
  36. package/dist/components/dialogs/FeatureDialog.js.map +1 -1
  37. package/dist/components/{header/TreeSettingsMenu.d.ts → dialogs/GapThresholdDialog.d.ts} +3 -2
  38. package/dist/components/dialogs/GapThresholdDialog.js +15 -0
  39. package/dist/components/dialogs/GapThresholdDialog.js.map +1 -0
  40. package/dist/components/{header → dialogs}/GappynessSlider.d.ts +1 -1
  41. package/dist/components/{header → dialogs}/GappynessSlider.js +3 -10
  42. package/dist/components/dialogs/GappynessSlider.js.map +1 -0
  43. package/dist/components/{header → dialogs}/GoToBox.d.ts +4 -2
  44. package/dist/components/dialogs/GoToBox.js +48 -0
  45. package/dist/components/dialogs/GoToBox.js.map +1 -0
  46. package/dist/components/dialogs/GoToDialog.d.ts +6 -0
  47. package/dist/components/dialogs/GoToDialog.js +10 -0
  48. package/dist/components/dialogs/GoToDialog.js.map +1 -0
  49. package/dist/components/dialogs/HelpDialog.d.ts +6 -0
  50. package/dist/components/dialogs/HelpDialog.js +30 -0
  51. package/dist/components/dialogs/HelpDialog.js.map +1 -0
  52. package/dist/components/dialogs/MetadataDialog.js +11 -3
  53. package/dist/components/dialogs/MetadataDialog.js.map +1 -1
  54. package/dist/components/dialogs/goTo.d.ts +5 -0
  55. package/dist/components/{header → dialogs}/goTo.js +1 -1
  56. package/dist/components/dialogs/goTo.js.map +1 -0
  57. package/dist/components/dialogs/metadataLabels.d.ts +4 -0
  58. package/dist/components/dialogs/metadataLabels.js +52 -0
  59. package/dist/components/dialogs/metadataLabels.js.map +1 -0
  60. package/dist/components/dialogs/metadataRecord.d.ts +1 -0
  61. package/dist/components/dialogs/metadataRecord.js +38 -0
  62. package/dist/components/dialogs/metadataRecord.js.map +1 -0
  63. package/dist/components/header/Header.d.ts +6 -2
  64. package/dist/components/header/Header.js +30 -34
  65. package/dist/components/header/Header.js.map +1 -1
  66. package/dist/components/header/HiddenColumnsChip.d.ts +6 -0
  67. package/dist/components/header/HiddenColumnsChip.js +15 -0
  68. package/dist/components/header/HiddenColumnsChip.js.map +1 -0
  69. package/dist/components/header/{FileMenu.d.ts → MenuBar.d.ts} +3 -3
  70. package/dist/components/header/MenuBar.js +33 -0
  71. package/dist/components/header/MenuBar.js.map +1 -0
  72. package/dist/components/header/ScrollZoomCheckbox.d.ts +7 -0
  73. package/dist/components/header/ScrollZoomCheckbox.js +19 -0
  74. package/dist/components/header/ScrollZoomCheckbox.js.map +1 -0
  75. package/dist/components/header/ZoomControls.js +12 -48
  76. package/dist/components/header/ZoomControls.js.map +1 -1
  77. package/dist/components/header/colorSchemeMenuItems.d.ts +4 -0
  78. package/dist/components/header/colorSchemeMenuItems.js +106 -0
  79. package/dist/components/header/colorSchemeMenuItems.js.map +1 -0
  80. package/dist/components/header/getAnnotationsMenu.d.ts +3 -30
  81. package/dist/components/header/getAnnotationsMenu.js +48 -54
  82. package/dist/components/header/getAnnotationsMenu.js.map +1 -1
  83. package/dist/components/header/menuBarItems.d.ts +11 -0
  84. package/dist/components/header/menuBarItems.js +277 -0
  85. package/dist/components/header/menuBarItems.js.map +1 -0
  86. package/dist/components/import/ImportForm.js +12 -6
  87. package/dist/components/import/ImportForm.js.map +1 -1
  88. package/dist/components/import/data/seq2.d.ts +0 -1
  89. package/dist/components/import/data/seq2.js +0 -17
  90. package/dist/components/import/data/seq2.js.map +1 -1
  91. package/dist/components/minimap/Minimap.js +7 -3
  92. package/dist/components/minimap/Minimap.js.map +1 -1
  93. package/dist/components/minimap/MinimapSVG.js +2 -1
  94. package/dist/components/minimap/MinimapSVG.js.map +1 -1
  95. package/dist/components/minimap/minimapLayout.d.ts +12 -0
  96. package/dist/components/minimap/minimapLayout.js +20 -0
  97. package/dist/components/minimap/minimapLayout.js.map +1 -1
  98. package/dist/components/msa/MSACanvas.js +28 -10
  99. package/dist/components/msa/MSACanvas.js.map +1 -1
  100. package/dist/components/msa/MSACanvasBlock.js +17 -16
  101. package/dist/components/msa/MSACanvasBlock.js.map +1 -1
  102. package/dist/components/msa/MSAMouseoverCanvas.js +2 -2
  103. package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
  104. package/dist/components/msa/WheelZoomHint.d.ts +7 -0
  105. package/dist/components/msa/WheelZoomHint.js +38 -0
  106. package/dist/components/msa/WheelZoomHint.js.map +1 -0
  107. package/dist/components/msa/drawFeatureSpans.d.ts +50 -11
  108. package/dist/components/msa/drawFeatureSpans.js +99 -56
  109. package/dist/components/msa/drawFeatureSpans.js.map +1 -1
  110. package/dist/components/msa/msaKeys.js +3 -0
  111. package/dist/components/msa/msaKeys.js.map +1 -1
  112. package/dist/components/msa/msaRaster.d.ts +14 -2
  113. package/dist/components/msa/msaRaster.js +20 -10
  114. package/dist/components/msa/msaRaster.js.map +1 -1
  115. package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +9 -0
  116. package/dist/components/msa/renderBoxFeatureCanvasBlock.js +39 -8
  117. package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
  118. package/dist/components/msa/renderHighlights.d.ts +2 -5
  119. package/dist/components/msa/renderHighlights.js +5 -6
  120. package/dist/components/msa/renderHighlights.js.map +1 -1
  121. package/dist/components/msa/renderMSABlock.d.ts +6 -1
  122. package/dist/components/msa/renderMSABlock.js +44 -17
  123. package/dist/components/msa/renderMSABlock.js.map +1 -1
  124. package/dist/components/msa/renderMSAMouseover.js +2 -1
  125. package/dist/components/msa/renderMSAMouseover.js.map +1 -1
  126. package/dist/components/msa/tileColor.js +7 -0
  127. package/dist/components/msa/tileColor.js.map +1 -1
  128. package/dist/components/renderCtx.d.ts +1 -1
  129. package/dist/components/rowpanels/RowPanelBlock.js +2 -2
  130. package/dist/components/rowpanels/RowPanelBlock.js.map +1 -1
  131. package/dist/components/rowpanels/renderFeaturePanel.d.ts +5 -1
  132. package/dist/components/rowpanels/renderFeaturePanel.js +12 -5
  133. package/dist/components/rowpanels/renderFeaturePanel.js.map +1 -1
  134. package/dist/components/settings/MenuItemsForm.d.ts +10 -0
  135. package/dist/components/settings/MenuItemsForm.js +80 -0
  136. package/dist/components/settings/MenuItemsForm.js.map +1 -0
  137. package/dist/components/settings/SettingsPanel.d.ts +12 -0
  138. package/dist/components/settings/SettingsPanel.js +92 -0
  139. package/dist/components/settings/SettingsPanel.js.map +1 -0
  140. package/dist/components/{header/ZoomMenu.d.ts → settings/TrackList.d.ts} +2 -2
  141. package/dist/components/settings/TrackList.js +55 -0
  142. package/dist/components/settings/TrackList.js.map +1 -0
  143. package/dist/components/tracks/TrackBlocks.js +2 -2
  144. package/dist/components/tracks/TrackBlocks.js.map +1 -1
  145. package/dist/components/tracks/drawTracks.d.ts +1 -53
  146. package/dist/components/tracks/drawTracks.js +5 -5
  147. package/dist/components/tracks/drawTracks.js.map +1 -1
  148. package/dist/components/tree/CladeLabels.d.ts +1 -1
  149. package/dist/components/tree/CladeLabels.js +22 -34
  150. package/dist/components/tree/CladeLabels.js.map +1 -1
  151. package/dist/components/tree/TreeCanvasBlock.js +2 -2
  152. package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
  153. package/dist/components/tree/TreeMenu.js +4 -6
  154. package/dist/components/tree/TreeMenu.js.map +1 -1
  155. package/dist/components/tree/TreeOverview.js +2 -2
  156. package/dist/components/tree/TreeOverview.js.map +1 -1
  157. package/dist/components/tree/cladeBrackets.d.ts +17 -10
  158. package/dist/components/tree/cladeBrackets.js +33 -3
  159. package/dist/components/tree/cladeBrackets.js.map +1 -1
  160. package/dist/components/tree/renderTreeCanvas.js +2 -8
  161. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  162. package/dist/components/tree/renderTreeOverview.js +4 -11
  163. package/dist/components/tree/renderTreeOverview.js.map +1 -1
  164. package/dist/constants.d.ts +4 -1
  165. package/dist/constants.js +7 -1
  166. package/dist/constants.js.map +1 -1
  167. package/dist/darkReader.d.ts +7 -0
  168. package/dist/darkReader.js +42 -0
  169. package/dist/darkReader.js.map +1 -0
  170. package/dist/element.js +25 -53
  171. package/dist/element.js.map +1 -1
  172. package/dist/exportLayout.d.ts +39 -0
  173. package/dist/exportLayout.js +78 -0
  174. package/dist/exportLayout.js.map +1 -0
  175. package/dist/featurePanels.d.ts +37 -0
  176. package/dist/featurePanels.js +187 -0
  177. package/dist/featurePanels.js.map +1 -0
  178. package/dist/filehandleLoader.d.ts +41 -0
  179. package/dist/filehandleLoader.js +99 -0
  180. package/dist/filehandleLoader.js.map +1 -0
  181. package/dist/headlessRenderEnv.d.ts +12 -39
  182. package/dist/headlessRenderEnv.js +18 -12
  183. package/dist/headlessRenderEnv.js.map +1 -1
  184. package/dist/hierarchy.d.ts +5 -8
  185. package/dist/hierarchy.js +5 -79
  186. package/dist/hierarchy.js.map +1 -1
  187. package/dist/index.d.ts +6 -1
  188. package/dist/index.js +6 -1
  189. package/dist/index.js.map +1 -1
  190. package/dist/measureTextCanvas.d.ts +7 -0
  191. package/dist/measureTextCanvas.js +8 -6
  192. package/dist/measureTextCanvas.js.map +1 -1
  193. package/dist/model/treeModel.d.ts +6 -2
  194. package/dist/model/treeModel.js +8 -4
  195. package/dist/model/treeModel.js.map +1 -1
  196. package/dist/model.d.ts +180 -76
  197. package/dist/model.js +358 -618
  198. package/dist/model.js.map +1 -1
  199. package/dist/neighborJoining.js +1 -40
  200. package/dist/neighborJoining.js.map +1 -1
  201. package/dist/renderToSvg.d.ts +2 -7
  202. package/dist/renderToSvg.js +33 -133
  203. package/dist/renderToSvg.js.map +1 -1
  204. package/dist/rerootTree.d.ts +1 -0
  205. package/dist/rerootTree.js +7 -6
  206. package/dist/rerootTree.js.map +1 -1
  207. package/dist/schemeResidueColor.d.ts +12 -0
  208. package/dist/schemeResidueColor.js +33 -0
  209. package/dist/schemeResidueColor.js.map +1 -0
  210. package/dist/similarityColors.d.ts +11 -0
  211. package/dist/similarityColors.js +90 -0
  212. package/dist/similarityColors.js.map +1 -0
  213. package/dist/svgTestUtil.d.ts +74 -32
  214. package/dist/treeDisplay.d.ts +37 -0
  215. package/dist/treeDisplay.js +209 -0
  216. package/dist/treeDisplay.js.map +1 -0
  217. package/dist/types.d.ts +6 -3
  218. package/dist/useWheelScroll.d.ts +3 -1
  219. package/dist/useWheelScroll.js +36 -17
  220. package/dist/useWheelScroll.js.map +1 -1
  221. package/dist/util.d.ts +2 -0
  222. package/dist/util.js +2 -0
  223. package/dist/util.js.map +1 -1
  224. package/dist/version.d.ts +1 -1
  225. package/dist/version.js +1 -1
  226. package/dist/viewerSnapshot.d.ts +169 -0
  227. package/dist/viewerSnapshot.js +100 -0
  228. package/dist/viewerSnapshot.js.map +1 -0
  229. package/dist/wheelZoom.d.ts +8 -3
  230. package/dist/wheelZoom.js +44 -32
  231. package/dist/wheelZoom.js.map +1 -1
  232. package/dist/zoomSnapshot.d.ts +29 -0
  233. package/dist/zoomSnapshot.js +47 -0
  234. package/dist/zoomSnapshot.js.map +1 -0
  235. package/package.json +11 -11
  236. package/src/blosum62.ts +45 -0
  237. package/src/colorSchemes.ts +2 -4
  238. package/src/columnCounts.ts +1 -1
  239. package/src/components/Loading.tsx +25 -14
  240. package/src/components/MSAView.tsx +22 -5
  241. package/src/components/MSAViewer.tsx +275 -251
  242. package/src/components/MetadataTable.tsx +83 -26
  243. package/src/components/ResizeHandles.tsx +9 -2
  244. package/src/components/Track.tsx +15 -1
  245. package/src/components/controls.ts +62 -0
  246. package/src/components/dialogs/AnnotationFileDialog.tsx +16 -21
  247. package/src/components/dialogs/ExportSVGDialog.tsx +8 -19
  248. package/src/components/dialogs/FeatureDialog.tsx +2 -5
  249. package/src/components/dialogs/GapThresholdDialog.tsx +36 -0
  250. package/src/components/{header → dialogs}/GappynessSlider.tsx +3 -10
  251. package/src/components/{header → dialogs}/GoToBox.tsx +36 -10
  252. package/src/components/dialogs/GoToDialog.tsx +30 -0
  253. package/src/components/dialogs/HelpDialog.tsx +79 -0
  254. package/src/components/dialogs/MetadataDialog.tsx +32 -4
  255. package/src/components/{header → dialogs}/goTo.ts +1 -1
  256. package/src/components/dialogs/metadataLabels.ts +54 -0
  257. package/src/components/dialogs/metadataRecord.tsx +61 -0
  258. package/src/components/header/Header.tsx +75 -44
  259. package/src/components/header/HiddenColumnsChip.tsx +39 -0
  260. package/src/components/header/MenuBar.tsx +64 -0
  261. package/src/components/header/ScrollZoomCheckbox.tsx +46 -0
  262. package/src/components/header/ZoomControls.tsx +23 -74
  263. package/src/components/header/colorSchemeMenuItems.ts +121 -0
  264. package/src/components/header/getAnnotationsMenu.ts +52 -56
  265. package/src/components/header/menuBarItems.ts +357 -0
  266. package/src/components/import/ImportForm.tsx +19 -7
  267. package/src/components/import/data/seq2.ts +0 -18
  268. package/src/components/minimap/Minimap.tsx +11 -3
  269. package/src/components/minimap/MinimapSVG.tsx +17 -1
  270. package/src/components/minimap/minimapLayout.ts +27 -0
  271. package/src/components/msa/MSACanvas.tsx +24 -4
  272. package/src/components/msa/MSACanvasBlock.tsx +20 -17
  273. package/src/components/msa/MSAMouseoverCanvas.tsx +2 -2
  274. package/src/components/msa/WheelZoomHint.tsx +56 -0
  275. package/src/components/msa/drawFeatureSpans.ts +160 -79
  276. package/src/components/msa/msaKeys.ts +3 -0
  277. package/src/components/msa/msaRaster.ts +26 -10
  278. package/src/components/msa/renderBoxFeatureCanvasBlock.ts +62 -24
  279. package/src/components/msa/renderHighlights.ts +5 -6
  280. package/src/components/msa/renderMSABlock.ts +51 -15
  281. package/src/components/msa/renderMSAMouseover.ts +5 -1
  282. package/src/components/msa/tileColor.ts +7 -0
  283. package/src/components/renderCtx.ts +0 -1
  284. package/src/components/rowpanels/RowPanelBlock.tsx +2 -2
  285. package/src/components/rowpanels/renderFeaturePanel.ts +26 -7
  286. package/src/components/settings/MenuItemsForm.tsx +225 -0
  287. package/src/components/settings/SettingsPanel.tsx +156 -0
  288. package/src/components/settings/TrackList.tsx +119 -0
  289. package/src/components/tracks/TrackBlocks.tsx +2 -2
  290. package/src/components/tracks/drawTracks.ts +5 -5
  291. package/src/components/tree/CladeLabels.tsx +30 -54
  292. package/src/components/tree/TreeCanvasBlock.tsx +2 -2
  293. package/src/components/tree/TreeMenu.tsx +4 -6
  294. package/src/components/tree/TreeOverview.tsx +2 -2
  295. package/src/components/tree/cladeBrackets.ts +50 -3
  296. package/src/components/tree/renderTreeCanvas.ts +2 -13
  297. package/src/components/tree/renderTreeOverview.ts +7 -14
  298. package/src/constants.ts +9 -1
  299. package/src/darkReader.ts +57 -0
  300. package/src/element.ts +37 -64
  301. package/src/exportLayout.ts +134 -0
  302. package/src/featurePanels.ts +269 -0
  303. package/src/filehandleLoader.ts +136 -0
  304. package/src/headlessRenderEnv.ts +24 -11
  305. package/src/hierarchy.ts +5 -88
  306. package/src/index.ts +9 -5
  307. package/src/measureTextCanvas.ts +8 -6
  308. package/src/model/treeModel.ts +9 -3
  309. package/src/model.ts +452 -807
  310. package/src/neighborJoining.ts +1 -42
  311. package/src/renderToSvg.tsx +56 -207
  312. package/src/rerootTree.ts +7 -6
  313. package/src/schemeResidueColor.ts +37 -0
  314. package/src/similarityColors.ts +112 -0
  315. package/src/treeDisplay.ts +278 -0
  316. package/src/types.ts +6 -4
  317. package/src/useWheelScroll.ts +43 -22
  318. package/src/util.ts +3 -0
  319. package/src/version.ts +1 -1
  320. package/src/viewerSnapshot.ts +147 -0
  321. package/src/wheelZoom.ts +55 -33
  322. package/src/zoomSnapshot.ts +80 -0
  323. package/dist/components/header/ColorSchemeMenu.d.ts +0 -12
  324. package/dist/components/header/ColorSchemeMenu.js +0 -37
  325. package/dist/components/header/ColorSchemeMenu.js.map +0 -1
  326. package/dist/components/header/FileMenu.js +0 -66
  327. package/dist/components/header/FileMenu.js.map +0 -1
  328. package/dist/components/header/GappynessSlider.js.map +0 -1
  329. package/dist/components/header/GoToBox.js +0 -31
  330. package/dist/components/header/GoToBox.js.map +0 -1
  331. package/dist/components/header/MSASettingsMenu.d.ts +0 -6
  332. package/dist/components/header/MSASettingsMenu.js +0 -11
  333. package/dist/components/header/MSASettingsMenu.js.map +0 -1
  334. package/dist/components/header/ScrollZoomIcons.d.ts +0 -6
  335. package/dist/components/header/ScrollZoomIcons.js +0 -35
  336. package/dist/components/header/ScrollZoomIcons.js.map +0 -1
  337. package/dist/components/header/TreeSettingsMenu.js +0 -42
  338. package/dist/components/header/TreeSettingsMenu.js.map +0 -1
  339. package/dist/components/header/ZoomMenu.js +0 -37
  340. package/dist/components/header/ZoomMenu.js.map +0 -1
  341. package/dist/components/header/goTo.d.ts +0 -20
  342. package/dist/components/header/goTo.js.map +0 -1
  343. package/dist/components/header/settingsMenuItems.d.ts +0 -4
  344. package/dist/components/header/settingsMenuItems.js +0 -127
  345. package/dist/components/header/settingsMenuItems.js.map +0 -1
  346. package/src/components/header/ColorSchemeMenu.tsx +0 -56
  347. package/src/components/header/FileMenu.tsx +0 -81
  348. package/src/components/header/MSASettingsMenu.tsx +0 -26
  349. package/src/components/header/ScrollZoomIcons.tsx +0 -52
  350. package/src/components/header/TreeSettingsMenu.tsx +0 -60
  351. package/src/components/header/ZoomMenu.tsx +0 -48
  352. package/src/components/header/settingsMenuItems.ts +0 -157
@@ -0,0 +1,100 @@
1
+ import { createJBrowseTheme } from '@jbrowse/core/ui/theme';
2
+ export function colorSchemeSnapshot(scheme) {
3
+ return typeof scheme === 'string'
4
+ ? { colorSchemeName: scheme }
5
+ : scheme
6
+ ? { customColorScheme: scheme.map }
7
+ : {};
8
+ }
9
+ /**
10
+ * The `highlightColumns` prop as `highlights`: one `{start, end}` per run of
11
+ * adjacent 1-based alignment columns
12
+ */
13
+ export function columnHighlights(columns = []) {
14
+ const sorted = [...new Set(columns)].sort((a, b) => a - b);
15
+ const runs = [];
16
+ for (const column of sorted) {
17
+ const last = runs.at(-1);
18
+ if (last?.end === column - 1) {
19
+ last.end = column;
20
+ }
21
+ else {
22
+ runs.push({ start: column, end: column });
23
+ }
24
+ }
25
+ return runs;
26
+ }
27
+ export function viewerHighlights({ highlights = [], highlightColumns, }) {
28
+ return [...highlights, ...columnHighlights(highlightColumns)];
29
+ }
30
+ function urlLocation(uri) {
31
+ return uri ? { uri, locationType: 'UriLocation' } : undefined;
32
+ }
33
+ /** each filehandle prop, or the URL prop standing in for it */
34
+ export function fileLocations({ msaFilehandle, treeFilehandle, gffFilehandle, msaUrl, treeUrl, gffUrl, }) {
35
+ return {
36
+ msaFilehandle: msaFilehandle ?? urlLocation(msaUrl),
37
+ treeFilehandle: treeFilehandle ?? urlLocation(treeUrl),
38
+ gffFilehandle: gffFilehandle ?? urlLocation(gffUrl),
39
+ };
40
+ }
41
+ export function resolveTheme(theme) {
42
+ return createJBrowseTheme(theme === 'dark'
43
+ ? { palette: { mode: 'dark' } }
44
+ : typeof theme === 'object'
45
+ ? theme
46
+ : undefined);
47
+ }
48
+ /**
49
+ * The model snapshot `MSAViewer` creates from its props. The CLI's `--props`
50
+ * reads the same JSON the R and Python widgets send, so a figure exported
51
+ * headlessly draws what the widget drew.
52
+ */
53
+ export function viewerSnapshot(props) {
54
+ const { msa, tree, gff, rowData, colorScheme, height, colWidth, rowHeight, allowedGappyness, highlightColumns, highlights, features, selection, clades, relativeTo, columnTracks, residueMappings, encodings, rowPanels, drawTree, treeAreaWidth, showBranchLen, treeOrder, treeRoot, region, residueEncoding, } = props;
55
+ const { msaFilehandle, treeFilehandle, gffFilehandle } = fileLocations(props);
56
+ return {
57
+ type: 'MsaView',
58
+ ...(msa || tree || gff || rowData
59
+ ? {
60
+ data: {
61
+ msa: msa ?? '',
62
+ tree: tree ?? '',
63
+ gff,
64
+ // the row table is stored as this JSON string, which is what a
65
+ // shared URL and the size limit already cover
66
+ ...(rowData ? { treeMetadata: JSON.stringify(rowData) } : {}),
67
+ },
68
+ }
69
+ : {}),
70
+ ...(msaFilehandle ? { msaFilehandle } : {}),
71
+ ...(treeFilehandle ? { treeFilehandle } : {}),
72
+ ...(gffFilehandle ? { gffFilehandle } : {}),
73
+ ...colorSchemeSnapshot(colorScheme),
74
+ ...(height ? { height } : {}),
75
+ ...(colWidth ? { colWidth } : {}),
76
+ ...(rowHeight ? { rowHeight } : {}),
77
+ ...(allowedGappyness !== undefined ? { allowedGappyness } : {}),
78
+ ...(highlights || highlightColumns
79
+ ? { highlights: viewerHighlights({ highlights, highlightColumns }) }
80
+ : {}),
81
+ ...(features ? { features } : {}),
82
+ ...(selection ? { selection } : {}),
83
+ ...(clades ? { clades } : {}),
84
+ ...(relativeTo ? { relativeTo } : {}),
85
+ ...(columnTracks ? { columnTracks } : {}),
86
+ ...(residueMappings ? { residueMappings } : {}),
87
+ ...(encodings ? { encodings } : {}),
88
+ ...(rowPanels ? { rowPanels } : {}),
89
+ ...(drawTree !== undefined ? { drawTree } : {}),
90
+ ...(treeAreaWidth ? { treeAreaWidth } : {}),
91
+ ...(showBranchLen !== undefined ? { showBranchLen } : {}),
92
+ ...(treeOrder ? { treeOrder } : {}),
93
+ ...(treeRoot ? { treeRoot } : {}),
94
+ ...(region ? { region } : {}),
95
+ ...(residueEncoding !== undefined
96
+ ? { bgColor: residueEncoding === 'fill' }
97
+ : {}),
98
+ };
99
+ }
100
+ //# sourceMappingURL=viewerSnapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewerSnapshot.js","sourceRoot":"","sources":["../src/viewerSnapshot.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,9 @@
1
- export declare const SCROLL_ZOOM_DIVISOR = 500;
1
+ export declare const NOTCH_ZOOM = 1.25;
2
2
  export declare function normalizeWheelDelta(delta: number, mode: number): number;
3
- export declare function getZoomNormalizer(deltaY: number): 25 | 75 | 150 | 500;
4
- export declare function zoomFactorFromAccum(zoomAccum: number, elapsedMs: number): number;
3
+ export declare class WheelZoomSmoother {
4
+ private continuous;
5
+ private pending;
6
+ add(deltaY: number, deltaMode: number, isPinch: boolean): void;
7
+ get idle(): boolean;
8
+ step(elapsedMs: number): number;
9
+ }
package/dist/wheelZoom.js CHANGED
@@ -1,43 +1,55 @@
1
- // Wheel / trackpad-pinch delta handling, adapted from @jbrowse/core's
2
- // util/wheelZoom (not yet in our pinned @jbrowse/core). Turns raw wheel deltas
3
- // into a per-frame zoom factor that feels consistent across fine trackpad
4
- // pinches and coarse mouse notches.
5
- // Fixed divisor for plain-wheel scroll-zoom mode, where deltas are big notches.
6
- export const SCROLL_ZOOM_DIVISOR = 500;
7
- // Cap the zoom change per millisecond so a burst of momentum-scroll events
8
- // coalesced into one frame can't jump the zoom level (0.2 per ~60fps frame).
9
- const MAX_ZOOM_RATE_PER_MS = 0.2 / 16.67;
10
- // Convert a wheel delta to pixels regardless of the browser's deltaMode; some
11
- // browsers/mice report lines or pages instead of pixels.
1
+ // Chrome and Firefox encode a trackpad pinch as ctrl+wheel with
2
+ // deltaY = -100 * ln(scale), so dividing by 100 tracks the fingers 1:1
3
+ const PINCH_PX_PER_LOG = 100;
4
+ // a plain scroll covers more pixels than a pinch for the same intent
5
+ const SCROLL_PX_PER_LOG = 400;
6
+ // a pixel delta at least this large counts as a wheel notch
7
+ const NOTCH_MIN_PX = 40;
8
+ export const NOTCH_ZOOM = 1.25;
9
+ // the time constant a notch eases in over
10
+ const NOTCH_TAU_MS = 60;
11
+ // a burst of continuous events coalesced into one frame applies at most 2x
12
+ const MAX_FRAME_LOG = Math.log(2);
13
+ // the queue holds at most four notches, which caps a fast spin
14
+ const MAX_PENDING_LOG = 4 * Math.log(NOTCH_ZOOM);
12
15
  export function normalizeWheelDelta(delta, mode) {
13
16
  if (mode === 1) {
14
- return delta * 16; // DOM_DELTA_LINE
17
+ return delta * 16;
15
18
  }
16
19
  if (mode === 2) {
17
- return delta * 100; // DOM_DELTA_PAGE
20
+ return delta * 100;
18
21
  }
19
- return delta; // DOM_DELTA_PIXEL
22
+ return delta;
20
23
  }
21
- // Adaptive divisor: tiny pinch deltas zoom in larger steps, big mouse notches
22
- // in finer steps, so a trackpad pinch and a mouse wheel feel similar.
23
- export function getZoomNormalizer(deltaY) {
24
- const abs = Math.abs(deltaY);
25
- if (abs < 6) {
26
- return 25;
24
+ const clampAbs = (x, max) => Math.max(-max, Math.min(max, x));
25
+ // Positive log zooms in. Feed every wheel event to add() and call step() once
26
+ // per animation frame with the time since the last frame; step() returns the
27
+ // multiplier for colWidth/rowHeight.
28
+ export class WheelZoomSmoother {
29
+ continuous = 0;
30
+ pending = 0;
31
+ add(deltaY, deltaMode, isPinch) {
32
+ const px = normalizeWheelDelta(deltaY, deltaMode);
33
+ if (deltaMode !== 0 || Math.abs(px) >= NOTCH_MIN_PX) {
34
+ const notches = deltaMode !== 0 ? 1 : Math.min(Math.max(Math.abs(px) / 100, 1), 3);
35
+ this.pending = clampAbs(this.pending - Math.sign(px) * notches * Math.log(NOTCH_ZOOM), MAX_PENDING_LOG);
36
+ }
37
+ else {
38
+ this.continuous -= px / (isPinch ? PINCH_PX_PER_LOG : SCROLL_PX_PER_LOG);
39
+ }
27
40
  }
28
- if (abs > 150) {
29
- return 500;
41
+ get idle() {
42
+ return this.continuous === 0 && this.pending === 0;
30
43
  }
31
- if (abs > 30) {
32
- return 150;
44
+ step(elapsedMs) {
45
+ let eased = this.pending * (1 - Math.exp(-elapsedMs / NOTCH_TAU_MS));
46
+ if (Math.abs(this.pending - eased) < 0.005) {
47
+ eased = this.pending;
48
+ }
49
+ this.pending -= eased;
50
+ const log = clampAbs(this.continuous + eased, MAX_FRAME_LOG);
51
+ this.continuous = 0;
52
+ return Math.exp(log);
33
53
  }
34
- return 75;
35
- }
36
- // Turn accumulated, normalized zoom intent into a colWidth/rowHeight multiplier.
37
- // Positive accum (wheel toward user) zooms out (factor < 1); negative zooms in.
38
- export function zoomFactorFromAccum(zoomAccum, elapsedMs) {
39
- const max = MAX_ZOOM_RATE_PER_MS * elapsedMs;
40
- const d = Math.max(-max, Math.min(max, zoomAccum));
41
- return d > 0 ? 1 / (1 + d) : 1 - d;
42
54
  }
43
55
  //# sourceMappingURL=wheelZoom.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wheelZoom.js","sourceRoot":"","sources":["../src/wheelZoom.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,+EAA+E;AAC/E,0EAA0E;AAC1E,oCAAoC;AAEpC,gFAAgF;AAChF,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAA;AAEtC,2EAA2E;AAC3E,6EAA6E;AAC7E,MAAM,oBAAoB,GAAG,GAAG,GAAG,KAAK,CAAA;AAExC,8EAA8E;AAC9E,yDAAyD;AACzD,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,IAAY;IAC7D,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;QACf,OAAO,KAAK,GAAG,EAAE,CAAA,CAAC,iBAAiB;IACrC,CAAC;IACD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;QACf,OAAO,KAAK,GAAG,GAAG,CAAA,CAAC,iBAAiB;IACtC,CAAC;IACD,OAAO,KAAK,CAAA,CAAC,kBAAkB;AACjC,CAAC;AAED,8EAA8E;AAC9E,sEAAsE;AACtE,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAC5B,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACZ,OAAO,EAAE,CAAA;IACX,CAAC;IACD,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;QACd,OAAO,GAAG,CAAA;IACZ,CAAC;IACD,IAAI,GAAG,GAAG,EAAE,EAAE,CAAC;QACb,OAAO,GAAG,CAAA;IACZ,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC;AAED,iFAAiF;AACjF,gFAAgF;AAChF,MAAM,UAAU,mBAAmB,CAAC,SAAiB,EAAE,SAAiB;IACtE,MAAM,GAAG,GAAG,oBAAoB,GAAG,SAAS,CAAA;IAC5C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAA;IAClD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;AACpC,CAAC"}
1
+ {"version":3,"file":"wheelZoom.js","sourceRoot":"","sources":["../src/wheelZoom.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ export interface ZoomSnapshot {
2
+ colWidth: number;
3
+ rowHeight: number;
4
+ blocksX: number[];
5
+ blocksY: number[];
6
+ }
7
+ interface Viewport {
8
+ colWidth: number;
9
+ rowHeight: number;
10
+ scrollX: number;
11
+ scrollY: number;
12
+ msaAreaWidth: number;
13
+ msaAreaHeight: number;
14
+ totalWidth: number;
15
+ totalHeight: number;
16
+ blockSize: number;
17
+ }
18
+ export declare function takeZoomSnapshot(view: Viewport, withMargin: boolean): {
19
+ colWidth: number;
20
+ rowHeight: number;
21
+ blocksX: number[];
22
+ blocksY: number[];
23
+ };
24
+ export declare function zoomSnapshotScale(view: Viewport, snap: ZoomSnapshot): {
25
+ sx: number;
26
+ sy: number;
27
+ };
28
+ export declare function zoomSnapshotCovers(view: Viewport, snap: ZoomSnapshot): boolean;
29
+ export {};
@@ -0,0 +1,47 @@
1
+ import { calculateBlocks } from './calculateBlocks.js';
2
+ // past this stretch the scaled letters blur enough to redraw
3
+ const maxStretch = 2;
4
+ // a redraw covers this fraction of the viewport again on each side, so a zoom
5
+ // out shrinks it for a few frames before it runs out of picture
6
+ const margin = 0.2;
7
+ function blocksAt(view, axis, scale, marginFraction) {
8
+ const size = axis === 'x' ? view.msaAreaWidth : view.msaAreaHeight;
9
+ const pos = -(axis === 'x' ? view.scrollX : view.scrollY);
10
+ const map = axis === 'x' ? view.totalWidth : view.totalHeight;
11
+ const pad = size * marginFraction;
12
+ return calculateBlocks({
13
+ viewportSize: (size + 2 * pad) / scale,
14
+ viewportPos: (pos - pad) / scale,
15
+ mapSize: map / scale,
16
+ blockSize: view.blockSize,
17
+ });
18
+ }
19
+ const within = (need, have) => need.length === 0 ||
20
+ (have.length > 0 && need[0] >= have[0] && need.at(-1) <= have.at(-1));
21
+ // a gesture starts from the blocks already drawn, and each redraw during it
22
+ // adds the margin
23
+ export function takeZoomSnapshot(view, withMargin) {
24
+ const m = withMargin ? margin : 0;
25
+ return {
26
+ colWidth: view.colWidth,
27
+ rowHeight: view.rowHeight,
28
+ blocksX: blocksAt(view, 'x', 1, m),
29
+ blocksY: blocksAt(view, 'y', 1, m),
30
+ };
31
+ }
32
+ export function zoomSnapshotScale(view, snap) {
33
+ return {
34
+ sx: view.colWidth / snap.colWidth,
35
+ sy: view.rowHeight / snap.rowHeight,
36
+ };
37
+ }
38
+ // whether the blocks drawn at the snapshot, stretched to the current cell
39
+ // size, still fill the viewport sharply enough
40
+ export function zoomSnapshotCovers(view, snap) {
41
+ const { sx, sy } = zoomSnapshotScale(view, snap);
42
+ return (sx <= maxStretch &&
43
+ sy <= maxStretch &&
44
+ within(blocksAt(view, 'x', sx, 0), snap.blocksX) &&
45
+ within(blocksAt(view, 'y', sy, 0), snap.blocksY));
46
+ }
47
+ //# sourceMappingURL=zoomSnapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zoomSnapshot.js","sourceRoot":"","sources":["../src/zoomSnapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAqBtD,6DAA6D;AAC7D,MAAM,UAAU,GAAG,CAAC,CAAA;AAEpB,8EAA8E;AAC9E,gEAAgE;AAChE,MAAM,MAAM,GAAG,GAAG,CAAA;AAElB,SAAS,QAAQ,CACf,IAAc,EACd,IAAe,EACf,KAAa,EACb,cAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAA;IAClE,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACzD,MAAM,GAAG,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAA;IAC7D,MAAM,GAAG,GAAG,IAAI,GAAG,cAAc,CAAA;IACjC,OAAO,eAAe,CAAC;QACrB,YAAY,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,KAAK;QACtC,WAAW,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,KAAK;QAChC,OAAO,EAAE,GAAG,GAAG,KAAK;QACpB,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,CAAC,IAAc,EAAE,IAAc,EAAE,EAAE,CAChD,IAAI,CAAC,MAAM,KAAK,CAAC;IACjB,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAE,IAAI,IAAI,CAAC,CAAC,CAAE,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,CAAA;AAE3E,4EAA4E;AAC5E,kBAAkB;AAClB,MAAM,UAAU,gBAAgB,CAAC,IAAc,EAAE,UAAmB;IAClE,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IACjC,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAClC,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;KACZ,CAAA;AAC1B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAc,EAAE,IAAkB;IAClE,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ;QACjC,EAAE,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS;KACpC,CAAA;AACH,CAAC;AAED,0EAA0E;AAC1E,+CAA+C;AAC/C,MAAM,UAAU,kBAAkB,CAAC,IAAc,EAAE,IAAkB;IACnE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAChD,OAAO,CACL,EAAE,IAAI,UAAU;QAChB,EAAE,IAAI,UAAU;QAChB,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC;QAChD,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CACjD,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-msaview",
3
3
  "author": "Colin",
4
- "version": "9.0.0",
4
+ "version": "9.1.1",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "repository": {
@@ -37,23 +37,23 @@
37
37
  "react-dom": ">=16.8.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@jbrowse/core": "^5.0.0-beta.9",
41
- "@jbrowse/mobx-state-tree": "^6.6.1",
42
- "@mui/icons-material": "^9.4.0",
43
- "@mui/material": "^9.4.0",
44
- "@types/node": "^26.6.2",
40
+ "@jbrowse/core": "^5.0.0-beta.15",
41
+ "@jbrowse/mobx-state-tree": "^6.9.0",
42
+ "@mui/icons-material": "^9.5.0",
43
+ "@mui/material": "^9.5.0",
44
+ "@types/node": "^26.6.5",
45
45
  "esbuild": "^0.28.2",
46
- "mobx": "^7.0.3",
46
+ "mobx": "^7.0.6",
47
47
  "mobx-react": "^10.0.2",
48
- "react": "^19.3.0",
49
- "react-dom": "^19.3.0"
48
+ "react": "^19.3.1",
49
+ "react-dom": "^19.3.1"
50
50
  },
51
51
  "dependencies": {
52
52
  "@gmod/newick": "^1.0.3",
53
- "@jbrowse/svgcanvas": "9.0.0",
53
+ "@jbrowse/svgcanvas": "9.1.1",
54
54
  "colord": "^2.10.0",
55
55
  "flatbush": "^4.6.2",
56
- "msa-parsers": "9.0.0"
56
+ "msa-parsers": "9.1.1"
57
57
  },
58
58
  "scripts": {
59
59
  "clean": "rimraf dist bundle",
@@ -0,0 +1,45 @@
1
+ // BLOSUM62 (Henikoff & Henikoff 1992), shared by the neighbor-joining tree and
2
+ // the blosum62_dynamic color scheme
3
+
4
+ // prettier-ignore
5
+ const BLOSUM62_KEYS = 'ARNDCQEGHILKMFPSTWYVBZX*'
6
+ // prettier-ignore
7
+ const BLOSUM62_DATA = [
8
+ [ 4,-1,-2,-2, 0,-1,-1, 0,-2,-1,-1,-1,-1,-2,-1, 1, 0,-3,-2, 0,-2,-1, 0,-4],
9
+ [-1, 5, 0,-2,-3, 1, 0,-2, 0,-3,-2, 2,-1,-3,-2,-1,-1,-3,-2,-3,-1, 0,-1,-4],
10
+ [-2, 0, 6, 1,-3, 0, 0, 0, 1,-3,-3, 0,-2,-3,-2, 1, 0,-4,-2,-3, 3, 0,-1,-4],
11
+ [-2,-2, 1, 6,-3, 0, 2,-1,-1,-3,-4,-1,-3,-3,-1, 0,-1,-4,-3,-3, 4, 1,-1,-4],
12
+ [ 0,-3,-3,-3, 9,-3,-4,-3,-3,-1,-1,-3,-1,-2,-3,-1,-1,-2,-2,-1,-3,-3,-2,-4],
13
+ [-1, 1, 0, 0,-3, 5, 2,-2, 0,-3,-2, 1, 0,-3,-1, 0,-1,-2,-1,-2, 0, 3,-1,-4],
14
+ [-1, 0, 0, 2,-4, 2, 5,-2, 0,-3,-3, 1,-2,-3,-1, 0,-1,-3,-2,-2, 1, 4,-1,-4],
15
+ [ 0,-2, 0,-1,-3,-2,-2, 6,-2,-4,-4,-2,-3,-3,-2, 0,-2,-2,-3,-3,-1,-2,-1,-4],
16
+ [-2, 0, 1,-1,-3, 0, 0,-2, 8,-3,-3,-1,-2,-1,-2,-1,-2,-2, 2,-3, 0, 0,-1,-4],
17
+ [-1,-3,-3,-3,-1,-3,-3,-4,-3, 4, 2,-3, 1, 0,-3,-2,-1,-3,-1, 3,-3,-3,-1,-4],
18
+ [-1,-2,-3,-4,-1,-2,-3,-4,-3, 2, 4,-2, 2, 0,-3,-2,-1,-2,-1, 1,-4,-3,-1,-4],
19
+ [-1, 2, 0,-1,-3, 1, 1,-2,-1,-3,-2, 5,-1,-3,-1, 0,-1,-3,-2,-2, 0, 1,-1,-4],
20
+ [-1,-1,-2,-3,-1, 0,-2,-3,-2, 1, 2,-1, 5, 0,-2,-1,-1,-1,-1, 1,-3,-1,-1,-4],
21
+ [-2,-3,-3,-3,-2,-3,-3,-3,-1, 0, 0,-3, 0, 6,-4,-2,-2, 1, 3,-1,-3,-3,-1,-4],
22
+ [-1,-2,-2,-1,-3,-1,-1,-2,-2,-3,-3,-1,-2,-4, 7,-1,-1,-4,-3,-2,-2,-1,-2,-4],
23
+ [ 1,-1, 1, 0,-1, 0, 0, 0,-1,-2,-2, 0,-1,-2,-1, 4, 1,-3,-2,-2, 0, 0, 0,-4],
24
+ [ 0,-1, 0,-1,-1,-1,-1,-2,-2,-1,-1,-1,-1,-2,-1, 1, 5,-2,-2, 0,-1,-1, 0,-4],
25
+ [-3,-3,-4,-4,-2,-2,-3,-2,-2,-3,-2,-3,-1, 1,-4,-3,-2,11, 2,-3,-4,-3,-2,-4],
26
+ [-2,-2,-2,-3,-2,-1,-2,-3, 2,-1,-1,-2,-1, 3,-3,-2,-2, 2, 7,-1,-3,-2,-1,-4],
27
+ [ 0,-3,-3,-3,-1,-2,-2,-3,-3, 3, 1,-2, 1,-1,-2,-2, 0,-3,-1, 4,-3,-2,-1,-4],
28
+ [-2,-1, 3, 4,-3, 0, 1,-1, 0,-3,-4, 0,-3,-3,-2, 0,-1,-4,-3,-3, 4, 1,-1,-4],
29
+ [-1, 0, 0, 1,-3, 3, 4,-2, 0,-3,-3, 1,-1,-3,-1, 0,-1,-3,-2,-2, 1, 4,-1,-4],
30
+ [ 0,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2, 0, 0,-2,-1,-1,-1,-1,-1,-4],
31
+ [-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, 1],
32
+ ]
33
+
34
+ export const NUM_SYMBOLS = BLOSUM62_KEYS.length
35
+ export const BLOSUM62 = Int8Array.from(BLOSUM62_DATA.flat())
36
+
37
+ // charCode -> row/column in BLOSUM62, -1 for anything the matrix does not name.
38
+ // On a 120x800 alignment a Map keyed by upper-cased character took 2.6s to
39
+ // build a tree, against 0.34s for this table.
40
+ export const symbolOfCode = new Int8Array(128).fill(-1)
41
+ for (let i = 0; i < NUM_SYMBOLS; i++) {
42
+ const key = BLOSUM62_KEYS[i]!
43
+ symbolOfCode[key.charCodeAt(0)] = i
44
+ symbolOfCode[key.toLowerCase().charCodeAt(0)] = i
45
+ }
@@ -1,11 +1,8 @@
1
1
  import { blue, green, orange, red } from '@mui/material/colors'
2
- import { colord, extend } from 'colord'
3
- import namesPlugin from 'colord/plugins/names'
2
+ import { colord } from 'colord'
4
3
 
5
4
  import { transform } from './util.ts'
6
5
 
7
- extend([namesPlugin])
8
-
9
6
  // standard A/C/G/T(/U) coloring, shared by the `jbrowse_dna` and `nucleotide`
10
7
  // scheme names
11
8
  const dna = {
@@ -82,6 +79,7 @@ const colorSchemes: Record<string, Record<string, string>> = {
82
79
  },
83
80
 
84
81
  percent_identity_dynamic: {},
82
+ blosum62_dynamic: {},
85
83
  // https://github.com/biotite-dev/biotite/blob/8c460972f8ab904312f130dfb80f3efc8c9bd7c5/src/biotite/sequence/graphics/color_schemes/flower.json
86
84
  flower: {
87
85
  A: '#b18a51',
@@ -44,7 +44,7 @@ function slotOf(code: number) {
44
44
  return code < 128 ? slotOfCode[code]! : OTHER
45
45
  }
46
46
 
47
- export function isGapSlot(slot: number) {
47
+ function isGapSlot(slot: number) {
48
48
  return slot === DASH || slot === DOT
49
49
  }
50
50
 
@@ -10,6 +10,7 @@ import StatusMessage from './StatusMessage.tsx'
10
10
  import ImportForm from './import/ImportForm.tsx'
11
11
 
12
12
  import type { MsaViewModel } from '../model.ts'
13
+ import type { ToolbarSlots } from './header/Header.tsx'
13
14
 
14
15
  const Reset = observer(function ({
15
16
  model,
@@ -21,20 +22,25 @@ const Reset = observer(function ({
21
22
  return (
22
23
  <div>
23
24
  <ErrorMessage error={error} />
24
- <Button
25
- variant="contained"
26
- color="primary"
27
- onClick={() => {
28
- model.reset()
29
- }}
30
- >
31
- Return to import form
32
- </Button>
25
+ {model.importForm ? (
26
+ <Button
27
+ variant="contained"
28
+ color="primary"
29
+ onClick={() => {
30
+ model.reset()
31
+ }}
32
+ >
33
+ Return to import form
34
+ </Button>
35
+ ) : null}
33
36
  </div>
34
37
  )
35
38
  })
36
39
 
37
- const Loading = observer(function ({ model }: { model: MsaViewModel }) {
40
+ const Loading = observer(function ({
41
+ model,
42
+ ...slots
43
+ }: { model: MsaViewModel } & ToolbarSlots) {
38
44
  const {
39
45
  isLoading,
40
46
  dataInitialized,
@@ -43,6 +49,7 @@ const Loading = observer(function ({ model }: { model: MsaViewModel }) {
43
49
  resetCount,
44
50
  msaFilehandle,
45
51
  treeFilehandle,
52
+ importForm,
46
53
  } = model
47
54
  const hasData = !!(data.msa || data.tree)
48
55
  // a failed load keeps its filehandle, so the error outranks the spinner
@@ -61,16 +68,20 @@ const Loading = observer(function ({ model }: { model: MsaViewModel }) {
61
68
  isLoading ? (
62
69
  <StatusMessage model={model} variant="page" />
63
70
  ) : (
64
- <MSAView model={model} />
71
+ <MSAView model={model} {...slots} />
65
72
  )
66
73
  ) : hasData ? (
67
74
  <Reset model={model} error={error} />
68
75
  ) : (
69
76
  <>
70
77
  {loading ? <StatusMessage model={model} variant="page" /> : null}
71
- <div style={{ display: loading ? 'none' : undefined }}>
72
- <ImportForm model={model} />
73
- </div>
78
+ {importForm ? (
79
+ <div style={{ display: loading ? 'none' : undefined }}>
80
+ <ImportForm model={model} />
81
+ </div>
82
+ ) : error ? (
83
+ <ErrorMessage error={error} />
84
+ ) : null}
74
85
  </>
75
86
  )}
76
87
  </ErrorBoundary>
@@ -14,11 +14,13 @@ import MSAPanel from './msa/MSAPanel.tsx'
14
14
  import { clickColor, hoverColor, selectionFill } from './overlayColors.ts'
15
15
  import RowPanelHeaders from './rowpanels/RowPanelHeaders.tsx'
16
16
  import RowPanels from './rowpanels/RowPanels.tsx'
17
+ import SettingsPanel from './settings/SettingsPanel.tsx'
17
18
  import TreeOverview from './tree/TreeOverview.tsx'
18
19
  import TreePanel from './tree/TreePanel.tsx'
19
20
  import TreeRuler from './tree/TreeRuler.tsx'
20
21
 
21
22
  import type { MsaViewModel } from '../model.ts'
23
+ import type { ToolbarSlots } from './header/Header.tsx'
22
24
 
23
25
  // The band above the panels: the tree overview and scale bar, the strip
24
26
  // headers, and the minimap over the alignment. The spacer stands in for the
@@ -139,17 +141,32 @@ const View = observer(function ({ model }: { model: MsaViewModel }) {
139
141
  )
140
142
  })
141
143
 
142
- const MSAView = observer(function ({ model }: { model: MsaViewModel }) {
143
- const { height, hideHeader, viewInitialized, DialogComponent, DialogProps } =
144
- model
144
+ const MSAView = observer(function ({
145
+ model,
146
+ ...slots
147
+ }: { model: MsaViewModel } & ToolbarSlots) {
148
+ const {
149
+ height,
150
+ headerHeight,
151
+ hideHeader,
152
+ settingsOpen,
153
+ viewInitialized,
154
+ DialogComponent,
155
+ DialogProps,
156
+ } = model
145
157
 
146
158
  return (
147
159
  <div>
148
160
  {viewInitialized ? (
149
161
  <>
150
162
  <div style={{ height, overflow: 'clip' }}>
151
- {hideHeader ? null : <Header model={model} />}
152
- <View model={model} />
163
+ {hideHeader ? null : <Header model={model} {...slots} />}
164
+ <div style={{ display: 'flex' }}>
165
+ <View model={model} />
166
+ {settingsOpen ? (
167
+ <SettingsPanel model={model} height={height - headerHeight} />
168
+ ) : null}
169
+ </div>
153
170
  </div>
154
171
  <HorizontalResizeHandle model={model} />
155
172