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
@@ -1,21 +1,57 @@
1
1
  import React from 'react'
2
2
 
3
3
  import { makeStyles } from '@jbrowse/core/util/tss-react'
4
- import { Table, TableBody, TableCell, TableRow } from '@mui/material'
5
4
 
6
- const useStyles = makeStyles()({
5
+ const useStyles = makeStyles()(theme => ({
6
+ list: {
7
+ display: 'grid',
8
+ gridTemplateColumns: 'minmax(8em, max-content) minmax(0, 1fr)',
9
+ columnGap: theme.spacing(3),
10
+ margin: 0,
11
+ },
12
+ row: {
13
+ display: 'contents',
14
+ },
7
15
  key: {
8
- fontWeight: 'bold',
9
- verticalAlign: 'top',
16
+ fontWeight: 600,
17
+ padding: theme.spacing(0.75, 0),
18
+ borderTop: `1px solid ${theme.palette.divider}`,
19
+ },
20
+ code: {
21
+ marginLeft: theme.spacing(1),
22
+ fontWeight: 400,
23
+ fontSize: '0.75em',
24
+ fontFamily: 'monospace',
25
+ color: theme.palette.text.secondary,
10
26
  },
11
27
  value: {
28
+ margin: 0,
29
+ padding: theme.spacing(0.75, 0),
30
+ borderTop: `1px solid ${theme.palette.divider}`,
12
31
  whiteSpace: 'pre-wrap',
13
- wordBreak: 'break-word',
32
+ overflowWrap: 'anywhere',
33
+ },
34
+ mono: {
35
+ fontFamily: 'monospace',
36
+ fontSize: '0.85em',
37
+ maxHeight: '8em',
38
+ overflow: 'auto',
14
39
  },
15
- })
40
+ nested: {
41
+ '& > dl': {
42
+ paddingLeft: theme.spacing(2),
43
+ borderLeft: `2px solid ${theme.palette.divider}`,
44
+ },
45
+ },
46
+ }))
16
47
 
