react-msaview 1.3.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/bundle/index.js +285 -97099
  2. package/dist/StructureModel.d.ts +9 -0
  3. package/dist/StructureModel.js +11 -0
  4. package/dist/StructureModel.js.map +1 -0
  5. package/dist/UniprotTrack.d.ts +27 -0
  6. package/dist/UniprotTrack.js +53 -0
  7. package/dist/UniprotTrack.js.map +1 -0
  8. package/dist/colorSchemes.d.ts +5 -11
  9. package/dist/colorSchemes.js +27 -32
  10. package/dist/colorSchemes.js.map +1 -0
  11. package/dist/components/BoxTrack.d.ts +6 -6
  12. package/dist/components/BoxTrack.js +9 -137
  13. package/dist/components/BoxTrack.js.map +1 -0
  14. package/dist/components/BoxTrackBlock.d.ts +8 -0
  15. package/dist/components/BoxTrackBlock.js +136 -0
  16. package/dist/components/BoxTrackBlock.js.map +1 -0
  17. package/dist/components/Header.d.ts +2 -2
  18. package/dist/components/Header.js +55 -48
  19. package/dist/components/Header.js.map +1 -0
  20. package/dist/components/ImportForm.d.ts +2 -2
  21. package/dist/components/ImportForm.js +59 -71
  22. package/dist/components/ImportForm.js.map +1 -0
  23. package/dist/components/MSABlock.d.ts +8 -0
  24. package/dist/components/MSABlock.js +103 -0
  25. package/dist/components/MSABlock.js.map +1 -0
  26. package/dist/components/MSACanvas.d.ts +2 -2
  27. package/dist/components/MSACanvas.js +32 -133
  28. package/dist/components/MSACanvas.js.map +1 -0
  29. package/dist/components/MSAMouseoverCanvas.d.ts +6 -0
  30. package/dist/components/MSAMouseoverCanvas.js +52 -0
  31. package/dist/components/MSAMouseoverCanvas.js.map +1 -0
  32. package/dist/components/MSAView.d.ts +2 -2
  33. package/dist/components/MSAView.js +17 -62
  34. package/dist/components/MSAView.js.map +1 -0
  35. package/dist/components/MultiAlignmentSelector.d.ts +6 -0
  36. package/dist/components/MultiAlignmentSelector.js +13 -0
  37. package/dist/components/MultiAlignmentSelector.js.map +1 -0
  38. package/dist/components/ResizeHandles.d.ts +5 -5
  39. package/dist/components/ResizeHandles.js +31 -32
  40. package/dist/components/ResizeHandles.js.map +1 -0
  41. package/dist/components/Rubberband.d.ts +3 -2
  42. package/dist/components/Rubberband.js +41 -64
  43. package/dist/components/Rubberband.js.map +1 -0
  44. package/dist/components/Ruler.d.ts +2 -16
  45. package/dist/components/Ruler.js +19 -88
  46. package/dist/components/Ruler.js.map +1 -0
  47. package/dist/components/TextTrack.d.ts +5 -5
  48. package/dist/components/TextTrack.js +23 -24
  49. package/dist/components/TextTrack.js.map +1 -0
  50. package/dist/components/Track.d.ts +5 -5
  51. package/dist/components/Track.js +41 -40
  52. package/dist/components/Track.js.map +1 -0
  53. package/dist/components/TreeBranchMenu.d.ts +14 -0
  54. package/dist/components/TreeBranchMenu.js +26 -0
  55. package/dist/components/TreeBranchMenu.js.map +1 -0
  56. package/dist/components/TreeCanvas.d.ts +2 -2
  57. package/dist/components/TreeCanvas.js +24 -356
  58. package/dist/components/TreeCanvas.js.map +1 -0
  59. package/dist/components/TreeCanvasBlock.d.ts +7 -0
  60. package/dist/components/TreeCanvasBlock.js +252 -0
  61. package/dist/components/TreeCanvasBlock.js.map +1 -0
  62. package/dist/components/TreeMenu.d.ts +12 -0
  63. package/dist/components/TreeMenu.js +56 -0
  64. package/dist/components/TreeMenu.js.map +1 -0
  65. package/dist/components/TreeRuler.d.ts +2 -2
  66. package/dist/components/TreeRuler.js +3 -3
  67. package/dist/components/TreeRuler.js.map +1 -0
  68. package/dist/components/VerticalGuide.d.ts +7 -0
  69. package/dist/components/VerticalGuide.js +30 -0
  70. package/dist/components/VerticalGuide.js.map +1 -0
  71. package/dist/components/ZoomControls.d.ts +6 -0
  72. package/dist/components/ZoomControls.js +58 -0
  73. package/dist/components/ZoomControls.js.map +1 -0
  74. package/dist/components/data/seq2.d.ts +3 -3
  75. package/dist/components/data/seq2.js +33 -3
  76. package/dist/components/data/seq2.js.map +1 -0
  77. package/dist/components/dialogs/AboutDlg.d.ts +4 -0
  78. package/dist/components/dialogs/AboutDlg.js +40 -0
  79. package/dist/components/dialogs/AboutDlg.js.map +1 -0
  80. package/{bundle/components → dist/components/dialogs}/AddTrackDlg.d.ts +3 -3
  81. package/dist/components/dialogs/AddTrackDlg.js +26 -0
  82. package/dist/components/dialogs/AddTrackDlg.js.map +1 -0
  83. package/dist/components/{AnnotationDlg.d.ts → dialogs/AnnotationDlg.d.ts} +3 -3
  84. package/dist/components/dialogs/AnnotationDlg.js +65 -0
  85. package/dist/components/dialogs/AnnotationDlg.js.map +1 -0
  86. package/dist/components/dialogs/DetailsDlg.d.ts +7 -0
  87. package/dist/components/dialogs/DetailsDlg.js +13 -0
  88. package/dist/components/dialogs/DetailsDlg.js.map +1 -0
  89. package/dist/components/dialogs/MoreInfoDlg.d.ts +6 -0
  90. package/dist/components/dialogs/MoreInfoDlg.js +11 -0
  91. package/dist/components/dialogs/MoreInfoDlg.js.map +1 -0
  92. package/dist/components/dialogs/SettingsDlg.d.ts +7 -0
  93. package/dist/components/dialogs/SettingsDlg.js +48 -0
  94. package/dist/components/dialogs/SettingsDlg.js.map +1 -0
  95. package/dist/components/dialogs/TrackInfoDlg.d.ts +9 -0
  96. package/{bundle/components → dist/components/dialogs}/TrackInfoDlg.js +12 -13
  97. package/dist/components/dialogs/TrackInfoDlg.js.map +1 -0
  98. package/dist/components/dialogs/TracklistDlg.d.ts +7 -0
  99. package/dist/components/dialogs/TracklistDlg.js +18 -0
  100. package/dist/components/dialogs/TracklistDlg.js.map +1 -0
  101. package/{bundle/components/Ruler.d.ts → dist/components/util.d.ts} +1 -6
  102. package/dist/components/util.js +68 -0
  103. package/dist/components/util.js.map +1 -0
  104. package/dist/index.d.ts +2 -4
  105. package/dist/index.js +3 -3
  106. package/dist/index.js.map +1 -0
  107. package/dist/layout.js +14 -20
  108. package/dist/layout.js.map +1 -0
  109. package/dist/model.d.ts +114 -97
  110. package/dist/model.js +248 -486
  111. package/dist/model.js.map +1 -0
  112. package/dist/parseNewick.d.ts +1 -5
  113. package/dist/parseNewick.js +11 -8
  114. package/dist/parseNewick.js.map +1 -0
  115. package/dist/parsers/ClustalMSA.d.ts +6 -18
  116. package/dist/parsers/ClustalMSA.js +55 -64
  117. package/dist/parsers/ClustalMSA.js.map +1 -0
  118. package/dist/parsers/FastaMSA.d.ts +5 -12
  119. package/dist/parsers/FastaMSA.js +55 -64
  120. package/dist/parsers/FastaMSA.js.map +1 -0
  121. package/dist/parsers/StockholmMSA.d.ts +10 -17
  122. package/dist/parsers/StockholmMSA.js +81 -110
  123. package/dist/parsers/StockholmMSA.js.map +1 -0
  124. package/dist/util.d.ts +34 -7
  125. package/dist/util.js +76 -24
  126. package/dist/util.js.map +1 -0
  127. package/dist/version.d.ts +1 -0
  128. package/dist/version.js +2 -0
  129. package/dist/version.js.map +1 -0
  130. package/package.json +34 -34
  131. package/src/StructureModel.ts +11 -0
  132. package/src/UniprotTrack.ts +59 -0
  133. package/src/colorSchemes.ts +520 -0
  134. package/src/components/BoxTrack.tsx +33 -0
  135. package/src/components/BoxTrackBlock.tsx +198 -0
  136. package/src/components/Header.tsx +106 -0
  137. package/src/components/ImportForm.tsx +192 -0
  138. package/src/components/MSABlock.tsx +164 -0
  139. package/src/components/MSACanvas.tsx +142 -0
  140. package/src/components/MSAMouseoverCanvas.tsx +87 -0
  141. package/src/components/MSAView.tsx +88 -0
  142. package/src/components/MultiAlignmentSelector.tsx +33 -0
  143. package/src/components/ResizeHandles.tsx +137 -0
  144. package/src/components/Rubberband.tsx +270 -0
  145. package/src/components/Ruler.tsx +123 -0
  146. package/src/components/TextTrack.tsx +120 -0
  147. package/src/components/Track.tsx +153 -0
  148. package/src/components/TreeBranchMenu.tsx +67 -0
  149. package/src/components/TreeCanvas.tsx +128 -0
  150. package/src/components/TreeCanvasBlock.tsx +359 -0
  151. package/src/components/TreeMenu.tsx +105 -0
  152. package/src/components/TreeRuler.tsx +12 -0
  153. package/src/components/VerticalGuide.tsx +50 -0
  154. package/src/components/ZoomControls.tsx +78 -0
  155. package/src/components/data/seq2.ts +35 -0
  156. package/src/components/dialogs/AboutDlg.tsx +58 -0
  157. package/src/components/dialogs/AddTrackDlg.tsx +74 -0
  158. package/src/components/dialogs/AnnotationDlg.tsx +144 -0
  159. package/src/components/dialogs/DetailsDlg.tsx +28 -0
  160. package/src/components/dialogs/MoreInfoDlg.tsx +21 -0
  161. package/src/components/dialogs/SettingsDlg.tsx +154 -0
  162. package/src/components/dialogs/TrackInfoDlg.tsx +59 -0
  163. package/src/components/dialogs/TracklistDlg.tsx +59 -0
  164. package/src/components/util.ts +93 -0
  165. package/src/declare.d.ts +1 -0
  166. package/src/index.ts +2 -0
  167. package/src/layout.ts +83 -0
  168. package/src/model.ts +793 -0
  169. package/{bundle/parseNewick.d.ts → src/parseNewick.ts} +35 -5
  170. package/src/parsers/ClustalMSA.ts +79 -0
  171. package/src/parsers/FastaMSA.ts +82 -0
  172. package/src/parsers/StockholmMSA.ts +137 -0
  173. package/src/util.ts +142 -0
  174. package/src/version.ts +1 -0
  175. package/bundle/colorSchemes.d.ts +0 -16
  176. package/bundle/colorSchemes.js +0 -455
  177. package/bundle/components/AboutDlg.d.ts +0 -5
  178. package/bundle/components/AboutDlg.js +0 -47
  179. package/bundle/components/AddTrackDlg.js +0 -26
  180. package/bundle/components/AnnotationDlg.d.ts +0 -11
  181. package/bundle/components/AnnotationDlg.js +0 -77
  182. package/bundle/components/BoxTrack.d.ts +0 -7
  183. package/bundle/components/BoxTrack.js +0 -143
  184. package/bundle/components/DetailsDlg.d.ts +0 -8
  185. package/bundle/components/DetailsDlg.js +0 -12
  186. package/bundle/components/Header.d.ts +0 -6
  187. package/bundle/components/Header.js +0 -63
  188. package/bundle/components/ImportForm.d.ts +0 -6
  189. package/bundle/components/ImportForm.js +0 -89
  190. package/bundle/components/MSACanvas.d.ts +0 -6
  191. package/bundle/components/MSACanvas.js +0 -210
  192. package/bundle/components/MSAView.d.ts +0 -6
  193. package/bundle/components/MSAView.js +0 -88
  194. package/bundle/components/MoreInfoDlg.d.ts +0 -6
  195. package/bundle/components/MoreInfoDlg.js +0 -11
  196. package/bundle/components/ResizeHandles.d.ts +0 -8
  197. package/bundle/components/ResizeHandles.js +0 -110
  198. package/bundle/components/Rubberband.d.ts +0 -7
  199. package/bundle/components/Rubberband.js +0 -196
  200. package/bundle/components/Ruler.js +0 -121
  201. package/bundle/components/SettingsDlg.d.ts +0 -8
  202. package/bundle/components/SettingsDlg.js +0 -40
  203. package/bundle/components/TextTrack.d.ts +0 -7
  204. package/bundle/components/TextTrack.js +0 -72
  205. package/bundle/components/Track.d.ts +0 -11
  206. package/bundle/components/Track.js +0 -81
  207. package/bundle/components/TrackInfoDlg.d.ts +0 -6
  208. package/bundle/components/TracklistDlg.d.ts +0 -8
  209. package/bundle/components/TracklistDlg.js +0 -18
  210. package/bundle/components/TreeCanvas.d.ts +0 -6
  211. package/bundle/components/TreeCanvas.js +0 -431
  212. package/bundle/components/TreeRuler.d.ts +0 -6
  213. package/bundle/components/TreeRuler.js +0 -8
  214. package/bundle/components/data/seq2.d.ts +0 -3
  215. package/bundle/components/data/seq2.js +0 -3
  216. package/bundle/index.d.ts +0 -4
  217. package/bundle/layout.d.ts +0 -23
  218. package/bundle/layout.js +0 -53
  219. package/bundle/model.d.ts +0 -364
  220. package/bundle/model.js +0 -894
  221. package/bundle/parseNewick.js +0 -94
  222. package/bundle/parsers/ClustalMSA.d.ts +0 -39
  223. package/bundle/parsers/ClustalMSA.js +0 -77
  224. package/bundle/parsers/FastaMSA.d.ts +0 -26
  225. package/bundle/parsers/FastaMSA.js +0 -78
  226. package/bundle/parsers/StockholmMSA.d.ts +0 -75
  227. package/bundle/parsers/StockholmMSA.js +0 -142
  228. package/bundle/util.d.ts +0 -17
  229. package/bundle/util.js +0 -33
  230. package/dist/components/AboutDlg.d.ts +0 -5
  231. package/dist/components/AboutDlg.js +0 -50
  232. package/dist/components/AddTrackDlg.d.ts +0 -8
  233. package/dist/components/AddTrackDlg.js +0 -26
  234. package/dist/components/AnnotationDlg.js +0 -77
  235. package/dist/components/DetailsDlg.d.ts +0 -8
  236. package/dist/components/DetailsDlg.js +0 -12
  237. package/dist/components/MoreInfoDlg.d.ts +0 -6
  238. package/dist/components/MoreInfoDlg.js +0 -11
  239. package/dist/components/SettingsDlg.d.ts +0 -8
  240. package/dist/components/SettingsDlg.js +0 -40
  241. package/dist/components/TrackInfoDlg.d.ts +0 -6
  242. package/dist/components/TrackInfoDlg.js +0 -33
  243. package/dist/components/TracklistDlg.d.ts +0 -8
  244. package/dist/components/TracklistDlg.js +0 -18
  245. package/dist/components/package.json +0 -62
