react-msaview 3.1.12 → 3.2.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 (233) hide show
  1. package/bundle/index.js +32 -31
  2. package/dist/colorSchemes.d.ts +2 -2
  3. package/dist/colorSchemes.js +5 -6
  4. package/dist/colorSchemes.js.map +1 -1
  5. package/dist/components/Loading.d.ts +1 -1
  6. package/dist/components/Loading.js +7 -5
  7. package/dist/components/Loading.js.map +1 -1
  8. package/dist/components/MSAView.d.ts +1 -1
  9. package/dist/components/MSAView.js +13 -9
  10. package/dist/components/MSAView.js.map +1 -1
  11. package/dist/components/ResizeHandles.d.ts +1 -1
  12. package/dist/components/ResizeHandles.js +8 -4
  13. package/dist/components/ResizeHandles.js.map +1 -1
  14. package/dist/components/SequenceTextArea.js +9 -3
  15. package/dist/components/SequenceTextArea.js.map +1 -1
  16. package/dist/components/TextTrack.d.ts +1 -1
  17. package/dist/components/TextTrack.js +1 -1
  18. package/dist/components/TextTrack.js.map +1 -1
  19. package/dist/components/Track.d.ts +1 -1
  20. package/dist/components/Track.js +6 -2
  21. package/dist/components/Track.js.map +1 -1
  22. package/dist/components/VerticalScrollbar.d.ts +6 -0
  23. package/dist/components/VerticalScrollbar.js +69 -0
  24. package/dist/components/VerticalScrollbar.js.map +1 -0
  25. package/dist/components/dialogs/AboutDialog.js +3 -1
  26. package/dist/components/dialogs/AboutDialog.js.map +1 -1
  27. package/dist/components/dialogs/AddTrackDialog.d.ts +3 -3
  28. package/dist/components/dialogs/AddTrackDialog.js +8 -3
  29. package/dist/components/dialogs/AddTrackDialog.js.map +1 -1
  30. package/dist/components/dialogs/DomainDialog.d.ts +1 -1
  31. package/dist/components/dialogs/DomainDialog.js +8 -4
  32. package/dist/components/dialogs/DomainDialog.js.map +1 -1
  33. package/dist/components/dialogs/ExportSVGDialog.d.ts +1 -1
  34. package/dist/components/dialogs/ExportSVGDialog.js +29 -17
  35. package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
  36. package/dist/components/dialogs/FeatureDialog.d.ts +1 -1
  37. package/dist/components/dialogs/FeatureDialog.js +8 -4
  38. package/dist/components/dialogs/FeatureDialog.js.map +1 -1
  39. package/dist/components/dialogs/{InterProScanPanel.d.ts → InterProScanDialog.d.ts} +1 -1
  40. package/dist/components/dialogs/{InterProScanPanel.js → InterProScanDialog.js} +26 -11
  41. package/dist/components/dialogs/InterProScanDialog.js.map +1 -0
  42. package/dist/components/dialogs/MetadataDialog.d.ts +1 -1
  43. package/dist/components/dialogs/MetadataDialog.js +3 -1
  44. package/dist/components/dialogs/MetadataDialog.js.map +1 -1
  45. package/dist/components/dialogs/SettingsDialog.d.ts +1 -1
  46. package/dist/components/dialogs/SettingsDialog.js +62 -15
  47. package/dist/components/dialogs/SettingsDialog.js.map +1 -1
  48. package/dist/components/dialogs/TracklistDialog.d.ts +3 -3
  49. package/dist/components/dialogs/TracklistDialog.js +8 -3
  50. package/dist/components/dialogs/TracklistDialog.js.map +1 -1
  51. package/dist/components/dialogs/UserProvidedDomainsDialog.d.ts +7 -0
  52. package/dist/components/dialogs/UserProvidedDomainsDialog.js +64 -0
  53. package/dist/components/dialogs/UserProvidedDomainsDialog.js.map +1 -0
  54. package/dist/components/header/Header.d.ts +1 -1
  55. package/dist/components/header/Header.js +11 -4
  56. package/dist/components/header/Header.js.map +1 -1
  57. package/dist/components/header/HeaderInfoArea.d.ts +1 -1
  58. package/dist/components/header/HeaderInfoArea.js +5 -2
  59. package/dist/components/header/HeaderInfoArea.js.map +1 -1
  60. package/dist/components/header/HeaderMenu.d.ts +1 -1
  61. package/dist/components/header/HeaderMenu.js +12 -4
  62. package/dist/components/header/HeaderMenu.js.map +1 -1
  63. package/dist/components/header/HeaderMenuExtra.d.ts +1 -1
  64. package/dist/components/header/HeaderMenuExtra.js +55 -35
  65. package/dist/components/header/HeaderMenuExtra.js.map +1 -1
  66. package/dist/components/header/HeaderStatusArea.d.ts +2 -2
  67. package/dist/components/header/HeaderStatusArea.js +1 -1
  68. package/dist/components/header/HeaderStatusArea.js.map +1 -1
  69. package/dist/components/header/MultiAlignmentSelector.d.ts +1 -1
  70. package/dist/components/header/ZoomControls.js +45 -3
  71. package/dist/components/header/ZoomControls.js.map +1 -1
  72. package/dist/components/import/ImportForm.d.ts +3 -3
  73. package/dist/components/import/ImportForm.js +15 -2
  74. package/dist/components/import/ImportForm.js.map +1 -1
  75. package/dist/components/import/ImportFormExamples.d.ts +1 -1
  76. package/dist/components/import/ImportFormExamples.js +53 -38
  77. package/dist/components/import/ImportFormExamples.js.map +1 -1
  78. package/dist/components/import/util.d.ts +2 -2
  79. package/dist/components/minimap/Minimap.d.ts +1 -1
  80. package/dist/components/minimap/Minimap.js +24 -17
  81. package/dist/components/minimap/Minimap.js.map +1 -1
  82. package/dist/components/minimap/MinimapSVG.d.ts +1 -1
  83. package/dist/components/minimap/MinimapSVG.js +1 -1
  84. package/dist/components/minimap/MinimapSVG.js.map +1 -1
  85. package/dist/components/msa/MSACanvas.d.ts +1 -1
  86. package/dist/components/msa/MSACanvas.js +3 -3
  87. package/dist/components/msa/MSACanvas.js.map +1 -1
  88. package/dist/components/msa/MSACanvasBlock.d.ts +3 -3
  89. package/dist/components/msa/MSACanvasBlock.js +9 -6
  90. package/dist/components/msa/MSACanvasBlock.js.map +1 -1
  91. package/dist/components/msa/MSAMouseoverCanvas.d.ts +1 -1
  92. package/dist/components/msa/MSAPanel.d.ts +1 -1
  93. package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +1 -1
  94. package/dist/components/msa/renderBoxFeatureCanvasBlock.js +3 -4
  95. package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
  96. package/dist/components/msa/renderMSABlock.d.ts +2 -2
  97. package/dist/components/msa/renderMSABlock.js +16 -16
  98. package/dist/components/msa/renderMSABlock.js.map +1 -1
  99. package/dist/components/msa/renderMSAMouseover.d.ts +1 -1
  100. package/dist/components/msa/renderMSAMouseover.js +3 -3
  101. package/dist/components/msa/renderMSAMouseover.js.map +1 -1
  102. package/dist/components/tree/TreeBranchMenu.d.ts +1 -1
  103. package/dist/components/tree/TreeBranchMenu.js +6 -3
  104. package/dist/components/tree/TreeBranchMenu.js.map +1 -1
  105. package/dist/components/tree/TreeCanvas.d.ts +1 -1
  106. package/dist/components/tree/TreeCanvas.js +13 -12
  107. package/dist/components/tree/TreeCanvas.js.map +1 -1
  108. package/dist/components/tree/TreeCanvasBlock.d.ts +1 -1
  109. package/dist/components/tree/TreeCanvasBlock.js +13 -5
  110. package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
  111. package/dist/components/tree/TreeNodeMenu.d.ts +1 -1
  112. package/dist/components/tree/TreeNodeMenu.js +3 -3
  113. package/dist/components/tree/TreeNodeMenu.js.map +1 -1
  114. package/dist/components/tree/TreePanel.d.ts +1 -1
  115. package/dist/components/tree/TreeRuler.d.ts +1 -1
  116. package/dist/components/tree/dialogs/TreeNodeInfoDialog.d.ts +3 -3
  117. package/dist/components/tree/dialogs/TreeNodeInfoDialog.js +5 -2
  118. package/dist/components/tree/dialogs/TreeNodeInfoDialog.js.map +1 -1
  119. package/dist/components/tree/renderTreeCanvas.d.ts +3 -3
  120. package/dist/components/tree/renderTreeCanvas.js +25 -9
  121. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  122. package/dist/components/util.js +1 -4
  123. package/dist/components/util.js.map +1 -1
  124. package/dist/ggplotPalettes.js.map +1 -1
  125. package/dist/launchInterProScan.d.ts +1 -1
  126. package/dist/launchInterProScan.js +11 -13
  127. package/dist/launchInterProScan.js.map +1 -1
  128. package/dist/model/DataModel.d.ts +5 -1
  129. package/dist/model/DataModel.js +10 -1
  130. package/dist/model/DataModel.js.map +1 -1
  131. package/dist/model/DialogQueue.d.ts +1 -1
  132. package/dist/model/DialogQueue.js +0 -1
  133. package/dist/model/DialogQueue.js.map +1 -1
  134. package/dist/model.d.ts +187 -35
  135. package/dist/model.js +317 -94
  136. package/dist/model.js.map +1 -1
  137. package/dist/parseGFF.js +8 -6
  138. package/dist/parseGFF.js.map +1 -1
  139. package/dist/parseNewick.js +1 -2
  140. package/dist/parseNewick.js.map +1 -1
  141. package/dist/parsers/ClustalMSA.d.ts +2 -2
  142. package/dist/parsers/ClustalMSA.js.map +1 -1
  143. package/dist/parsers/FastaMSA.d.ts +1 -1
  144. package/dist/parsers/FastaMSA.js +3 -3
  145. package/dist/parsers/FastaMSA.js.map +1 -1
  146. package/dist/parsers/StockholmMSA.d.ts +7 -7
  147. package/dist/parsers/StockholmMSA.js +4 -4
  148. package/dist/parsers/StockholmMSA.js.map +1 -1
  149. package/dist/renderToSvg.d.ts +2 -2
  150. package/dist/renderToSvg.js +6 -11
  151. package/dist/renderToSvg.js.map +1 -1
  152. package/dist/reparseTree.d.ts +1 -1
  153. package/dist/rowCoordinateCalculations.d.ts +2 -0
  154. package/dist/rowCoordinateCalculations.js +26 -0
  155. package/dist/rowCoordinateCalculations.js.map +1 -0
  156. package/dist/rowCoordinateCalculations.test.d.ts +1 -0
  157. package/dist/rowCoordinateCalculations.test.js +18 -0
  158. package/dist/rowCoordinateCalculations.test.js.map +1 -0
  159. package/dist/util.d.ts +2 -2
  160. package/dist/util.js +0 -2
  161. package/dist/util.js.map +1 -1
  162. package/dist/version.d.ts +1 -1
  163. package/dist/version.js +1 -1
  164. package/dist/version.js.map +1 -1
  165. package/package.json +10 -3
  166. package/src/colorSchemes.ts +7 -6
  167. package/src/components/Checkbox2.tsx +1 -1
  168. package/src/components/Loading.tsx +18 -6
  169. package/src/components/MSAView.tsx +27 -18
  170. package/src/components/ResizeHandles.tsx +9 -5
  171. package/src/components/SequenceTextArea.tsx +10 -4
  172. package/src/components/TextTrack.tsx +3 -3
  173. package/src/components/Track.tsx +9 -5
  174. package/src/components/VerticalScrollbar.tsx +89 -0
  175. package/src/components/dialogs/AboutDialog.tsx +7 -1
  176. package/src/components/dialogs/AddTrackDialog.tsx +15 -5
  177. package/src/components/dialogs/DomainDialog.tsx +12 -5
  178. package/src/components/dialogs/ExportSVGDialog.tsx +37 -18
  179. package/src/components/dialogs/FeatureDialog.tsx +10 -8
  180. package/src/components/dialogs/{InterProScanPanel.tsx → InterProScanDialog.tsx} +30 -13
  181. package/src/components/dialogs/MetadataDialog.tsx +9 -2
  182. package/src/components/dialogs/SettingsDialog.tsx +98 -19
  183. package/src/components/dialogs/TracklistDialog.tsx +18 -4
  184. package/src/components/dialogs/UserProvidedDomainsDialog.tsx +139 -0
  185. package/src/components/header/Header.tsx +12 -5
  186. package/src/components/header/HeaderInfoArea.tsx +4 -3
  187. package/src/components/header/HeaderMenu.tsx +13 -8
  188. package/src/components/header/HeaderMenuExtra.tsx +59 -43
  189. package/src/components/header/HeaderStatusArea.tsx +2 -6
  190. package/src/components/header/MultiAlignmentSelector.tsx +1 -1
  191. package/src/components/header/ZoomControls.tsx +52 -2
  192. package/src/components/import/ImportForm.tsx +16 -4
  193. package/src/components/import/ImportFormExamples.tsx +77 -64
  194. package/src/components/import/util.ts +2 -2
  195. package/src/components/minimap/Minimap.tsx +34 -29
  196. package/src/components/minimap/MinimapSVG.tsx +2 -2
  197. package/src/components/msa/MSACanvas.tsx +11 -4
  198. package/src/components/msa/MSACanvasBlock.tsx +10 -7
  199. package/src/components/msa/MSAMouseoverCanvas.tsx +1 -1
  200. package/src/components/msa/MSAPanel.tsx +1 -1
  201. package/src/components/msa/renderBoxFeatureCanvasBlock.ts +8 -9
  202. package/src/components/msa/renderMSABlock.ts +44 -24
  203. package/src/components/msa/renderMSAMouseover.ts +4 -4
  204. package/src/components/tree/TreeBranchMenu.tsx +6 -4
  205. package/src/components/tree/TreeCanvas.tsx +15 -16
  206. package/src/components/tree/TreeCanvasBlock.tsx +14 -6
  207. package/src/components/tree/TreeNodeMenu.tsx +4 -4
  208. package/src/components/tree/TreePanel.tsx +1 -1
  209. package/src/components/tree/TreeRuler.tsx +1 -1
  210. package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +12 -3
  211. package/src/components/tree/renderTreeCanvas.ts +32 -12
  212. package/src/components/util.ts +2 -5
  213. package/src/ggplotPalettes.ts +1 -1
  214. package/src/launchInterProScan.ts +13 -15
  215. package/src/model/DataModel.ts +10 -0
  216. package/src/model/DialogQueue.ts +1 -2
  217. package/src/model.ts +355 -112
  218. package/src/parseGFF.ts +13 -11
  219. package/src/parseNewick.ts +4 -4
  220. package/src/parsers/ClustalMSA.ts +3 -3
  221. package/src/parsers/FastaMSA.ts +5 -5
  222. package/src/parsers/StockholmMSA.ts +11 -11
  223. package/src/renderToSvg.tsx +7 -8
  224. package/src/reparseTree.ts +1 -1
  225. package/src/rowCoordinateCalculations.test.ts +19 -0
  226. package/src/rowCoordinateCalculations.ts +26 -0
  227. package/src/util.ts +2 -4
  228. package/src/version.ts +1 -1
  229. package/dist/components/dialogs/InterProScanPanel.js.map +0 -1
  230. package/dist/components/dialogs/UserProvidedResultPanel.d.ts +0 -7
  231. package/dist/components/dialogs/UserProvidedResultPanel.js +0 -56
  232. package/dist/components/dialogs/UserProvidedResultPanel.js.map +0 -1
  233. package/src/components/dialogs/UserProvidedResultPanel.tsx +0 -119
