react-msaview 9.1.0 → 9.2.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.
- package/bundle/index.js +111 -115
- package/bundle/index.js.map +4 -4
- package/dist/blosum62.d.ts +3 -0
- package/dist/blosum62.js +43 -0
- package/dist/blosum62.js.map +1 -0
- package/dist/colorSchemes.js +1 -0
- package/dist/colorSchemes.js.map +1 -1
- package/dist/components/Loading.d.ts +3 -2
- package/dist/components/Loading.js +2 -2
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/MSAView.d.ts +3 -2
- package/dist/components/MSAView.js +7 -4
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/MSAViewer.d.ts +64 -12
- package/dist/components/MetadataTable.d.ts +4 -1
- package/dist/components/MetadataTable.js +55 -16
- package/dist/components/MetadataTable.js.map +1 -1
- package/dist/components/Track.js +6 -0
- package/dist/components/Track.js.map +1 -1
- package/dist/components/controls.js +2 -1
- package/dist/components/controls.js.map +1 -1
- package/dist/components/dialogs/AnnotationFileDialog.js +7 -2
- package/dist/components/dialogs/AnnotationFileDialog.js.map +1 -1
- package/dist/components/dialogs/FeatureDialog.js +2 -2
- package/dist/components/dialogs/FeatureDialog.js.map +1 -1
- package/dist/components/{header/MSASettingsMenu.d.ts → dialogs/GapThresholdDialog.d.ts} +3 -2
- package/dist/components/dialogs/GapThresholdDialog.js +15 -0
- package/dist/components/dialogs/GapThresholdDialog.js.map +1 -0
- package/dist/components/{header → dialogs}/GappynessSlider.d.ts +1 -1
- package/dist/components/{header → dialogs}/GappynessSlider.js +3 -10
- package/dist/components/dialogs/GappynessSlider.js.map +1 -0
- package/dist/components/{header → dialogs}/GoToBox.d.ts +4 -2
- package/dist/components/dialogs/GoToBox.js +48 -0
- package/dist/components/dialogs/GoToBox.js.map +1 -0
- package/dist/components/dialogs/GoToDialog.d.ts +6 -0
- package/dist/components/dialogs/GoToDialog.js +10 -0
- package/dist/components/dialogs/GoToDialog.js.map +1 -0
- package/dist/components/dialogs/MetadataDialog.js +11 -3
- package/dist/components/dialogs/MetadataDialog.js.map +1 -1
- package/dist/components/dialogs/goTo.d.ts +5 -0
- package/dist/components/{header → dialogs}/goTo.js +1 -1
- package/dist/components/dialogs/goTo.js.map +1 -0
- package/dist/components/dialogs/metadataLabels.d.ts +4 -0
- package/dist/components/dialogs/metadataLabels.js +52 -0
- package/dist/components/dialogs/metadataLabels.js.map +1 -0
- package/dist/components/dialogs/metadataRecord.d.ts +1 -0
- package/dist/components/dialogs/metadataRecord.js +38 -0
- package/dist/components/dialogs/metadataRecord.js.map +1 -0
- package/dist/components/header/Header.d.ts +6 -2
- package/dist/components/header/Header.js +30 -32
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/header/{TreeSettingsMenu.d.ts → HiddenColumnsChip.d.ts} +2 -2
- package/dist/components/header/HiddenColumnsChip.js +15 -0
- package/dist/components/header/HiddenColumnsChip.js.map +1 -0
- package/dist/components/header/MenuBar.d.ts +6 -0
- package/dist/components/header/MenuBar.js +33 -0
- package/dist/components/header/MenuBar.js.map +1 -0
- package/dist/components/header/ScrollZoomCheckbox.d.ts +7 -0
- package/dist/components/header/ScrollZoomCheckbox.js +19 -0
- package/dist/components/header/ScrollZoomCheckbox.js.map +1 -0
- package/dist/components/header/ZoomControls.js +10 -30
- package/dist/components/header/ZoomControls.js.map +1 -1
- package/dist/components/header/colorSchemeMenuItems.d.ts +4 -0
- package/dist/components/header/colorSchemeMenuItems.js +106 -0
- package/dist/components/header/colorSchemeMenuItems.js.map +1 -0
- package/dist/components/header/getAnnotationsMenu.d.ts +3 -30
- package/dist/components/header/getAnnotationsMenu.js +48 -54
- package/dist/components/header/getAnnotationsMenu.js.map +1 -1
- package/dist/components/header/menuBarItems.d.ts +11 -0
- package/dist/components/header/menuBarItems.js +277 -0
- package/dist/components/header/menuBarItems.js.map +1 -0
- package/dist/components/import/ImportForm.js +12 -6
- package/dist/components/import/ImportForm.js.map +1 -1
- package/dist/components/minimap/Minimap.js +7 -3
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/minimap/MinimapSVG.js +2 -1
- package/dist/components/minimap/MinimapSVG.js.map +1 -1
- package/dist/components/minimap/minimapLayout.d.ts +12 -0
- package/dist/components/minimap/minimapLayout.js +20 -0
- package/dist/components/minimap/minimapLayout.js.map +1 -1
- package/dist/components/msa/MSACanvas.js +26 -9
- package/dist/components/msa/MSACanvas.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.js +15 -11
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js +2 -2
- package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
- package/dist/components/msa/WheelZoomHint.d.ts +7 -0
- package/dist/components/msa/WheelZoomHint.js +38 -0
- package/dist/components/msa/WheelZoomHint.js.map +1 -0
- package/dist/components/msa/msaKeys.js +3 -0
- package/dist/components/msa/msaKeys.js.map +1 -1
- package/dist/components/msa/msaRaster.d.ts +4 -5
- package/dist/components/msa/msaRaster.js +5 -5
- package/dist/components/msa/msaRaster.js.map +1 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js +22 -2
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
- package/dist/components/msa/renderHighlights.d.ts +0 -3
- package/dist/components/msa/renderHighlights.js +3 -3
- package/dist/components/msa/renderHighlights.js.map +1 -1
- package/dist/components/msa/renderMSABlock.d.ts +6 -1
- package/dist/components/msa/renderMSABlock.js +44 -17
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/tileColor.js +7 -0
- package/dist/components/msa/tileColor.js.map +1 -1
- package/dist/components/rowpanels/RowPanelBlock.js +2 -2
- package/dist/components/rowpanels/RowPanelBlock.js.map +1 -1
- package/dist/components/settings/MenuItemsForm.d.ts +10 -0
- package/dist/components/settings/MenuItemsForm.js +80 -0
- package/dist/components/settings/MenuItemsForm.js.map +1 -0
- package/dist/components/settings/SettingsPanel.d.ts +12 -0
- package/dist/components/settings/SettingsPanel.js +92 -0
- package/dist/components/settings/SettingsPanel.js.map +1 -0
- package/dist/components/{header/FileMenu.d.ts → settings/TrackList.d.ts} +2 -2
- package/dist/components/settings/TrackList.js +58 -0
- package/dist/components/settings/TrackList.js.map +1 -0
- package/dist/components/tracks/TrackBlocks.js +2 -2
- package/dist/components/tracks/TrackBlocks.js.map +1 -1
- package/dist/components/tracks/TrackTooltipContent.js +2 -1
- package/dist/components/tracks/TrackTooltipContent.js.map +1 -1
- package/dist/components/tracks/drawTracks.js +13 -6
- package/dist/components/tracks/drawTracks.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +2 -2
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/TreeMenu.js +4 -6
- package/dist/components/tree/TreeMenu.js.map +1 -1
- package/dist/components/tree/TreeOverview.js +2 -2
- package/dist/components/tree/TreeOverview.js.map +1 -1
- package/dist/constants.d.ts +4 -1
- package/dist/constants.js +7 -1
- package/dist/constants.js.map +1 -1
- package/dist/darkReader.d.ts +7 -0
- package/dist/darkReader.js +42 -0
- package/dist/darkReader.js.map +1 -0
- package/dist/element.js +22 -47
- package/dist/element.js.map +1 -1
- package/dist/featurePanels.d.ts +37 -0
- package/dist/featurePanels.js +187 -0
- package/dist/featurePanels.js.map +1 -0
- package/dist/filehandleLoader.d.ts +41 -0
- package/dist/filehandleLoader.js +99 -0
- package/dist/filehandleLoader.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/model/treeModel.d.ts +9 -0
- package/dist/model/treeModel.js +12 -1
- package/dist/model/treeModel.js.map +1 -1
- package/dist/model.d.ts +148 -32
- package/dist/model.js +291 -569
- package/dist/model.js.map +1 -1
- package/dist/neighborJoining.js +1 -40
- package/dist/neighborJoining.js.map +1 -1
- package/dist/renderToSvg.js +1 -13
- package/dist/renderToSvg.js.map +1 -1
- package/dist/rerootTree.d.ts +1 -0
- package/dist/rerootTree.js +7 -6
- package/dist/rerootTree.js.map +1 -1
- package/dist/schemeResidueColor.d.ts +12 -0
- package/dist/schemeResidueColor.js +33 -0
- package/dist/schemeResidueColor.js.map +1 -0
- package/dist/similarityColors.d.ts +11 -0
- package/dist/similarityColors.js +90 -0
- package/dist/similarityColors.js.map +1 -0
- package/dist/svgTestUtil.d.ts +64 -12
- package/dist/treeDisplay.d.ts +37 -0
- package/dist/treeDisplay.js +209 -0
- package/dist/treeDisplay.js.map +1 -0
- package/dist/types.d.ts +7 -3
- package/dist/useWheelScroll.d.ts +3 -1
- package/dist/useWheelScroll.js +36 -17
- package/dist/useWheelScroll.js.map +1 -1
- package/dist/util.d.ts +2 -0
- package/dist/util.js +2 -0
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/wheelZoom.d.ts +8 -3
- package/dist/wheelZoom.js +44 -32
- package/dist/wheelZoom.js.map +1 -1
- package/dist/zoomSnapshot.d.ts +29 -0
- package/dist/zoomSnapshot.js +47 -0
- package/dist/zoomSnapshot.js.map +1 -0
- package/package.json +11 -11
- package/src/blosum62.ts +45 -0
- package/src/colorSchemes.ts +1 -0
- package/src/components/Loading.tsx +6 -2
- package/src/components/MSAView.tsx +22 -5
- package/src/components/MetadataTable.tsx +83 -26
- package/src/components/Track.tsx +13 -0
- package/src/components/controls.ts +2 -1
- package/src/components/dialogs/AnnotationFileDialog.tsx +12 -1
- package/src/components/dialogs/FeatureDialog.tsx +2 -5
- package/src/components/dialogs/GapThresholdDialog.tsx +36 -0
- package/src/components/{header → dialogs}/GappynessSlider.tsx +3 -10
- package/src/components/{header → dialogs}/GoToBox.tsx +36 -10
- package/src/components/dialogs/GoToDialog.tsx +30 -0
- package/src/components/dialogs/MetadataDialog.tsx +32 -4
- package/src/components/{header → dialogs}/goTo.ts +1 -1
- package/src/components/dialogs/metadataLabels.ts +54 -0
- package/src/components/dialogs/metadataRecord.tsx +61 -0
- package/src/components/header/Header.tsx +75 -42
- package/src/components/header/HiddenColumnsChip.tsx +39 -0
- package/src/components/header/MenuBar.tsx +64 -0
- package/src/components/header/ScrollZoomCheckbox.tsx +46 -0
- package/src/components/header/ZoomControls.tsx +20 -35
- package/src/components/header/colorSchemeMenuItems.ts +121 -0
- package/src/components/header/getAnnotationsMenu.ts +52 -56
- package/src/components/header/menuBarItems.ts +357 -0
- package/src/components/import/ImportForm.tsx +19 -7
- package/src/components/minimap/Minimap.tsx +11 -3
- package/src/components/minimap/MinimapSVG.tsx +17 -1
- package/src/components/minimap/minimapLayout.ts +27 -0
- package/src/components/msa/MSACanvas.tsx +22 -3
- package/src/components/msa/MSACanvasBlock.tsx +18 -11
- package/src/components/msa/MSAMouseoverCanvas.tsx +2 -2
- package/src/components/msa/WheelZoomHint.tsx +56 -0
- package/src/components/msa/msaKeys.ts +3 -0
- package/src/components/msa/msaRaster.ts +6 -8
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +28 -5
- package/src/components/msa/renderHighlights.ts +3 -3
- package/src/components/msa/renderMSABlock.ts +51 -15
- package/src/components/msa/tileColor.ts +7 -0
- package/src/components/rowpanels/RowPanelBlock.tsx +2 -2
- package/src/components/settings/MenuItemsForm.tsx +225 -0
- package/src/components/settings/SettingsPanel.tsx +156 -0
- package/src/components/settings/TrackList.tsx +124 -0
- package/src/components/tracks/TrackBlocks.tsx +2 -2
- package/src/components/tracks/TrackTooltipContent.tsx +2 -1
- package/src/components/tracks/drawTracks.ts +15 -7
- package/src/components/tree/TreeCanvasBlock.tsx +2 -2
- package/src/components/tree/TreeMenu.tsx +4 -6
- package/src/components/tree/TreeOverview.tsx +2 -2
- package/src/constants.ts +9 -1
- package/src/darkReader.ts +57 -0
- package/src/element.ts +34 -57
- package/src/featurePanels.ts +269 -0
- package/src/filehandleLoader.ts +136 -0
- package/src/index.ts +4 -0
- package/src/model/treeModel.ts +13 -0
- package/src/model.ts +370 -748
- package/src/neighborJoining.ts +1 -42
- package/src/renderToSvg.tsx +1 -13
- package/src/rerootTree.ts +7 -6
- package/src/schemeResidueColor.ts +37 -0
- package/src/similarityColors.ts +112 -0
- package/src/treeDisplay.ts +278 -0
- package/src/types.ts +7 -4
- package/src/useWheelScroll.ts +43 -22
- package/src/util.ts +3 -0
- package/src/version.ts +1 -1
- package/src/wheelZoom.ts +55 -33
- package/src/zoomSnapshot.ts +80 -0
- package/dist/components/header/ColorSchemeMenu.d.ts +0 -12
- package/dist/components/header/ColorSchemeMenu.js +0 -37
- package/dist/components/header/ColorSchemeMenu.js.map +0 -1
- package/dist/components/header/FileMenu.js +0 -92
- package/dist/components/header/FileMenu.js.map +0 -1
- package/dist/components/header/GappynessSlider.js.map +0 -1
- package/dist/components/header/GoToBox.js +0 -31
- package/dist/components/header/GoToBox.js.map +0 -1
- package/dist/components/header/MSASettingsMenu.js +0 -11
- package/dist/components/header/MSASettingsMenu.js.map +0 -1
- package/dist/components/header/ScrollZoomIcons.d.ts +0 -6
- package/dist/components/header/ScrollZoomIcons.js +0 -35
- package/dist/components/header/ScrollZoomIcons.js.map +0 -1
- package/dist/components/header/TreeSettingsMenu.js +0 -11
- package/dist/components/header/TreeSettingsMenu.js.map +0 -1
- package/dist/components/header/goTo.d.ts +0 -20
- package/dist/components/header/goTo.js.map +0 -1
- package/dist/components/header/settingsMenuItems.d.ts +0 -5
- package/dist/components/header/settingsMenuItems.js +0 -171
- package/dist/components/header/settingsMenuItems.js.map +0 -1
- package/src/components/header/ColorSchemeMenu.tsx +0 -56
- package/src/components/header/FileMenu.tsx +0 -107
- package/src/components/header/MSASettingsMenu.tsx +0 -26
- package/src/components/header/ScrollZoomIcons.tsx +0 -52
- package/src/components/header/TreeSettingsMenu.tsx +0 -30
- package/src/components/header/settingsMenuItems.ts +0 -216
|
@@ -1,29 +1,33 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useEffect } from 'react'
|
|
2
2
|
|
|
3
3
|
import useMeasure from '@jbrowse/core/util/useMeasure'
|
|
4
|
-
import
|
|
5
|
-
import { IconButton, Tooltip } from '@mui/material'
|
|
4
|
+
import Tune from '@mui/icons-material/Tune'
|
|
5
|
+
import { AppBar, Button, IconButton, Toolbar, Tooltip } from '@mui/material'
|
|
6
6
|
import { observer } from 'mobx-react'
|
|
7
7
|
|
|
8
8
|
import StatusMessage from '../StatusMessage.tsx'
|
|
9
|
-
import ColorSchemeMenu from './ColorSchemeMenu.tsx'
|
|
10
|
-
import FileMenu from './FileMenu.tsx'
|
|
11
|
-
import GappynessSlider from './GappynessSlider.tsx'
|
|
12
|
-
import GoToBox from './GoToBox.tsx'
|
|
13
9
|
import HeaderInfoArea from './HeaderInfoArea.tsx'
|
|
10
|
+
import HiddenColumnsChip from './HiddenColumnsChip.tsx'
|
|
14
11
|
import LoadWarnings from './LoadWarnings.tsx'
|
|
15
|
-
import
|
|
12
|
+
import MenuBar from './MenuBar.tsx'
|
|
16
13
|
import MultiAlignmentSelector from './MultiAlignmentSelector.tsx'
|
|
14
|
+
import ScrollZoomCheckbox from './ScrollZoomCheckbox.tsx'
|
|
17
15
|
import SelectionMenu from './SelectionMenu.tsx'
|
|
18
|
-
import TreeSettingsMenu from './TreeSettingsMenu.tsx'
|
|
19
16
|
import UnshareableDataWarning from './UnshareableDataWarning.tsx'
|
|
20
17
|
import ZoomControls from './ZoomControls.tsx'
|
|
21
18
|
|
|
22
19
|
import type { MsaViewModel } from '../../model.ts'
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
export interface ToolbarSlots {
|
|
22
|
+
toolbarStart?: React.ReactNode
|
|
23
|
+
toolbarEnd?: React.ReactNode
|
|
24
|
+
}
|
|
25
25
|
|
|
26
|
-
const Header = observer(function ({
|
|
26
|
+
const Header = observer(function ({
|
|
27
|
+
model,
|
|
28
|
+
toolbarStart,
|
|
29
|
+
toolbarEnd,
|
|
30
|
+
}: { model: MsaViewModel } & ToolbarSlots) {
|
|
27
31
|
const [ref, { height }] = useMeasure()
|
|
28
32
|
useEffect(() => {
|
|
29
33
|
model.setHeaderHeight(height ?? 0)
|
|
@@ -35,37 +39,66 @@ const Header = observer(function ({ model }: { model: MsaViewModel }) {
|
|
|
35
39
|
[model],
|
|
36
40
|
)
|
|
37
41
|
return (
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
42
|
+
<AppBar
|
|
43
|
+
ref={ref}
|
|
44
|
+
position="static"
|
|
45
|
+
color="default"
|
|
46
|
+
elevation={0}
|
|
47
|
+
sx={{ borderBottom: 1, borderColor: 'divider' }}
|
|
48
|
+
>
|
|
49
|
+
<Toolbar
|
|
50
|
+
variant="dense"
|
|
51
|
+
disableGutters
|
|
52
|
+
sx={{ minHeight: 40, flexWrap: 'wrap', px: 0.5 }}
|
|
53
|
+
>
|
|
54
|
+
{toolbarStart}
|
|
55
|
+
<MenuBar model={model} />
|
|
56
|
+
{model.embeddedMode ? (
|
|
57
|
+
<Tooltip title="Settings">
|
|
58
|
+
<IconButton
|
|
59
|
+
data-testid="settings_button"
|
|
60
|
+
aria-label="Settings"
|
|
61
|
+
color={model.settingsOpen ? 'primary' : 'inherit'}
|
|
62
|
+
onClick={() => {
|
|
63
|
+
model.setSettingsOpen(!model.settingsOpen)
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
<Tune />
|
|
67
|
+
</IconButton>
|
|
68
|
+
</Tooltip>
|
|
69
|
+
) : (
|
|
70
|
+
<Button
|
|
71
|
+
data-testid="settings_button"
|
|
72
|
+
size="small"
|
|
73
|
+
startIcon={<Tune />}
|
|
74
|
+
color={model.settingsOpen ? 'primary' : 'inherit'}
|
|
75
|
+
variant={model.settingsOpen ? 'outlined' : 'text'}
|
|
76
|
+
onClick={() => {
|
|
77
|
+
model.setSettingsOpen(!model.settingsOpen)
|
|
78
|
+
}}
|
|
79
|
+
sx={{ mx: 0.5, flexShrink: 0 }}
|
|
80
|
+
>
|
|
81
|
+
Settings
|
|
82
|
+
</Button>
|
|
83
|
+
)}
|
|
84
|
+
<ZoomControls model={model} />
|
|
85
|
+
<ScrollZoomCheckbox model={model} />
|
|
86
|
+
<HiddenColumnsChip model={model} />
|
|
87
|
+
<div style={{ paddingLeft: 20, margin: 'auto' }}>
|
|
88
|
+
<MultiAlignmentSelector model={model} />
|
|
89
|
+
</div>
|
|
90
|
+
{/* zero flex-basis, so what appears here on a selection or a hover
|
|
91
|
+
shrinks into the header's spare width and never wraps it */}
|
|
92
|
+
<div style={{ flex: '1 1 0', minWidth: 0, display: 'flex' }}>
|
|
93
|
+
<SelectionMenu model={model} />
|
|
94
|
+
<HeaderInfoArea model={model} />
|
|
95
|
+
</div>
|
|
96
|
+
<LoadWarnings model={model} />
|
|
97
|
+
<UnshareableDataWarning model={model} />
|
|
98
|
+
<StatusMessage model={model} variant="header" />
|
|
99
|
+
{toolbarEnd}
|
|
100
|
+
</Toolbar>
|
|
101
|
+
</AppBar>
|
|
69
102
|
)
|
|
70
103
|
})
|
|
71
104
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React, { lazy } from 'react'
|
|
2
|
+
|
|
3
|
+
import { Chip, Tooltip } from '@mui/material'
|
|
4
|
+
import { observer } from 'mobx-react'
|
|
5
|
+
|
|
6
|
+
import type { MsaViewModel } from '../../model.ts'
|
|
7
|
+
|
|
8
|
+
const GapThresholdDialog = lazy(
|
|
9
|
+
() => import('../dialogs/GapThresholdDialog.tsx'),
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
const HiddenColumnsChip = observer(function ({
|
|
13
|
+
model,
|
|
14
|
+
}: {
|
|
15
|
+
model: MsaViewModel
|
|
16
|
+
}) {
|
|
17
|
+
const n = model.blanks.length
|
|
18
|
+
return n > 0 ? (
|
|
19
|
+
<Tooltip
|
|
20
|
+
title={`Hiding columns with ≥${model.allowedGappyness}% gaps. Click to change the threshold, × to show every column`}
|
|
21
|
+
>
|
|
22
|
+
<Chip
|
|
23
|
+
data-testid="hidden_columns_chip"
|
|
24
|
+
size="small"
|
|
25
|
+
variant="outlined"
|
|
26
|
+
label={`${n.toLocaleString('en-US')} gappy column${n === 1 ? '' : 's'} hidden`}
|
|
27
|
+
style={{ margin: 'auto 8px', flexShrink: 0 }}
|
|
28
|
+
onClick={() => {
|
|
29
|
+
model.queueDialog(onClose => [GapThresholdDialog, { model, onClose }])
|
|
30
|
+
}}
|
|
31
|
+
onDelete={() => {
|
|
32
|
+
model.setHideGaps(false)
|
|
33
|
+
}}
|
|
34
|
+
/>
|
|
35
|
+
</Tooltip>
|
|
36
|
+
) : null
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
export default HiddenColumnsChip
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton'
|
|
4
|
+
import Build from '@mui/icons-material/Build'
|
|
5
|
+
import Help from '@mui/icons-material/Help'
|
|
6
|
+
import InsertDriveFile from '@mui/icons-material/InsertDriveFile'
|
|
7
|
+
import Visibility from '@mui/icons-material/Visibility'
|
|
8
|
+
import { Tooltip } from '@mui/material'
|
|
9
|
+
import { observer } from 'mobx-react'
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
fileMenuItems,
|
|
13
|
+
helpMenuItems,
|
|
14
|
+
toolsMenuItems,
|
|
15
|
+
viewMenuItems,
|
|
16
|
+
} from './menuBarItems.ts'
|
|
17
|
+
|
|
18
|
+
import type { MsaViewModel } from '../../model.ts'
|
|
19
|
+
import type { MenuItem } from '@jbrowse/core/ui/Menu'
|
|
20
|
+
import type { SxProps, Theme } from '@mui/material'
|
|
21
|
+
|
|
22
|
+
// CascadingMenuButton renders an IconButton on every core a host may ship, so
|
|
23
|
+
// these styles give it the look of a small text Button
|
|
24
|
+
const menuButtonSx: SxProps<Theme> = {
|
|
25
|
+
borderRadius: 1,
|
|
26
|
+
typography: 'button',
|
|
27
|
+
color: 'text.primary',
|
|
28
|
+
px: 1,
|
|
29
|
+
py: 0.5,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const menus: [string, (model: MsaViewModel) => MenuItem[], React.ReactNode][] =
|
|
33
|
+
[
|
|
34
|
+
['File', fileMenuItems, <InsertDriveFile key="file" />],
|
|
35
|
+
['View', viewMenuItems, <Visibility key="view" />],
|
|
36
|
+
['Tools', toolsMenuItems, <Build key="tools" />],
|
|
37
|
+
['Help', helpMenuItems, <Help key="help" />],
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
const MenuBar = observer(function ({ model }: { model: MsaViewModel }) {
|
|
41
|
+
const { embeddedMode } = model
|
|
42
|
+
return menus.map(([name, items, icon]) => {
|
|
43
|
+
const button = (
|
|
44
|
+
<CascadingMenuButton
|
|
45
|
+
key={name}
|
|
46
|
+
data-testid={`${name.toLowerCase()}_menu`}
|
|
47
|
+
aria-label={name}
|
|
48
|
+
menuItems={items(model)}
|
|
49
|
+
sx={menuButtonSx}
|
|
50
|
+
>
|
|
51
|
+
{embeddedMode ? icon : name}
|
|
52
|
+
</CascadingMenuButton>
|
|
53
|
+
)
|
|
54
|
+
return embeddedMode ? (
|
|
55
|
+
<Tooltip key={name} title={name}>
|
|
56
|
+
{button}
|
|
57
|
+
</Tooltip>
|
|
58
|
+
) : (
|
|
59
|
+
button
|
|
60
|
+
)
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
export default MenuBar
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { Checkbox, FormControlLabel, Tooltip } from '@mui/material'
|
|
4
|
+
import { observer } from 'mobx-react'
|
|
5
|
+
|
|
6
|
+
import type { MsaViewModel } from '../../model.ts'
|
|
7
|
+
|
|
8
|
+
// the label and the control jbrowse-components' ScrollZoomToggle uses, kept
|
|
9
|
+
// local because a host's older core lacks that export
|
|
10
|
+
export const scrollZoomLabel = 'Zoom on scroll'
|
|
11
|
+
|
|
12
|
+
const scrollZoomHelp =
|
|
13
|
+
'The mouse wheel zooms the alignment instead of scrolling it; shift+scroll still scrolls. ctrl+scroll (⌘+scroll on a Mac) zooms either way.'
|
|
14
|
+
|
|
15
|
+
const ScrollZoomCheckbox = observer(function ({
|
|
16
|
+
model,
|
|
17
|
+
}: {
|
|
18
|
+
model: MsaViewModel
|
|
19
|
+
}) {
|
|
20
|
+
return (
|
|
21
|
+
<Tooltip title={scrollZoomHelp} describeChild>
|
|
22
|
+
<FormControlLabel
|
|
23
|
+
data-testid="scroll-zoom-toggle"
|
|
24
|
+
style={{
|
|
25
|
+
marginLeft: 4,
|
|
26
|
+
marginRight: model.embeddedMode ? 0 : 8,
|
|
27
|
+
whiteSpace: 'nowrap',
|
|
28
|
+
}}
|
|
29
|
+
control={
|
|
30
|
+
<Checkbox
|
|
31
|
+
size="small"
|
|
32
|
+
checked={model.scrollZoom}
|
|
33
|
+
onChange={() => {
|
|
34
|
+
model.setScrollZoom(!model.scrollZoom)
|
|
35
|
+
}}
|
|
36
|
+
style={{ padding: 6 }}
|
|
37
|
+
/>
|
|
38
|
+
}
|
|
39
|
+
label={model.embeddedMode ? '' : scrollZoomLabel}
|
|
40
|
+
slotProps={{ typography: { variant: 'body2' } }}
|
|
41
|
+
/>
|
|
42
|
+
</Tooltip>
|
|
43
|
+
)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
export default ScrollZoomCheckbox
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
|
|
3
|
-
import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton'
|
|
4
3
|
import FitScreen from '@mui/icons-material/FitScreen'
|
|
5
4
|
import RestartAlt from '@mui/icons-material/RestartAlt'
|
|
6
5
|
import ZoomIn from '@mui/icons-material/ZoomIn'
|
|
@@ -37,40 +36,26 @@ const ZoomControls = observer(function ZoomControls({
|
|
|
37
36
|
<ZoomOut />
|
|
38
37
|
</IconButton>
|
|
39
38
|
</Tooltip>
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
{ type: 'divider' },
|
|
63
|
-
{
|
|
64
|
-
label: 'Reset zoom',
|
|
65
|
-
icon: RestartAlt,
|
|
66
|
-
onClick: () => {
|
|
67
|
-
model.resetZoom()
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
]}
|
|
71
|
-
>
|
|
72
|
-
<FitScreen />
|
|
73
|
-
</CascadingMenuButton>
|
|
39
|
+
<Tooltip title="Fit the whole alignment in the window">
|
|
40
|
+
<IconButton
|
|
41
|
+
aria-label="Fit to window"
|
|
42
|
+
onClick={() => {
|
|
43
|
+
model.fit()
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
<FitScreen />
|
|
47
|
+
</IconButton>
|
|
48
|
+
</Tooltip>
|
|
49
|
+
<Tooltip title="Reset zoom to the default cell size (0)">
|
|
50
|
+
<IconButton
|
|
51
|
+
aria-label="Reset zoom"
|
|
52
|
+
onClick={() => {
|
|
53
|
+
model.resetZoom()
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
<RestartAlt />
|
|
57
|
+
</IconButton>
|
|
58
|
+
</Tooltip>
|
|
74
59
|
</>
|
|
75
60
|
)
|
|
76
61
|
})
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { MsaViewModel } from '../../model.ts'
|
|
2
|
+
import type { MenuItem } from '@jbrowse/core/ui/Menu'
|
|
3
|
+
|
|
4
|
+
type Alphabet = 'any' | 'nucleotide' | 'protein'
|
|
5
|
+
|
|
6
|
+
interface SchemeEntry {
|
|
7
|
+
name: string
|
|
8
|
+
label: string
|
|
9
|
+
alphabet: Alphabet
|
|
10
|
+
// shown at the top level for its alphabet, the rest under More schemes
|
|
11
|
+
featured?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const schemes: SchemeEntry[] = [
|
|
15
|
+
{ name: 'maeditor', label: 'MAEditor', alphabet: 'protein', featured: true },
|
|
16
|
+
{
|
|
17
|
+
name: 'clustalx_protein',
|
|
18
|
+
label: 'Clustal X',
|
|
19
|
+
alphabet: 'protein',
|
|
20
|
+
featured: true,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'clustalx_protein_dynamic',
|
|
24
|
+
label: 'Clustal X, by column conservation',
|
|
25
|
+
alphabet: 'protein',
|
|
26
|
+
featured: true,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'blosum62_dynamic',
|
|
30
|
+
label: 'BLOSUM62 similarity',
|
|
31
|
+
alphabet: 'protein',
|
|
32
|
+
featured: true,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'jalview_hydrophobicity',
|
|
36
|
+
label: 'Hydrophobicity',
|
|
37
|
+
alphabet: 'protein',
|
|
38
|
+
featured: true,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'nucleotide',
|
|
42
|
+
label: 'Nucleotide',
|
|
43
|
+
alphabet: 'nucleotide',
|
|
44
|
+
featured: true,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'rainbow_dna',
|
|
48
|
+
label: 'Rainbow',
|
|
49
|
+
alphabet: 'nucleotide',
|
|
50
|
+
featured: true,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'percent_identity_dynamic',
|
|
54
|
+
label: 'Percent identity',
|
|
55
|
+
alphabet: 'any',
|
|
56
|
+
featured: true,
|
|
57
|
+
},
|
|
58
|
+
{ name: 'none', label: 'None', alphabet: 'any', featured: true },
|
|
59
|
+
{ name: 'clustal', label: 'Clustal', alphabet: 'protein' },
|
|
60
|
+
{ name: 'lesk', label: 'Lesk', alphabet: 'protein' },
|
|
61
|
+
{ name: 'flower', label: 'Flower', alphabet: 'protein' },
|
|
62
|
+
{ name: 'cinema', label: 'Cinema', alphabet: 'protein' },
|
|
63
|
+
{ name: 'jalview_zappo', label: 'Zappo', alphabet: 'protein' },
|
|
64
|
+
{ name: 'jalview_taylor', label: 'Taylor', alphabet: 'protein' },
|
|
65
|
+
{ name: 'jalview_buried', label: 'Buried index', alphabet: 'protein' },
|
|
66
|
+
{ name: 'jalview_prophelix', label: 'Helix propensity', alphabet: 'protein' },
|
|
67
|
+
{
|
|
68
|
+
name: 'jalview_propstrand',
|
|
69
|
+
label: 'Strand propensity',
|
|
70
|
+
alphabet: 'protein',
|
|
71
|
+
},
|
|
72
|
+
{ name: 'jalview_propturn', label: 'Turn propensity', alphabet: 'protein' },
|
|
73
|
+
{ name: 'clustalx_dna', label: 'Clustal X (DNA)', alphabet: 'nucleotide' },
|
|
74
|
+
{ name: 'jbrowse_dna', label: 'JBrowse (DNA)', alphabet: 'nucleotide' },
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
export const catalogedSchemeNames = schemes.map(s => s.name)
|
|
78
|
+
|
|
79
|
+
// While a `customColorScheme` map is set, a checked Custom entry stands for it
|
|
80
|
+
// and no named scheme is checked. Picking a named scheme clears the map. The
|
|
81
|
+
// active scheme always shows at the top level.
|
|
82
|
+
export function colorSchemeMenuItems(model: MsaViewModel): MenuItem[] {
|
|
83
|
+
const { colorSchemeName, customColorScheme, sequenceType } = model
|
|
84
|
+
const alphabet = sequenceType === 'amino' ? 'protein' : 'nucleotide'
|
|
85
|
+
function radio(entry: SchemeEntry) {
|
|
86
|
+
return {
|
|
87
|
+
label: entry.label,
|
|
88
|
+
type: 'radio',
|
|
89
|
+
checked: !customColorScheme && colorSchemeName === entry.name,
|
|
90
|
+
onClick: () => {
|
|
91
|
+
model.setColorSchemeName(entry.name)
|
|
92
|
+
// a scheme picked while the domains fill the cells would color
|
|
93
|
+
// nothing, so the pick hands the cells back to the residues
|
|
94
|
+
if (model.cellFill === 'domain') {
|
|
95
|
+
model.setCellFill('residue')
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
} as const
|
|
99
|
+
}
|
|
100
|
+
const top = (e: SchemeEntry) =>
|
|
101
|
+
(e.featured && (e.alphabet === 'any' || e.alphabet === alphabet)) ||
|
|
102
|
+
(!customColorScheme && e.name === colorSchemeName)
|
|
103
|
+
return [
|
|
104
|
+
...(customColorScheme
|
|
105
|
+
? [
|
|
106
|
+
{
|
|
107
|
+
label: 'Custom',
|
|
108
|
+
type: 'radio',
|
|
109
|
+
checked: true,
|
|
110
|
+
onClick: () => {},
|
|
111
|
+
} as const,
|
|
112
|
+
]
|
|
113
|
+
: []),
|
|
114
|
+
...schemes.filter(top).map(radio),
|
|
115
|
+
{
|
|
116
|
+
label: 'More schemes',
|
|
117
|
+
type: 'subMenu',
|
|
118
|
+
subMenu: schemes.filter(e => !top(e)).map(radio),
|
|
119
|
+
},
|
|
120
|
+
]
|
|
121
|
+
}
|
|
@@ -1,80 +1,76 @@
|
|
|
1
1
|
import { lazy } from 'react'
|
|
2
2
|
|
|
3
|
-
import FilterAlt from '@mui/icons-material/FilterAlt'
|
|
4
|
-
import FolderOpen from '@mui/icons-material/FolderOpen'
|
|
5
|
-
import MenuBook from '@mui/icons-material/MenuBook'
|
|
6
|
-
import Sort from '@mui/icons-material/Sort'
|
|
7
|
-
import Visibility from '@mui/icons-material/Visibility'
|
|
8
|
-
|
|
9
3
|
import type { MsaViewModel } from '../../model.ts'
|
|
4
|
+
import type { MenuItem } from '@jbrowse/core/ui/Menu'
|
|
10
5
|
|
|
11
6
|
const FeatureFilterDialog = lazy(() => import('../dialogs/FeatureDialog.tsx'))
|
|
12
7
|
const AnnotationFileDialog = lazy(
|
|
13
8
|
() => import('../dialogs/AnnotationFileDialog.tsx'),
|
|
14
9
|
)
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
export function openAnnotationFileItem(model: MsaViewModel): MenuItem {
|
|
12
|
+
return {
|
|
13
|
+
label: 'Open annotation file…',
|
|
14
|
+
onClick: () => {
|
|
15
|
+
model.queueDialog(handleClose => [
|
|
16
|
+
AnnotationFileDialog,
|
|
17
|
+
{ handleClose, model },
|
|
18
|
+
])
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
}
|
|
17
22
|
|
|
18
|
-
export function
|
|
19
|
-
const { showDomains, actuallyShowDomains, subFeatureRows
|
|
20
|
-
const noneLoaded = noDomains ? ' (none loaded)' : ''
|
|
23
|
+
export function annotationsSubMenu(model: MsaViewModel): MenuItem[] {
|
|
24
|
+
const { showDomains, actuallyShowDomains, subFeatureRows } = model
|
|
21
25
|
return [
|
|
22
26
|
{
|
|
23
|
-
label: '
|
|
24
|
-
|
|
25
|
-
onClick: () => {
|
|
26
|
-
model.queueDialog(handleClose => [
|
|
27
|
-
AnnotationFileDialog,
|
|
28
|
-
{
|
|
29
|
-
handleClose,
|
|
30
|
-
model,
|
|
31
|
-
},
|
|
32
|
-
])
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
// `react-msaview-cli interpro` reads InterPro's precomputed matches in
|
|
36
|
-
// seconds, and `interproscan` covers rows InterPro has not seen; this links
|
|
37
|
-
// the tutorial for both
|
|
38
|
-
{
|
|
39
|
-
label: 'How to get a domain file...',
|
|
40
|
-
icon: MenuBook,
|
|
41
|
-
onClick: () => {
|
|
42
|
-
window.open(domainsTutorial, '_blank', 'noopener,noreferrer')
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
label: `Show annotations${noneLoaded}`,
|
|
47
|
-
disabled: noDomains,
|
|
48
|
-
icon: Visibility,
|
|
27
|
+
label: 'Show annotations',
|
|
28
|
+
type: 'checkbox',
|
|
49
29
|
checked: actuallyShowDomains,
|
|
50
|
-
type: 'checkbox' as const,
|
|
51
30
|
onClick: () => {
|
|
52
31
|
model.setShowDomains(!showDomains)
|
|
53
32
|
},
|
|
54
33
|
},
|
|
55
34
|
{
|
|
56
|
-
label:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
type: 'checkbox' as const,
|
|
35
|
+
label: 'Sub-row layout',
|
|
36
|
+
type: 'checkbox',
|
|
37
|
+
disabled: !actuallyShowDomains,
|
|
38
|
+
checked: actuallyShowDomains && subFeatureRows,
|
|
61
39
|
onClick: () => {
|
|
62
40
|
model.setSubFeatureRows(!subFeatureRows)
|
|
63
41
|
},
|
|
64
42
|
},
|
|
65
|
-
|
|
66
|
-
label: `Filter annotations${noneLoaded}`,
|
|
67
|
-
icon: FilterAlt,
|
|
68
|
-
disabled: noDomains,
|
|
69
|
-
onClick: () => {
|
|
70
|
-
model.queueDialog(onClose => [
|
|
71
|
-
FeatureFilterDialog,
|
|
72
|
-
{
|
|
73
|
-
onClose,
|
|
74
|
-
model,
|
|
75
|
-
},
|
|
76
|
-
])
|
|
77
|
-
},
|
|
78
|
-
},
|
|
43
|
+
...typeItems(model),
|
|
79
44
|
]
|
|
80
45
|
}
|
|
46
|
+
|
|
47
|
+
// up to this many types list inline, one checkbox each; past it the filter
|
|
48
|
+
// dialog, which searches and counts them, takes over
|
|
49
|
+
const inlineTypes = 12
|
|
50
|
+
|
|
51
|
+
function typeItems(model: MsaViewModel): MenuItem[] {
|
|
52
|
+
const types = [...model.annotationTypes.values()]
|
|
53
|
+
return types.length <= inlineTypes
|
|
54
|
+
? [
|
|
55
|
+
{ type: 'subHeader', label: 'Types' },
|
|
56
|
+
...types.map(({ accession, name }) => ({
|
|
57
|
+
label: name || accession,
|
|
58
|
+
type: 'checkbox' as const,
|
|
59
|
+
checked: !model.featureOff(accession),
|
|
60
|
+
onClick: () => {
|
|
61
|
+
model.setFilter(accession, model.featureOff(accession))
|
|
62
|
+
},
|
|
63
|
+
})),
|
|
64
|
+
]
|
|
65
|
+
: [
|
|
66
|
+
{
|
|
67
|
+
label: 'Filter annotations…',
|
|
68
|
+
onClick: () => {
|
|
69
|
+
model.queueDialog(onClose => [
|
|
70
|
+
FeatureFilterDialog,
|
|
71
|
+
{ onClose, model },
|
|
72
|
+
])
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
]
|
|
76
|
+
}
|