17
- function isRecord(value: unknown): value is Record<string, unknown> {
18
- return typeof value === 'object' && value !== null && !Array.isArray(value)
48
+ export function isRecord(value: unknown): value is Record<string, unknown> {
49
+ return (
50
+ typeof value === 'object' &&
51
+ value !== null &&
52
+ !Array.isArray(value) &&
53
+ !React.isValidElement(value)
54
+ )
19
55
  }
20
56
 
21
57
  export function isEmpty(value: unknown) {
@@ -24,32 +60,53 @@ export function isEmpty(value: unknown) {
24
60
 
25
61
  export default function MetadataTable({
26
62
  record,
63
+ labels = {},
64
+ monospaceKeys,
27
65
  }: {
28
66
  record: Record<string, unknown>
67
+ labels?: Record<string, string>
68
+ monospaceKeys?: Set<string>
29
69
  }) {
30
- const { classes } = useStyles()
70
+ const { classes, cx } = useStyles()
31
71
  return (
32
- <Table size="small">
33
- <TableBody>
34
- {Object.entries(record)
35
- .filter(([, value]) => value != null && !isEmpty(value))
36
- .map(([key, value]) => (
37
- <TableRow key={key}>
38
- <TableCell component="th" className={classes.key}>
39
- {key}
40
- </TableCell>
41
- <TableCell className={classes.value}>
42
- {isRecord(value) ? (
43
- <MetadataTable record={value} />
72
+ <dl className={classes.list}>
73
+ {Object.entries(record)
74
+ .filter(([, value]) => value != null && !isEmpty(value))
75
+ .map(([key, value]) => {
76
+ const label = labels[key]
77
+ const nested = isRecord(value)
78
+ return (
79
+ <div key={key} className={classes.row}>
80
+ <dt className={classes.key}>
81
+ {label ?? key}
82
+ {label && label !== key ? (
83
+ <span className={classes.code}>{key}</span>
84
+ ) : null}
85
+ </dt>
86
+ <dd
87
+ className={cx(
88
+ classes.value,
89
+ nested && classes.nested,
90
+ monospaceKeys?.has(key) && classes.mono,
91
+ )}
92
+ >
93
+ {nested ? (
94
+ <MetadataTable
95
+ record={value}
96
+ labels={labels}
97
+ monospaceKeys={monospaceKeys}
98
+ />
44
99
  ) : Array.isArray(value) ? (
45
100
  value.join('\n')
101
+ ) : React.isValidElement(value) ? (
102
+ value
46
103
  ) : (
47
104
  String(value)
48
105
  )}
49
- </TableCell>
50
- </TableRow>
51
- ))}
52
- </TableBody>
53
- </Table>
106
+ </dd>
107
+ </div>
108
+ )
109
+ })}
110
+ </dl>
54
111
  )
55
112
  }
@@ -7,6 +7,8 @@ import DragHandle from './DragHandle.tsx'
7
7
  import type { MsaViewModel } from '../model.ts'
8
8
  import type { BasicTrack } from '../types.ts'
9
9
 
10
+ const minViewHeight = 50
11
+
10
12
  export const VerticalResizeHandle = observer(function ({
11
13
  model,
12
14
  }: {
@@ -14,7 +16,12 @@ export const VerticalResizeHandle = observer(function ({
14
16
  }) {
15
17
  const onDrag = useCallback(
16
18
  (delta: number, startWidth: number) => {
17
- model.setTreeAreaWidth(startWidth + delta)
19
+ model.setTreeAreaWidth(
20
+ Math.min(
21
+ Math.max(0, startWidth + delta),
22
+ model.width - model.resizeHandleWidth,
23
+ ),
24
+ )
18
25
  },
19
26
  [model],
20
27
  )
@@ -36,7 +43,7 @@ export const HorizontalResizeHandle = observer(function ({
36
43
  }) {
37
44
  const onDrag = useCallback(
38
45
  (delta: number, startHeight: number) => {
39
- model.setHeight(startHeight + delta)
46
+ model.setHeight(Math.max(minViewHeight, startHeight + delta))
40
47
  },
41
48
  [model],
42
49
  )
@@ -3,11 +3,13 @@ import React, { lazy, useCallback, useRef, useState } from 'react'
3
3
  import BaseTooltip from '@jbrowse/core/ui/BaseTooltip'
4
4
  import { makeStyles } from '@jbrowse/core/util/tss-react'
5
5
  import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'
6
+ import CloseIcon from '@mui/icons-material/Close'
6
7
  import { IconButton, Menu, MenuItem } from '@mui/material'
7
8
  import { observer } from 'mobx-react'
8
9
 
9
10
  import { useWheelScroll } from '../useWheelScroll.ts'
10
11
  import { onMsaKey } from './msa/msaKeys.ts'
12
+ import TrackBlocks from './tracks/TrackBlocks.tsx'
11
13
  import TrackTooltipContent from './tracks/TrackTooltipContent.tsx'
12
14
  import { useTrackHover } from './tracks/useTrackHover.ts'
13
15
 
@@ -50,6 +52,7 @@ const TrackLabel = observer(function TrackLabel({
50
52
  } = track
51
53
  const { classes } = useStyles()
52
54
  const trackLabelHeight = Math.min(height, fontSize)
55
+ const closeSize = Math.min(height, Math.max(fontSize, 16))
53
56
 
54
57
  return (
55
58
  // a flex row, not inline text: zooming in grows fontSize against a tree
@@ -77,6 +80,17 @@ const TrackLabel = observer(function TrackLabel({
77
80
  >
78
81
  {drawLabels ? name : ''}
79
82
  </span>
83
+ <IconButton
84
+ className={classes.button}
85
+ aria-label={`Hide ${name} track`}
86
+ title="Hide track"
87
+ style={{ width: closeSize, height: closeSize, flexShrink: 0 }}
88
+ onClick={() => {
89
+ model.toggleTrack(track.model.id)
90
+ }}
91
+ >
92
+ <CloseIcon style={{ fontSize: closeSize * 0.8 }} />
93
+ </IconButton>
80
94
  <IconButton
81
95
  className={classes.button}
82
96
  aria-label={`${name} track menu`}
@@ -184,7 +198,7 @@ const Track = observer(function ({
184
198
  onMouseLeave()
185
199
  }}
186
200
  >
187
- <track.ReactComponent model={model} track={track} />
201
+ <TrackBlocks model={model} track={track} />
188
202
  {anchor ? (
189
203
  <BaseTooltip clientPoint={anchor.clientPoint}>
190
204
  <TrackTooltipContent
@@ -0,0 +1,62 @@
1
+ export interface Control {
2
+ label: string
3
+ action: string
4
+ }
5
+
6
+ export interface KeyControl extends Control {
7
+ keys: string[]
8
+ shiftKey?: boolean
9
+ }
10
+
11
+ const arrows = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']
12
+
13
+ export const keyboardControls: KeyControl[] = [
14
+ { label: 'Arrow keys', action: 'Scroll one cell', keys: arrows },
15
+ {
16
+ label: 'Shift + arrow keys',
17
+ action: 'Scroll one page',
18
+ keys: arrows,
19
+ shiftKey: true,
20
+ },
21
+ { label: '+ and -', action: 'Zoom in and out', keys: ['+', '=', '-'] },
22
+ { label: '0', action: 'Reset to the default cell size', keys: ['0'] },
23
+ {
24
+ label: 'Home and End',
25
+ action: 'Jump to the first and last column',
26
+ keys: ['Home', 'End'],
27
+ },
28
+ { label: 'Escape', action: 'Clear the selection', keys: ['Escape'] },
29
+ ]
30
+
31
+ const selectCells: Control = {
32
+ label: 'Shift + drag',
33
+ action: 'Select a block of cells',
34
+ }
35
+
36
+ export const mouseControls: Control[] = [
37
+ { label: 'Drag', action: 'Pan the alignment' },
38
+ {
39
+ label: 'Wheel',
40
+ action: 'Scroll, or zoom with Zoom on scroll checked',
41
+ },
42
+ { label: 'Ctrl + wheel', action: 'Zoom at the cursor' },
43
+ selectCells,
44
+ {
45
+ label: 'Drag along a track',
46
+ action: 'Select a range of columns across every row',
47
+ },
48
+ {
49
+ label: 'Click a tree node',
50
+ action: 'Collapse, rotate, reroot or show only that clade',
51
+ },
52
+ {
53
+ label: 'Click the tree overview',
54
+ action: 'Show only the clade under the pointer',
55
+ },
56
+ { label: 'Drag a divider', action: 'Resize the tree area or a track' },
57
+ ]
58
+
59
+ export const alignmentAriaLabel = [
60
+ 'Alignment',
61
+ ...[...keyboardControls, selectCells].map(c => `${c.label}: ${c.action}`),
62
+ ].join('. ')
@@ -7,31 +7,18 @@ import {
7
7
  DialogContent,
8
8
  FormControl,
9
9
  FormControlLabel,
10
+ Link,
10
11
  Radio,
11
12
  RadioGroup,
12
13
  TextField,
13
14
  Typography,
14
15
  } from '@mui/material'
15
16
  import { observer } from 'mobx-react'
16
- import {
17
- annotationsToGFF,
18
- interProScanResponseToAnnotations,
19
- } from 'msa-parsers'
17
+ import { annotationTextToGFF } from 'msa-parsers'
20
18
 
21
19
  import type { MsaViewModel } from '../../model.ts'
22
- import type { InterProScanResponse } from 'msa-parsers'
23
20
 
24
- // GFF3 as the CLI writes it, or the JSON an InterProScan run returns. Both
25
- // arrive as text and the model keeps GFF, so the JSON is converted on the way
26
- // in rather than given a second path through the model
27
- function toGFF(text: string) {
28
- const trimmed = text.trimStart()
29
- if (!trimmed.startsWith('{')) {
30
- return text
31
- }
32
- const response: InterProScanResponse = JSON.parse(trimmed)
33
- return annotationsToGFF(interProScanResponseToAnnotations(response))
34
- }
21
+ const domainsTutorial = 'https://gmod.org/JBrowseMSA/tutorials/protein_family'
35
22
 
36
23
  async function fetchText(url: string) {
37
24
  const response = await fetch(url)
@@ -73,7 +60,14 @@ const AnnotationFileDialog = observer(function ({
73
60
  {error ? <ErrorMessage error={error} /> : null}
74
61
  <Typography>
75
62
  Open a GFF3 file of annotations, such as the one `react-msaview-cli
76
- interpro` writes, or the JSON an InterProScan run returns.
63
+ interpro` writes, or the JSON an InterProScan run returns.{' '}
64
+ <Link
65
+ href={domainsTutorial}
66
+ target="_blank"
67
+ rel="noopener noreferrer"
68
+ >
69
+ How to make one
70
+ </Link>
77
71
  </Typography>
78
72
 
79
73
  <div style={{ display: 'flex', margin: 30 }}>
@@ -137,11 +131,12 @@ const AnnotationFileDialog = observer(function ({
137
131
  ? file.text()
138
132
  : fetchText(url))
139
133
  // through the model's own GFF text, so the annotations travel
140
- // in the snapshot and the shared URL like every other layer.
141
- // Setting them straight onto the volatile left a view whose
142
- // link opened without them
143
- model.setGFF(toGFF(text))
134
+ // in the snapshot and the shared URL like every other layer. A
135
+ // filehandle left set would make the snapshot drop that text
136
+ model.setGFFFilehandle(undefined)
137
+ model.setGFF(annotationTextToGFF(text))
144
138
  model.setShowDomains(true)
139
+ model.setCellFill('domain')
145
140
  handleClose()
146
141
  } catch (e) {
147
142
  console.error(e)
@@ -17,6 +17,7 @@ import {
17
17
  } from '@mui/material'
18
18
  import { observer } from 'mobx-react'
19
19
 
20
+ import { exportPageSize, getLayout } from '../../exportLayout.ts'
20
21
  import Checkbox2 from '../Checkbox2.tsx'
21
22
 
22
23
  import type { MsaViewModel } from '../../model.ts'
@@ -46,24 +47,12 @@ const ExportSVGDialog = observer(function ({
46
47
  const [error, setError] = useState<unknown>()
47
48
  const [exporting, setExporting] = useState(false)
48
49
  const theme = useTheme()
49
- const {
50
- totalWidth,
51
- totalHeight,
52
- effectiveTreeAreaWidth,
53
- rowPanelsWidth,
54
- turnedOnTracks,
55
- totalTrackAreaHeight,
56
- numColumns,
57
- leaves,
58
- showMsaLetters,
59
- treeOverviewHeight,
60
- } = model
50
+ const { turnedOnTracks, numColumns, leaves, showMsaLetters } = model
61
51
  const hasTracks = turnedOnTracks.length > 0
62
- const entireWidth = totalWidth + effectiveTreeAreaWidth + rowPanelsWidth
63
- const entireHeight =
64
- totalHeight +
65
- (includeTracks ? totalTrackAreaHeight : 0) +
66
- treeOverviewHeight
52
+ const entire = exportPageSize(
53
+ model,
54
+ getLayout(model, { theme, exportType: 'entire', includeTracks }),
55
+ )
67
56
  // the background is one raster image whatever its size, so what the figure
68
57
  // actually costs is its residue letters: each is an svg element of its own.
69
58
  // Past roughly this many the export runs to tens of seconds and can exhaust
@@ -126,8 +115,8 @@ const ExportSVGDialog = observer(function ({
126
115
  </div>
127
116
  {isLargeExport ? (
128
117
  <Alert severity="warning" style={{ marginTop: 8 }}>
129
- The entire MSA is {Math.round(entireWidth)}x
130
- {Math.round(entireHeight)} pixels and draws{' '}
118
+ The entire MSA is {Math.round(entire.width)}x
119
+ {Math.round(entire.height)} pixels and draws{' '}
131
120
  {Math.round(glyphs / 1000)}k residue letters, each its own SVG
132
121
  element. Export may be slow or fail — zooming out far enough to hide
133
122
  the letters exports the same alignment as an image instead.
@@ -102,12 +102,9 @@ const FeatureTable = observer(function ({ model }: { model: MsaViewModel }) {
102
102
  <TableRow key={accession}>
103
103
  <TableCell padding="checkbox">
104
104
  <Checkbox
105
- checked={!model.turnedOffFeatures.get(accession)}
105
+ checked={!model.featureOff(accession)}
106
106
  onChange={() => {
107
- model.setFilter(
108
- accession,
109
- !!model.turnedOffFeatures.get(accession),
110
- )
107
+ model.setFilter(accession, model.featureOff(accession))
111
108
  }}
112
109
  />
113
110
  </TableCell>
@@ -0,0 +1,36 @@
1
+ import React from 'react'
2
+
3
+ import { Dialog } from '@jbrowse/core/ui'
4
+ import { Button, DialogActions, DialogContent, Typography } from '@mui/material'
5
+ import { observer } from 'mobx-react'
6
+
7
+ import GappynessSlider from './GappynessSlider.tsx'
8
+
9
+ import type { MsaViewModel } from '../../model.ts'
10
+
11
+ const GapThresholdDialog = observer(function ({
12
+ model,
13
+ onClose,
14
+ }: {
15
+ model: MsaViewModel
16
+ onClose: () => void
17
+ }) {
18
+ return (
19
+ <Dialog open onClose={onClose} title="Hide gappy columns">
20
+ <DialogContent>
21
+ <Typography variant="body2" sx={{ mb: 2 }}>
22
+ The viewer hides each column where at least this share of the rows has
23
+ a gap.
24
+ </Typography>
25
+ <GappynessSlider model={model} />
26
+ </DialogContent>
27
+ <DialogActions>
28
+ <Button variant="contained" onClick={onClose}>
29
+ Close
30
+ </Button>
31
+ </DialogActions>
32
+ </Dialog>
33
+ )
34
+ })
35
+
36
+ export default GapThresholdDialog
@@ -10,19 +10,15 @@ const GappynessSlider = observer(function GappynessSlider({
10
10
  }: {
11
11
  model: MsaViewModel
12
12
  }) {
13
- const { hideGaps, allowedGappyness } = model
14
13
  const [dragValue, setDragValue] = useState<number>()
15
- const value = dragValue ?? allowedGappyness
16
- if (!hideGaps) {
17
- return null
18
- }
14
+ const value = dragValue ?? model.allowedGappyness
19
15
  return (
20
16
  <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
21
17
  {/* the threshold is inclusive: blanks are columns whose gap count is at
22
18
  least ceil(allowedGappyness% of the rows), so at 100 it hides the
23
19
  columns that are entirely gaps rather than nothing */}
24
20
  <Typography style={{ whiteSpace: 'nowrap' }}>
25
- Hide columns w/ &ge;{value}% gaps
21
+ &ge;{value}% gaps
26
22
  </Typography>
27
23
  <Slider
28
24
  // In JBrowse other MUI Sliders share the page, so `.MuiSlider-thumb`
@@ -36,11 +32,8 @@ const GappynessSlider = observer(function GappynessSlider({
36
32
  // The thumb follows local state while dragging and the model takes the
37
33
  // value on release, since each write recomputes the gap columns over
38
34
  // the whole alignment.
39
- //
40
- // The thumb centers on the track's ends, so the margin keeps its
41
- // overhang off the label and the row search beside it.
42
35
  data-testid="gappyness_slider"
43
- style={{ width: 100, marginInline: 10 }}
36
+ style={{ width: 200, marginInline: 10 }}
44
37
  min={1}
45
38
  max={100}
46
39
  value={value}
@@ -26,14 +26,32 @@ export function labelledInput(params: AutocompleteRenderInputParams) {
26
26
  : { inputProps: { ...inputProps, 'aria-label': label } }
27
27
  }
28
28
 
29
- const GoToBox = observer(function ({ model }: { model: MsaViewModel }) {
29
+ // the menu that opens the dialog hands focus back to its button as it closes,
30
+ // after an autoFocus input would have taken it
31
+ function focusNextFrame(el: HTMLInputElement | null) {
32
+ if (el) {
33
+ requestAnimationFrame(() => {
34
+ el.focus()
35
+ })
36
+ }
37
+ }
38
+
39
+ export function canGoTo(model: MsaViewModel) {
40
+ return findableRowNames(model).length > 1 || model.numColumns > 0
41
+ }
42
+
43
+ const GoToBox = observer(function ({
44
+ model,
45
+ onFound,
46
+ }: {
47
+ model: MsaViewModel
48
+ onFound?: () => void
49
+ }) {
30
50
  const [missed, setMissed] = useState(false)
31
- const names = findableRowNames(model)
32
- return names.length > 1 || model.numColumns > 0 ? (
51
+ return (
33
52
  <Autocomplete
34
53
  freeSolo
35
- size="small"
36
- options={names}
54
+ options={findableRowNames(model)}
37
55
  filterOptions={(options, { inputValue }) =>
38
56
  rowNameSuggestions(options, inputValue)
39
57
  }
@@ -44,21 +62,29 @@ const GoToBox = observer(function ({ model }: { model: MsaViewModel }) {
44
62
  }}
45
63
  onChange={(_, text) => {
46
64
  if (text) {
47
- setMissed(!goTo(model, text))
65
+ const found = goTo(model, text)
66
+ setMissed(!found)
67
+ if (found) {
68
+ onFound?.()
69
+ }
48
70
  }
49
71
  }}
50
- style={{ width: 180, margin: 'auto 8px' }}
51
72
  renderInput={params => (
52
73
  <TextField
53
74
  {...params}
75
+ inputRef={focusNextFrame}
54
76
  error={missed}
55
- placeholder={label}
56
- title="A row name, a column number, or name:residue"
77
+ placeholder="Row name or column number"
78
+ helperText={
79
+ missed
80
+ ? 'No row or column matches'
81
+ : 'Or name:N for residue N of that row'
82
+ }
57
83
  {...labelledInput(params)}
58
84
  />
59
85
  )}
60
86
  />
61
- ) : null
87
+ )
62
88
  })
63
89
 
64
90
  export default GoToBox
@@ -0,0 +1,30 @@
1
+ import React from 'react'
2
+
3
+ import { Dialog } from '@jbrowse/core/ui'
4
+ import { DialogContent } from '@mui/material'
5
+
6
+ import GoToBox from './GoToBox.tsx'
7
+
8
+ import type { MsaViewModel } from '../../model.ts'
9
+
10
+ export default function GoToDialog({
11
+ model,
12
+ onClose,
13
+ }: {
14
+ model: MsaViewModel
15
+ onClose: () => void
16
+ }) {
17
+ return (
18
+ <Dialog
19
+ open
20
+ onClose={onClose}
21
+ title="Go to row or column"
22
+ maxWidth="xs"
23
+ fullWidth
24
+ >
25
+ <DialogContent>
26
+ <GoToBox model={model} onFound={onClose} />
27
+ </DialogContent>
28
+ </Dialog>
29
+ )
30
+ }
@@ -0,0 +1,79 @@
1
+ import React, { lazy } from 'react'
2
+
3
+ import { Dialog } from '@jbrowse/core/ui'
4
+ import {
5
+ Button,
6
+ DialogActions,
7
+ DialogContent,
8
+ Table,
9
+ TableBody,
10
+ TableCell,
11
+ TableRow,
12
+ Typography,
13
+ } from '@mui/material'
14
+
15
+ import { version } from '../../version.ts'
16
+ import { keyboardControls, mouseControls } from '../controls.ts'
17
+
18
+ import type { MsaViewModel } from '../../model.ts'
19
+ import type { Control } from '../controls.ts'
20
+
21
+ const AboutDialog = lazy(() => import('./AboutDialog.tsx'))
22
+
23
+ function ControlTable({ title, rows }: { title: string; rows: Control[] }) {
24
+ return (
25
+ <>
26
+ <Typography variant="subtitle2" sx={{ mt: 1 }}>
27
+ {title}
28
+ </Typography>
29
+ <Table size="small" aria-label={title}>
30
+ <TableBody>
31
+ {rows.map(({ label, action }) => (
32
+ <TableRow key={label}>
33
+ <TableCell sx={{ whiteSpace: 'nowrap', fontWeight: 500 }}>
34
+ {label}
35
+ </TableCell>
36
+ <TableCell>{action}</TableCell>
37
+ </TableRow>
38
+ ))}
39
+ </TableBody>
40
+ </Table>
41
+ </>
42
+ )
43
+ }
44
+
45
+ export default function HelpDialog({
46
+ model,
47
+ onClose,
48
+ }: {
49
+ model: MsaViewModel
50
+ onClose: () => void
51
+ }) {
52
+ return (
53
+ <Dialog open title="Mouse & keyboard" onClose={onClose}>
54
+ <DialogContent>
55
+ <ControlTable title="Mouse" rows={mouseControls} />
56
+ <ControlTable
57
+ title="Keyboard (click the alignment first)"
58
+ rows={keyboardControls}
59
+ />
60
+ </DialogContent>
61
+ <DialogActions>
62
+ <Typography variant="caption" sx={{ mr: 'auto', pl: 1 }}>
63
+ MSAView {version}
64
+ </Typography>
65
+ <Button
66
+ onClick={() => {
67
+ model.queueDialog(done => [AboutDialog, { onClose: done }])
68
+ onClose()
69
+ }}
70
+ >
71
+ About & credits
72
+ </Button>
73
+ <Button variant="contained" onClick={onClose}>
74
+ Close
75
+ </Button>
76
+ </DialogActions>
77
+ </Dialog>
78
+ )
79
+ }