@@ -2,23 +2,20 @@ import React, { lazy } from 'react'
2
2
  import { observer } from 'mobx-react'
3
3
  import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton'
4
4
 
5
- // locals
6
-
7
5
  // icons
8
- import MoreVert from '@mui/icons-material/MoreVert'
6
+ import MoreVert from '@mui/icons-material/Menu'
9
7
  import Sort from '@mui/icons-material/Sort'
10
8
  import Visibility from '@mui/icons-material/Visibility'
11
9
  import FilterAlt from '@mui/icons-material/FilterAlt'
12
10
  import Search from '@mui/icons-material/Search'
13
11
  import PhotoCamera from '@mui/icons-material/PhotoCamera'
14
- import RestartAlt from '@mui/icons-material/RestartAlt'
15
- import FolderOpen from '@mui/icons-material/FolderOpen'
16
12
  import Settings from '@mui/icons-material/Settings'
17
13
  import Assignment from '@mui/icons-material/Assignment'
18
14
  import List from '@mui/icons-material/List'
15
+ import FolderOpen from '@mui/icons-material/FolderOpen'
19
16
 
20
17
  // locals
21
- import { MsaViewModel } from '../../model'
18
+ import type { MsaViewModel } from '../../model'
22
19
 
23
20
  // lazies