@@ -0,0 +1,142 @@
1
+ import React, { useEffect, useState, useRef } from 'react'
2
+ import { Typography, CircularProgress } from '@mui/material'
3
+ import { observer } from 'mobx-react'
4
+ import normalizeWheel from 'normalize-wheel'
5
+
6
+ // locals
7
+ import { MsaViewModel } from '../model'
8
+ import MSABlock from './MSABlock'
9
+
10
+ const MSACanvas = observer(function ({ model }: { model: MsaViewModel }) {
11
+ const { MSA, msaFilehandle, height, msaAreaWidth, blocks2d } = model
12
+ const ref = useRef<HTMLDivElement>(null)
13
+ // wheel
14
+ const scheduled = useRef(false)
15
+ const deltaX = useRef(0)
16
+ const deltaY = useRef(0)
17
+ // mouse click-and-drag scrolling
18
+ const prevX = useRef<number>(0)
19
+ const prevY = useRef<number>(0)
20
+ const [mouseDragging, setMouseDragging] = useState(false)
21
+ useEffect(() => {
22
+ const curr = ref.current
23
+ if (!curr) {
24
+ return
25
+ }
26
+ function onWheel(origEvent: WheelEvent) {
27
+ const event = normalizeWheel(origEvent)
28
+ deltaX.current += event.pixelX
29
+ deltaY.current += event.pixelY
30
+
31
+ if (!scheduled.current) {
32
+ scheduled.current = true
33
+ requestAnimationFrame(() => {
34
+ model.doScrollX(-deltaX.current)
35
+ model.doScrollY(-deltaY.current)
36
+ deltaX.current = 0
37
+ deltaY.current = 0
38
+ scheduled.current = false
39
+ })
40
+ }
41
+ origEvent.preventDefault()
42
+ }
43
+ curr.addEventListener('wheel', onWheel)
44
+ return () => {
45
+ curr.removeEventListener('wheel', onWheel)
46
+ }
47
+ }, [model])
48
+
49
+ useEffect(() => {
50
+ let cleanup = () => {}
51
+
52
+ function globalMouseMove(event: MouseEvent) {
53
+ event.preventDefault()
54
+ const currX = event.clientX
55
+ const currY = event.clientY
56
+ const distanceX = currX - prevX.current
57
+ const distanceY = currY - prevY.current
58
+ if (distanceX || distanceY) {
59
+ // use rAF to make it so multiple event handlers aren't fired per-frame
60
+ // see https://calendar.perfplanet.com/2013/the-runtime-performance-checklist/
61
+ if (!scheduled.current) {
62
+ scheduled.current = true
63
+ window.requestAnimationFrame(() => {
64
+ model.doScrollX(distanceX)
65
+ model.doScrollY(distanceY)
66
+ scheduled.current = false
67
+ prevX.current = event.clientX
68
+ prevY.current = event.clientY
69
+ })
70
+ }
71
+ }
72
+ }
73
+
74
+ function globalMouseUp() {
75
+ prevX.current = 0
76
+ if (mouseDragging) {
77
+ setMouseDragging(false)
78
+ }
79
+ }
80
+
81
+ if (mouseDragging) {
82
+ window.addEventListener('mousemove', globalMouseMove, true)
83
+ window.addEventListener('mouseup', globalMouseUp, true)
84
+ cleanup = () => {
85
+ window.removeEventListener('mousemove', globalMouseMove, true)
86
+ window.removeEventListener('mouseup', globalMouseUp, true)
87
+ }
88
+ }
89
+ return cleanup
90
+ }, [model, mouseDragging])
91
+
92
+ return (
93
+ <div
94
+ ref={ref}
95
+ onMouseDown={event => {
96
+ // check if clicking a draggable element or a resize handle
97
+ const target = event.target as HTMLElement
98
+ if (target.draggable || target.dataset.resizer) {
99
+ return
100
+ }
101
+
102
+ // otherwise do click and drag scroll
103
+ if (event.button === 0) {
104
+ prevX.current = event.clientX
105
+ prevY.current = event.clientY
106
+ setMouseDragging(true)
107
+ }
108
+ }}
109
+ onMouseUp={event => {
110
+ event.preventDefault()
111
+ setMouseDragging(false)
112
+ }}
113
+ onMouseLeave={event => {
114
+ event.preventDefault()
115
+ }}
116
+ style={{
117
+ position: 'relative',
118
+ height,
119
+ width: msaAreaWidth,
120
+ overflow: 'hidden',
121
+ }}
122
+ >
123
+ {!MSA && !msaFilehandle ? null : !MSA ? (
124
+ <div style={{ position: 'absolute', left: '50%', top: '50%' }}>
125
+ <CircularProgress />
126
+ <Typography>Loading...</Typography>
127
+ </div>
128
+ ) : (
129
+ blocks2d.map(([bx, by]) => (
130
+ <MSABlock
131
+ key={`${bx}_${by}`}
132
+ model={model}
133
+ offsetX={bx}
134
+ offsetY={by}
135
+ />
136
+ ))
137
+ )}
138
+ </div>
139
+ )
140
+ })
141
+
142
+ export default MSACanvas
@@ -0,0 +1,87 @@
1
+ import React, { useEffect, useRef } from 'react'
2
+ import { observer } from 'mobx-react'
3
+
4
+ // locals
5
+ import { MsaViewModel } from '../model'
6
+ import { sum } from '@jbrowse/core/util'
7
+
8
+ const MSAMouseoverCanvas = observer(function ({
9
+ model,
10
+ }: {
11
+ model: MsaViewModel
12
+ }) {
13
+ const ref = useRef<HTMLCanvasElement>(null)
14
+ const {
15
+ height,
16
+ width,
17
+ treeAreaWidth,
18
+ resizeHandleWidth,
19
+ rulerHeight,
20
+ turnedOnTracks,
21
+ scrollX,
22
+ scrollY,
23
+ mouseCol,
24
+ mouseRow,
25
+ rowHeight,
26
+ colWidth,
27
+ } = model
28
+ const totalTrackAreaHeight = sum(turnedOnTracks.map(r => r.model.height))
29
+ useEffect(() => {
30
+ if (!ref.current) {
31
+ return
32
+ }
33
+
34
+ const ctx = ref.current.getContext('2d')
35
+ if (!ctx) {
36
+ return
37
+ }
38
+
39
+ ctx.resetTransform()
40
+ ctx.clearRect(0, 0, width, height)
41
+
42
+ ctx.fillStyle = 'rgba(0,0,0,0.15)'
43
+ if (mouseCol !== undefined) {
44
+ const x =
45
+ (mouseCol - 1) * colWidth + scrollX + treeAreaWidth + resizeHandleWidth
46
+
47
+ ctx.fillRect(x, 0, colWidth, height)
48
+ }
49
+ if (mouseRow !== undefined) {
50
+ const y =
51
+ mouseRow * rowHeight + scrollY + rulerHeight + totalTrackAreaHeight
52
+ ctx.fillRect(treeAreaWidth + resizeHandleWidth, y, width, rowHeight)
53
+ }
54
+ }, [
55
+ mouseCol,
56
+ colWidth,
57
+ scrollY,
58
+ totalTrackAreaHeight,
59
+ mouseRow,
60
+ rowHeight,
61
+ rulerHeight,
62
+ scrollX,
63
+ height,
64
+ resizeHandleWidth,
65
+ treeAreaWidth,
66
+ width,
67
+ ])
68
+
69
+ return (
70
+ <canvas
71
+ ref={ref}
72
+ width={width}
73
+ height={height}
74
+ style={{
75
+ position: 'absolute',
76
+ top: 0,
77
+ left: 0,
78
+ width,
79
+ height,
80
+ zIndex: 1000,
81
+ pointerEvents: 'none',
82
+ }}
83
+ />
84
+ )
85
+ })
86
+
87
+ export default MSAMouseoverCanvas
@@ -0,0 +1,88 @@
1
+ import React, { lazy, Suspense } from 'react'
2
+
3
+ import { observer } from 'mobx-react'
4
+ import { Typography } from '@mui/material'
5
+
6
+ // locals
7
+ import ImportForm from './ImportForm'
8
+ import Rubberband from './Rubberband'
9
+ import TreeCanvas from './TreeCanvas'
10
+ import MSACanvas from './MSACanvas'
11
+ import Ruler from './Ruler'
12
+ import TreeRuler from './TreeRuler'
13
+ import Header from './Header'
14
+ import Track from './Track'
15
+
16
+ import { HorizontalResizeHandle, VerticalResizeHandle } from './ResizeHandles'
17
+ import { MsaViewModel } from '../model'
18
+ import MSAMouseoverCanvas from './MSAMouseoverCanvas'
19
+
20
+ const AnnotationDialog = lazy(() => import('./dialogs/AnnotationDlg'))
21
+
22
+ export default observer(function ({ model }: { model: MsaViewModel }) {
23
+ const { done, initialized, treeAreaWidth, height, turnedOnTracks } = model
24
+
25
+ return (
26
+ <div>
27
+ {!initialized ? (
28
+ <ImportForm model={model} />
29
+ ) : !done ? (
30
+ <Typography variant="h4">Loading...</Typography>
31
+ ) : (
32
+ <div>
33
+ <div style={{ height, overflow: 'hidden' }}>
34
+ <Header model={model} />
35
+ <div>
36
+ <div style={{ position: 'relative' }}>
37
+ <div style={{ display: 'flex' }}>
38
+ <div style={{ flexShrink: 0, width: treeAreaWidth }}>
39
+ <TreeRuler model={model} />
40
+ </div>
41
+
42
+ <Rubberband
43
+ model={model}
44
+ ControlComponent={<Ruler model={model} />}
45
+ />
46
+ </div>
47
+ {turnedOnTracks?.map(track => (
48
+ <Track key={track.model.id} model={model} track={track} />
49
+ ))}
50
+
51
+ <div style={{ display: 'flex' }}>
52
+ <div style={{ flexShrink: 0, width: treeAreaWidth }}>
53
+ <TreeCanvas model={model} />
54
+ </div>
55
+ <VerticalResizeHandle model={model} />
56
+ <MSACanvas model={model} />
57
+ <MSAMouseoverCanvas model={model} />
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ <HorizontalResizeHandle model={model} />
63
+ </div>
64
+ )}
65
+
66
+ {model.DialogComponent ? (
67
+ <Suspense fallback={null}>
68
+ <model.DialogComponent
69
+ {...(model.DialogProps || {})}
70
+ onClose={() => {
71
+ model.setDialogComponent(undefined, undefined)
72
+ }}
73
+ />
74
+ </Suspense>
75
+ ) : null}
76
+
77
+ {model.annotPos ? (
78
+ <Suspense fallback={null}>
79
+ <AnnotationDialog
80
+ data={model.annotPos}
81
+ model={model}
82
+ onClose={() => model.clearAnnotPos()}
83
+ />
84
+ </Suspense>
85
+ ) : null}
86
+ </div>
87
+ )
88
+ })
@@ -0,0 +1,33 @@
1
+ import React from 'react'
2
+ import { observer } from 'mobx-react'
3
+ import { Select } from '@mui/material'
4
+
5
+ // locals
6
+ import { MsaViewModel } from '../model'
7
+
8
+ const MultiAlignmentSelector = observer(function ({
9
+ model,
10
+ }: {
11
+ model: MsaViewModel
12
+ }) {
13
+ const { currentAlignment, alignmentNames } = model
14
+ return alignmentNames.length > 0 ? (
15
+ <Select
16
+ native
17
+ value={currentAlignment}
18
+ size="small"
19
+ onChange={event => {
20
+ model.setCurrentAlignment(+(event.target.value as string))
21
+ model.setScrollX(0)
22
+ model.setScrollY(0)
23
+ }}
24
+ >
25
+ {alignmentNames.map((option, index) => (
26
+ <option key={`${option}-${index}`} value={index}>
27
+ {option}
28
+ </option>
29
+ ))}
30
+ </Select>
31
+ ) : null
32
+ })
33
+ export default MultiAlignmentSelector
@@ -0,0 +1,137 @@
1
+ import React, { useEffect, useRef, useState } from 'react'
2
+ import { observer } from 'mobx-react'
3
+
4
+ // locals
5
+ import { MsaViewModel } from '../model'
6
+
7
+ export const VerticalResizeHandle = observer(function ({
8
+ model,
9
+ }: {
10
+ model: MsaViewModel
11
+ }) {
12
+ const { resizeHandleWidth } = model
13
+ const [mouseDragging, setMouseDragging] = useState(false)
14
+ const scheduled = useRef(false)
15
+ const prevX = useRef(0)
16
+
17
+ useEffect(() => {
18
+ function globalMouseMove(event: MouseEvent) {
19
+ event.preventDefault()
20
+ const currX = event.clientX
21
+ if (prevX.current === 0) {
22
+ prevX.current = event.clientX
23
+ } else {
24
+ const distance = currX - prevX.current
25
+ if (distance) {
26
+ // use rAF to make it so multiple event handlers aren't fired per-frame
27
+ // see https://calendar.perfplanet.com/2013/the-runtime-performance-checklist/
28
+ if (!scheduled.current) {
29
+ scheduled.current = true
30
+ window.requestAnimationFrame(() => {
31
+ model.setTreeAreaWidth(model.treeAreaWidth + distance)
32
+ scheduled.current = false
33
+ prevX.current = event.clientX
34
+ })
35
+ }
36
+ }
37
+ }
38
+ }
39
+
40
+ function globalMouseUp() {
41
+ prevX.current = 0
42
+ if (mouseDragging) {
43
+ setMouseDragging(false)
44
+ }
45
+ }
46
+ if (mouseDragging) {
47
+ document.addEventListener('mousemove', globalMouseMove, true)
48
+ document.addEventListener('mouseup', globalMouseUp, true)
49
+ return () => {
50
+ document.removeEventListener('mousemove', globalMouseMove, true)
51
+ document.removeEventListener('mouseup', globalMouseUp, true)
52
+ }
53
+ }
54
+ return () => {}
55
+ }, [mouseDragging, model])
56
+
57
+ return (
58
+ <div>
59
+ <div
60
+ onMouseDown={() => setMouseDragging(true)}
61
+ style={{
62
+ cursor: 'ew-resize',
63
+ height: '100%',
64
+ width: resizeHandleWidth,
65
+ background: `rgba(200,200,200)`,
66
+ position: 'relative',
67
+ }}
68
+ />
69
+ </div>
70
+ )
71
+ })
72
+
73
+ export const HorizontalResizeHandle = observer(function ({
74
+ model,
75
+ }: {
76
+ model: MsaViewModel
77
+ }) {
78
+ const { resizeHandleWidth } = model
79
+ const [mouseDragging, setMouseDragging] = useState(false)
80
+ const scheduled = useRef(false)
81
+ const prevY = useRef(0)
82
+
83
+ useEffect(() => {
84
+ function globalMouseMove(event: MouseEvent) {
85
+ event.preventDefault()
86
+ const currY = event.clientY
87
+ if (prevY.current === 0) {
88
+ prevY.current = event.clientY
89
+ } else {
90
+ const distance = currY - prevY.current
91
+ if (distance) {
92
+ // use rAF to make it so multiple event handlers aren't fired per-frame
93
+ // see https://calendar.perfplanet.com/2013/the-runtime-performance-checklist/
94
+ if (!scheduled.current) {
95
+ scheduled.current = true
96
+ window.requestAnimationFrame(() => {
97
+ model.setHeight(model.height + distance)
98
+ scheduled.current = false
99
+ prevY.current = event.clientY
100
+ })
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ function globalMouseUp() {
107
+ prevY.current = 0
108
+ if (mouseDragging) {
109
+ setMouseDragging(false)
110
+ }
111
+ }
112
+ if (mouseDragging) {
113
+ document.addEventListener('mousemove', globalMouseMove, true)
114
+ document.addEventListener('mouseup', globalMouseUp, true)
115
+ return () => {
116
+ document.removeEventListener('mousemove', globalMouseMove, true)
117
+ document.removeEventListener('mouseup', globalMouseUp, true)
118
+ }
119
+ }
120
+ return () => {}
121
+ }, [mouseDragging, model])
122
+
123
+ return (
124
+ <div>
125
+ <div
126
+ onMouseDown={() => setMouseDragging(true)}
127
+ style={{
128
+ cursor: 'ns-resize',
129
+ width: '100%',
130
+ height: resizeHandleWidth,
131
+ background: `rgba(200,200,200)`,
132
+ position: 'relative',
133
+ }}
134
+ />
135
+ </div>
136
+ )
137
+ })