24
21
  const SettingsDialog = lazy(() => import('../dialogs/SettingsDialog'))
@@ -26,72 +23,100 @@ const MetadataDialog = lazy(() => import('../dialogs/MetadataDialog'))
26
23
  const TracklistDialog = lazy(() => import('../dialogs/TracklistDialog'))
27
24
  const ExportSVGDialog = lazy(() => import('../dialogs/ExportSVGDialog'))
28
25
  const FeatureFilterDialog = lazy(() => import('../dialogs/FeatureDialog'))
29
- const DomainDialog = lazy(() => import('../dialogs/DomainDialog'))
26
+ const UserProvidedDomainsDialog = lazy(
27
+ () => import('../dialogs/UserProvidedDomainsDialog'),
28
+ )
29
+ const InterProScanDialog = lazy(() => import('../dialogs/InterProScanDialog'))
30
30
 
31
- const HeaderMenuExtra = observer(function ({ model }: { model: MsaViewModel }) {
32
- const { showDomains, subFeatureRows, noAnnotations } = model
31
+ const HeaderMenuExtra = observer(({ model }: { model: MsaViewModel }) => {
32
+ const { showDomains, actuallyShowDomains, subFeatureRows, noDomains } = model
33
33
  return (
34
34
  <CascadingMenuButton
35
35
  menuItems={[
36
36
  {
37
37
  label: 'Return to import form',
38
38
  icon: FolderOpen,
39
- onClick: () => model.reset(),
39
+ onClick: () => {
40
+ model.reset()
41
+ },
40
42
  },
41
43
  {
42
44
  label: 'Settings',
43
- onClick: () =>
44
- model.queueDialog(onClose => [SettingsDialog, { model, onClose }]),
45
+ onClick: () => {
46
+ model.queueDialog(onClose => [SettingsDialog, { model, onClose }])
47
+ },
45
48
  icon: Settings,
46
49
  },
47
50
  {
48
51
  label: 'Metadata',
49
- onClick: () =>
50
- model.queueDialog(onClose => [MetadataDialog, { model, onClose }]),
52
+ onClick: () => {
53
+ model.queueDialog(onClose => [MetadataDialog, { model, onClose }])
54
+ },
51
55
  icon: Assignment,
52
56
  },
53
57
  {
54
58
  label: 'Extra tracks',
55
- onClick: () =>
56
- model.queueDialog(onClose => [TracklistDialog, { model, onClose }]),
57
- icon: List,
58
- },
59
- {
60
- label: 'Reset zoom to default',
61
- icon: RestartAlt,
62
59
  onClick: () => {
63
- model.setColWidth(16)
64
- model.setRowHeight(20)
60
+ model.queueDialog(onClose => [TracklistDialog, { model, onClose }])
65
61
  },
62
+ icon: List,
66
63
  },
64
+
67
65
  {
68
66
  label: 'Export SVG',
69
67
  icon: PhotoCamera,
70
- onClick: () =>
71
- model.queueDialog(onClose => [ExportSVGDialog, { onClose, model }]),
68
+ onClick: () => {
69
+ model.queueDialog(onClose => [ExportSVGDialog, { onClose, model }])
70
+ },
72
71
  },
73
72
  {
74
73
  label: 'Features/protein domains',
75
74
  type: 'subMenu',
76
75
  subMenu: [
77
76
  {
78
- label:
79
- 'Show domains' + (noAnnotations ? ' (no domains loaded)' : ''),
77
+ label: 'Open domains...',
78
+ icon: FolderOpen,
79
+ onClick: () => {
80
+ model.queueDialog(handleClose => [
81
+ UserProvidedDomainsDialog,
82
+ { handleClose, model },
83
+ ])
84
+ },
85
+ },
86
+ {
87
+ label: 'Query InterProScan for domains...',
88
+ icon: Search,
89
+ onClick: () => {
90
+ model.queueDialog(handleClose => [
91
+ InterProScanDialog,
92
+ { handleClose, model },
93
+ ])
94
+ },
95
+ },
96
+ {
97
+ label: `Show domains${noDomains ? ' (no domains loaded)' : ''}`,
98
+ disabled: noDomains,
80
99
  icon: Visibility,
81
- checked: showDomains,
100
+ checked: actuallyShowDomains ? showDomains : false,
82
101
  type: 'checkbox',
83
- onClick: () => model.setShowDomains(!showDomains),
102
+ onClick: () => {
103
+ model.setShowDomains(!showDomains)
104
+ },
84
105
  },
85
106
  {
86
- label: 'Use sub-row layout',
87
- checked: subFeatureRows,
107
+ label: `Use sub-row layout${noDomains ? ' (no domains loaded)' : ''}`,
108
+ disabled: noDomains,
109
+ checked: actuallyShowDomains ? subFeatureRows : false,
88
110
  icon: Sort,
89
111
  type: 'checkbox',
90
- onClick: () => model.setSubFeatureRows(!subFeatureRows),
112
+ onClick: () => {
113
+ model.setSubFeatureRows(!subFeatureRows)
114
+ },
91
115
  },
92
116
  {
93
- label: 'Filter domains',
117
+ label: `Filter domains${noDomains ? ' (no domains loaded)' : ''}`,
94
118
  icon: FilterAlt,
119
+ disabled: noDomains,
95
120
  onClick: () => {
96
121
  model.queueDialog(onClose => [
97
122
  FeatureFilterDialog,
@@ -99,18 +124,9 @@ const HeaderMenuExtra = observer(function ({ model }: { model: MsaViewModel }) {
99
124
  ])
100
125
  },
101
126
  },
102
- {
103
- label: 'View domains',
104
- icon: Search,
105
- onClick: () =>
106
- model.queueDialog(handleClose => [
107
- DomainDialog,
108
- { handleClose, model },
109
- ]),
110
- },
111
127
  ],
112
128
  },
113
- ...(model.extraViewMenuItems?.() || []),
129
+ ...model.extraViewMenuItems(),
114
130
  ]}
115
131
  >
116
132
  <MoreVert />
@@ -5,7 +5,7 @@ import { makeStyles } from 'tss-react/mui'
5
5
  import { LoadingEllipses } from '@jbrowse/core/ui'
6
6
 
7
7
  // locals
8
- import { MsaViewModel } from '../../model'
8
+ import type { MsaViewModel } from '../../model'
9
9
 
10
10
  const useStyles = makeStyles()({
11
11
  margin: {
@@ -14,11 +14,7 @@ const useStyles = makeStyles()({
14
14
  },
15
15
  })
16
16
 
17
- const HeaderStatusArea = observer(function ({
18
- model,
19
- }: {
20
- model: MsaViewModel
21
- }) {
17
+ const HeaderStatusArea = observer(({ model }: { model: MsaViewModel }) => {
22
18
  const { status } = model
23
19
  const { classes } = useStyles()
24
20
  return status ? (
@@ -3,7 +3,7 @@ import { observer } from 'mobx-react'
3
3
  import { Select } from '@mui/material'
4
4
 
5
5
  // locals
6
- import { MsaViewModel } from '../../model'
6
+ import type { MsaViewModel } from '../../model'
7
7
 
8
8
  const MultiAlignmentSelector = observer(function ({
9
9
  model,
@@ -1,6 +1,7 @@
1
1
  import React from 'react'
2
2
  import { IconButton } from '@mui/material'
3
3
  import { observer } from 'mobx-react'
4
+ import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton'
4
5
 
5
6
  // locals
6
7
  import { MsaViewModel } from '../../model'
@@ -8,6 +9,8 @@ import { MsaViewModel } from '../../model'
8
9
  // icons
9
10
  import ZoomIn from '@mui/icons-material/ZoomIn'
10
11
  import ZoomOut from '@mui/icons-material/ZoomOut'
12
+ import MoreVert from '@mui/icons-material/MoreVert'
13
+ import RestartAlt from '@mui/icons-material/RestartAlt'
11
14
 
12
15
  const ZoomControls = observer(function ZoomControls({
13
16
  model,
@@ -16,12 +19,59 @@ const ZoomControls = observer(function ZoomControls({
16
19
  }) {
17
20
  return (
18
21
  <>
19
- <IconButton onClick={() => model.zoomIn()}>
22
+ <IconButton
23
+ onClick={() => {
24
+ model.zoomIn()
25
+ }}
26
+ >
20
27
  <ZoomIn />
21
28
  </IconButton>
22
- <IconButton onClick={() => model.zoomOut()}>
29
+ <IconButton
30
+ onClick={() => {
31
+ model.zoomOut()
32
+ }}
33
+ >
23
34
  <ZoomOut />
24
35
  </IconButton>
36
+ <CascadingMenuButton
37
+ menuItems={[
38
+ {
39
+ label: 'Zoom in horizontal',
40
+ onClick: () => {
41
+ model.zoomInHorizontal()
42
+ },
43
+ },
44
+ {
45
+ label: 'Zoom in vertical',
46
+ onClick: () => {
47
+ model.zoomInVertical()
48
+ },
49
+ },
50
+ {
51
+ label: 'Zoom out horizontal',
52
+ onClick: () => {
53
+ model.zoomOutHorizontal()
54
+ },
55
+ },
56
+
57
+ {
58
+ label: 'Zoom out vertical',
59
+ onClick: () => {
60
+ model.zoomOutVertical()
61
+ },
62
+ },
63
+ {
64
+ label: 'Reset zoom to default',
65
+ icon: RestartAlt,
66
+ onClick: () => {
67
+ model.setColWidth(16)
68
+ model.setRowHeight(20)
69
+ },
70
+ },
71
+ ]}
72
+ >
73
+ <MoreVert />
74
+ </CascadingMenuButton>
25
75
  </>
26
76
  )
27
77
  })
@@ -2,14 +2,14 @@ import React, { useState } from 'react'
2
2
  import { observer } from 'mobx-react'
3
3
  import { Button, Container, Grid, Typography } from '@mui/material'
4
4
  import { FileSelector } from '@jbrowse/core/ui'
5
- import { FileLocation } from '@jbrowse/core/util/types'
5
+ import type { FileLocation } from '@jbrowse/core/util/types'
6
6
 
7
7
  // locals
8
- import { MsaViewModel } from '../../model'
8
+ import type { MsaViewModel } from '../../model'
9
9
  import { load } from './util'
10
10
  import ImportFormExamples from './ImportFormExamples'
11
11
 
12
- export default observer(({ model }: { model: MsaViewModel }) => {
12
+ const ImportForm = observer(function ({ model }: { model: MsaViewModel }) {
13
13
  const [msaFile, setMsaFile] = useState<FileLocation>()
14
14
  const [treeFile, setTreeFile] = useState<FileLocation>()
15
15
  const { error } = model
@@ -44,7 +44,17 @@ export default observer(({ model }: { model: MsaViewModel }) => {
44
44
 
45
45
  <Grid item>
46
46
  <Button
47
- onClick={() => load(model, msaFile, treeFile)}
47
+ onClick={() => {
48
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
49
+ ;(async () => {
50
+ try {
51
+ await load(model, msaFile, treeFile)
52
+ } catch (e) {
53
+ console.error(e)
54
+ model.setError(e)
55
+ }
56
+ })()
57
+ }}
48
58
  variant="contained"
49
59
  color="primary"
50
60
  disabled={!msaFile && !treeFile}
@@ -61,3 +71,5 @@ export default observer(({ model }: { model: MsaViewModel }) => {
61
71
  </Container>
62
72
  )
63
73
  })
74
+
75
+ export default ImportForm
@@ -3,11 +3,11 @@ import { Typography, Link } from '@mui/material'
3
3
  import { observer } from 'mobx-react'
4
4
 
5
5
  // locals
6
- import { MsaViewModel } from '../../model'
6
+ import type { MsaViewModel } from '../../model'
7
7
  import { smallTree, smallMSA, smallMSAOnly } from './data/seq2'
8
8
  import { load } from './util'
9
9
 
10
- const ListItem = ({
10
+ function ListItem({
11
11
  onClick,
12
12
  model,
13
13
  children,
@@ -15,36 +15,63 @@ const ListItem = ({
15
15
  onClick: () => void
16
16
  model: MsaViewModel
17
17
  children: React.ReactNode
18
- }) => (
19
- <li>
20
- <Link
21
- onClick={event => {
22
- model.setError(undefined)
23
- event.preventDefault()
24
- onClick()
25
- }}
26
- href="#"
27
- >
28
- <Typography display="inline">{children}</Typography>
29
- </Link>
30
- </li>
31
- )
18
+ }) {
19
+ return (
20
+ <li>
21
+ <Link
22
+ onClick={event => {
23
+ model.setError(undefined)
24
+ event.preventDefault()
25
+ onClick()
26
+ }}
27
+ href="#"
28
+ >
29
+ <Typography display="inline">{children}</Typography>
30
+ </Link>
31
+ </li>
32
+ )
33
+ }
32
34
 
33
35
  const ImportFormExamples = observer(function ({
34
36
  model,
35
37
  }: {
36
38
  model: MsaViewModel
37
39
  }) {
40
+ function l2(uri1?: string, uri2?: string) {
41
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
42
+ ;(async () => {
43
+ try {
44
+ await load(
45
+ model,
46
+ uri1
47
+ ? {
48
+ uri: uri1,
49
+ locationType: 'UriLocation',
50
+ }
51
+ : undefined,
52
+ uri2
53
+ ? {
54
+ uri: uri2,
55
+ locationType: 'UriLocation',
56
+ }
57
+ : undefined,
58
+ )
59
+ } catch (e) {
60
+ console.error(e)
61
+ model.setError(e)
62
+ }
63
+ })()
64
+ }
38
65
  return (
39
66
  <ul>
40
67
  <ListItem
41
68
  model={model}
42
- onClick={() =>
43
- load(model, undefined, {
44
- uri: 'https://jbrowse.org/genomes/newick_trees/sarscov2phylo.pub.ft.nh',
45
- locationType: 'UriLocation',
46
- })
47
- }
69
+ onClick={() => {
70
+ l2(
71
+ undefined,
72
+ 'https://jbrowse.org/genomes/newicktrees/sarscov2phylo.pub.ft.nh',
73
+ )
74
+ }}
48
75
  >
49
76
  230k COVID-19 samples (tree only)
50
77
  </ListItem>
@@ -66,74 +93,60 @@ const ImportFormExamples = observer(function ({
66
93
  </ListItem>
67
94
  <ListItem
68
95
  model={model}
69
- onClick={() =>
70
- load(model, {
71
- uri: 'https://jbrowse.org/genomes/multiple_sequence_alignments/pfam-cov2.stock',
72
- locationType: 'UriLocation',
73
- })
74
- }
96
+ onClick={() => {
97
+ l2(
98
+ 'https://jbrowse.org/genomes/multiple_sequence_alignments/pfam-cov2.stock',
99
+ )
100
+ }}
75
101
  >
76
102
  PFAM SARS-CoV2 multi-stockholm
77
103
  </ListItem>
78
104
  <ListItem
79
105
  model={model}
80
- onClick={() =>
81
- load(model, {
82
- uri: 'https://jbrowse.org/genomes/multiple_sequence_alignments/Lysine.stock',
83
- locationType: 'UriLocation',
84
- })
85
- }
106
+ onClick={() => {
107
+ l2(
108
+ 'https://jbrowse.org/genomes/multiple_sequence_alignments/Lysine.stock',
109
+ )
110
+ }}
86
111
  >
87
112
  Lysine stockholm file
88
113
  </ListItem>
89
114
  <ListItem
90
115
  model={model}
91
- onClick={() =>
92
- load(model, {
93
- uri: 'https://jbrowse.org/genomes/multiple_sequence_alignments/PF01601_full.txt',
94
- locationType: 'UriLocation',
95
- })
96
- }
116
+ onClick={() => {
117
+ l2(
118
+ 'https://jbrowse.org/genomes/multiple_sequence_alignments/PF01601_full.txt',
119
+ )
120
+ }}
97
121
  >
98
122
  PF01601 stockholm file (SARS-CoV2 spike protein)
99
123
  </ListItem>
100
124
  <ListItem
101
125
  model={model}
102
- onClick={() =>
103
- load(model, {
104
- uri: 'https://jbrowse.org/genomes/multiple_sequence_alignments/europe_covid.fa',
105
- locationType: 'UriLocation',
106
- })
107
- }
126
+ onClick={() => {
127
+ l2(
128
+ 'https://jbrowse.org/genomes/multiple_sequence_alignments/europe_covid.fa',
129
+ )
130
+ }}
108
131
  >
109
132
  Europe COVID full genomes (LR883044.1 and 199 other sequences)
110
133
  </ListItem>
111
134
  <ListItem
112
135
  model={model}
113
- onClick={() =>
114
- load(
115
- model,
116
- {
117
- uri: 'https://jbrowse.org/genomes/multiple_sequence_alignments/rhv_test-only.aligned_with_mafft_auto.fa',
118
- locationType: 'UriLocation',
119
- },
120
- {
121
- uri: 'https://jbrowse.org/genomes/multiple_sequence_alignments/rhv_test-only.aligned_with_mafft_auto.nh',
122
- locationType: 'UriLocation',
123
- },
136
+ onClick={() => {
137
+ l2(
138
+ 'https://jbrowse.org/genomes/multiple_sequence_alignments/rhv_test-only.aligned_with_mafft_auto.fa',
139
+ 'https://jbrowse.org/genomes/multiple_sequence_alignments/rhv_test-only.aligned_with_mafft_auto.nh',
124
140
  )
125
- }
141
+ }}
126
142
  >
127
143
  MAFFT+VeryFastTree(17.9k samples)
128
144
  </ListItem>
129
145
  <ListItem
130
146
  model={model}
131
- onClick={() =>
132
- load(model, {
133
- uri: 'https://jbrowse.org/demos/ttc39a.mfa',
134
- locationType: 'UriLocation',
135
- })
136
- }
147
+ onClick={() => {
148
+ l2('https://jbrowse.org/demos/ttc39a.mfa')
149
+ }}
137
150
  >
138
151
  Human BLAST results mfa
139
152
  </ListItem>
@@ -1,5 +1,5 @@
1
- import { FileLocation } from '@jbrowse/core/util'
2
- import { MsaViewModel } from '../../model'
1
+ import type { FileLocation } from '@jbrowse/core/util'
2
+ import type { MsaViewModel } from '../../model'
3
3
 
4
4
  export async function load(
5
5
  model: MsaViewModel,
@@ -1,27 +1,24 @@
1
1
  import React, { useEffect, useRef, useState } from 'react'
2
2
  import { observer } from 'mobx-react'
3
- import { MsaViewModel } from '../../model'
3
+ import type { MsaViewModel } from '../../model'
4
+
5
+ interface ClickCoord {
6
+ clientX: number
7
+ scrollX: number
8
+ }
4
9
 
5
10
  const Minimap = observer(function ({ model }: { model: MsaViewModel }) {
6
- const [mouseDown, setMouseDown] = useState<{
7
- clientX: number
8
- scrollX: number
9
- }>()
10
- const scheduled = useRef(false)
11
+ const [mouseDown, setMouseDown] = useState<ClickCoord>()
11
12
  const [hovered, setHovered] = useState(false)
12
- const {
13
- scrollX,
14
- msaAreaWidth: W,
15
- minimapHeight: H,
16
- colWidth,
17
- numColumns,
18
- } = model
19
- const unit = W / numColumns / colWidth
13
+ const scheduled = useRef(false)
14
+ const { scrollX, msaAreaWidth, minimapHeight, colWidth, numColumns } = model
15
+ const unit = msaAreaWidth / numColumns / colWidth
20
16
  const left = -scrollX
21
- const right = left + W
17
+ const right = left + msaAreaWidth
22
18
  const s = left * unit
23
19
  const e = right * unit
24
20
  const fill = 'rgba(66, 119, 127, 0.3)'
21
+ const w = Math.max(e - s, 20)
25
22
 
26
23
  useEffect(() => {
27
24
  function fn(event: MouseEvent) {
@@ -50,14 +47,20 @@ const Minimap = observer(function ({ model }: { model: MsaViewModel }) {
50
47
  }
51
48
  }, [model, unit, mouseDown])
52
49
 
53
- const BAR_HEIGHT = 12
54
- const H2 = H - 12
50
+ const barHeight = 12
51
+ const polygonHeight = minimapHeight - barHeight
55
52
  return (
56
- <div style={{ position: 'relative', height: H, width: '100%' }}>
53
+ <div
54
+ style={{
55
+ position: 'relative',
56
+ height: minimapHeight,
57
+ width: '100%',
58
+ }}
59
+ >
57
60
  <div
58
61
  style={{
62
+ height: barHeight,
59
63
  boxSizing: 'border-box',
60
- height: BAR_HEIGHT,
61
64
  border: '1px solid #555',
62
65
  }}
63
66
  />
@@ -68,14 +71,16 @@ const Minimap = observer(function ({ model }: { model: MsaViewModel }) {
68
71
  left: Math.max(0, s),
69
72
  background: hovered ? 'rgba(66,119,127,0.6)' : fill,
70
73
  cursor: 'pointer',
71
- border: '1px solid #555',
72
- boxSizing: 'border-box',
73
- height: BAR_HEIGHT,
74
- width: e - s,
74
+ height: barHeight,
75
+ width: w,
75
76
  zIndex: 100,
76
77
  }}
77
- onMouseOver={() => setHovered(true)}
78
- onMouseOut={() => setHovered(false)}
78
+ onMouseOver={() => {
79
+ setHovered(true)
80
+ }}
81
+ onMouseOut={() => {
82
+ setHovered(false)
83
+ }}
79
84
  onMouseDown={event => {
80
85
  setMouseDown({
81
86
  clientX: event.clientX,
@@ -84,14 +89,14 @@ const Minimap = observer(function ({ model }: { model: MsaViewModel }) {
84
89
  }}
85
90
  />
86
91
 
87
- <svg height={H2} style={{ width: '100%' }}>
92
+ <svg height={polygonHeight} style={{ width: '100%' }}>
88
93
  <polygon
89
94
  fill={fill}
90
95
  points={[
91
- [e, 0],
96
+ [s + w, 0],
92
97
  [s, 0],
93
- [0, H2],
94
- [W, H2],
98
+ [0, polygonHeight],
99
+ [msaAreaWidth, polygonHeight],
95
100
  ].toString()}
96
101
  />
97
102
  </svg>
@@ -1,8 +1,8 @@
1
1
  import React from 'react'
2
2
  import { observer } from 'mobx-react'
3
- import { MsaViewModel } from '../../model'
3
+ import type { MsaViewModel } from '../../model'
4
4
 
5
- const MinimapSVG = observer(function ({ model }: { model: MsaViewModel }) {
5
+ const MinimapSVG = observer(({ model }: { model: MsaViewModel }) => {
6
6
  const {
7
7
  scrollX,
8
8
  msaAreaWidth: W,