@jbrowse/plugin-linear-genome-view 3.0.5 → 3.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/dist/BaseLinearDisplay/components/BlockErrorMessage.d.ts +7 -0
- package/dist/BaseLinearDisplay/components/{BlockError.js → BlockErrorMessage.js} +6 -3
- package/dist/BaseLinearDisplay/components/BlockLoadingMessage.d.ts +6 -0
- package/dist/BaseLinearDisplay/components/BlockLoadingMessage.js +26 -0
- package/dist/BaseLinearDisplay/components/BlockMsg.js +4 -2
- package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +4 -24
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +9 -9
- package/dist/LaunchLinearGenomeView/index.js +9 -5
- package/dist/LinearGenomeView/components/CenterLine.js +1 -1
- package/dist/LinearGenomeView/components/Gridlines.d.ts +2 -1
- package/dist/LinearGenomeView/components/Gridlines.js +3 -4
- package/dist/LinearGenomeView/components/Header.js +2 -0
- package/dist/LinearGenomeView/components/LinearGenomeView.js +2 -49
- package/dist/LinearGenomeView/components/LinearGenomeViewContainer.d.ts +5 -0
- package/dist/LinearGenomeView/components/LinearGenomeViewContainer.js +98 -0
- package/dist/LinearGenomeView/components/MiniControls.js +0 -1
- package/dist/LinearGenomeView/components/NoTracksActiveButton.js +1 -1
- package/dist/LinearGenomeView/components/OverviewRubberband.js +2 -15
- package/dist/LinearGenomeView/components/OverviewRubberbandHoverTooltip.d.ts +10 -0
- package/dist/LinearGenomeView/components/OverviewRubberbandHoverTooltip.js +36 -0
- package/dist/LinearGenomeView/components/Rubberband.js +7 -2
- package/dist/LinearGenomeView/components/RubberbandSpan.d.ts +3 -1
- package/dist/LinearGenomeView/components/RubberbandSpan.js +13 -25
- package/dist/LinearGenomeView/components/RubberbandTooltip.d.ts +5 -0
- package/dist/LinearGenomeView/components/RubberbandTooltip.js +28 -0
- package/dist/LinearGenomeView/components/Scalebar.js +2 -2
- package/dist/LinearGenomeView/components/TrackContainer.js +9 -4
- package/dist/LinearGenomeView/components/TrackLabel.js +1 -1
- package/dist/LinearGenomeView/components/TrackLabelContainer.js +1 -1
- package/dist/LinearGenomeView/components/TrackLabelMenu.js +21 -0
- package/dist/LinearGenomeView/components/TrackRenderingContainer.js +0 -1
- package/dist/LinearGenomeView/components/TracksContainer.js +3 -4
- package/dist/LinearGenomeView/components/VerticalGuide.js +12 -5
- package/dist/LinearGenomeView/model.d.ts +31 -3
- package/dist/LinearGenomeView/model.js +84 -24
- package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +2 -2
- package/dist/LinearGenomeView/types.d.ts +5 -0
- package/esm/BaseLinearDisplay/components/BlockErrorMessage.d.ts +7 -0
- package/esm/BaseLinearDisplay/components/{BlockError.js → BlockErrorMessage.js} +6 -3
- package/esm/BaseLinearDisplay/components/BlockLoadingMessage.d.ts +6 -0
- package/esm/BaseLinearDisplay/components/BlockLoadingMessage.js +24 -0
- package/esm/BaseLinearDisplay/components/BlockMsg.js +4 -2
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +4 -24
- package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +9 -9
- package/esm/LaunchLinearGenomeView/index.js +9 -5
- package/esm/LinearGenomeView/components/CenterLine.js +1 -1
- package/esm/LinearGenomeView/components/Gridlines.d.ts +2 -1
- package/esm/LinearGenomeView/components/Gridlines.js +3 -4
- package/esm/LinearGenomeView/components/Header.js +2 -0
- package/esm/LinearGenomeView/components/LinearGenomeView.js +3 -50
- package/esm/LinearGenomeView/components/LinearGenomeViewContainer.d.ts +5 -0
- package/esm/LinearGenomeView/components/LinearGenomeViewContainer.js +60 -0
- package/esm/LinearGenomeView/components/MiniControls.js +0 -1
- package/esm/LinearGenomeView/components/NoTracksActiveButton.js +1 -1
- package/esm/LinearGenomeView/components/OverviewRubberband.js +3 -16
- package/esm/LinearGenomeView/components/OverviewRubberbandHoverTooltip.d.ts +10 -0
- package/esm/LinearGenomeView/components/OverviewRubberbandHoverTooltip.js +34 -0
- package/esm/LinearGenomeView/components/Rubberband.js +7 -2
- package/esm/LinearGenomeView/components/RubberbandSpan.d.ts +3 -1
- package/esm/LinearGenomeView/components/RubberbandSpan.js +11 -26
- package/esm/LinearGenomeView/components/RubberbandTooltip.d.ts +5 -0
- package/esm/LinearGenomeView/components/RubberbandTooltip.js +25 -0
- package/esm/LinearGenomeView/components/Scalebar.js +2 -2
- package/esm/LinearGenomeView/components/TrackContainer.js +9 -4
- package/esm/LinearGenomeView/components/TrackLabel.js +1 -1
- package/esm/LinearGenomeView/components/TrackLabelContainer.js +1 -1
- package/esm/LinearGenomeView/components/TrackLabelMenu.js +21 -0
- package/esm/LinearGenomeView/components/TrackRenderingContainer.js +0 -1
- package/esm/LinearGenomeView/components/TracksContainer.js +3 -4
- package/esm/LinearGenomeView/components/VerticalGuide.js +13 -6
- package/esm/LinearGenomeView/model.d.ts +31 -3
- package/esm/LinearGenomeView/model.js +84 -24
- package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +2 -2
- package/esm/LinearGenomeView/types.d.ts +5 -0
- package/package.json +3 -3
- package/dist/BaseLinearDisplay/components/BlockError.d.ts +0 -4
- package/esm/BaseLinearDisplay/components/BlockError.d.ts +0 -4
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { LoadingEllipses } from '@jbrowse/core/ui';
|
|
3
|
+
import { observer } from 'mobx-react';
|
|
4
|
+
import { getParent } from 'mobx-state-tree';
|
|
5
|
+
import { makeStyles } from 'tss-react/mui';
|
|
6
|
+
const useStyles = makeStyles()(theme => {
|
|
7
|
+
const bg = theme.palette.action.disabledBackground;
|
|
8
|
+
return {
|
|
9
|
+
loading: {
|
|
10
|
+
paddingLeft: '0.6em',
|
|
11
|
+
backgroundColor: theme.palette.background.default,
|
|
12
|
+
backgroundImage: `repeating-linear-gradient(45deg, transparent, transparent 5px, ${bg} 5px, ${bg} 10px)`,
|
|
13
|
+
textAlign: 'center',
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
const BlockLoadingMessage = observer(function ({ model, }) {
|
|
18
|
+
const { classes } = useStyles();
|
|
19
|
+
const { status: blockStatus } = model;
|
|
20
|
+
const { message: displayStatus } = getParent(model, 2);
|
|
21
|
+
const status = displayStatus || blockStatus;
|
|
22
|
+
return (_jsx("div", { className: classes.loading, children: _jsx(LoadingEllipses, { message: status }) }));
|
|
23
|
+
});
|
|
24
|
+
export default BlockLoadingMessage;
|
|
@@ -9,7 +9,9 @@ const useStyles = makeStyles()({
|
|
|
9
9
|
});
|
|
10
10
|
export default function BlockMsg({ message, severity, action, }) {
|
|
11
11
|
const { classes } = useStyles();
|
|
12
|
-
return (_jsx(Alert, {
|
|
12
|
+
return (_jsx(Alert, { severity: severity, action: action, classes: {
|
|
13
|
+
message: classes.ellipses,
|
|
14
|
+
}, onMouseDown: event => {
|
|
13
15
|
event.stopPropagation();
|
|
14
|
-
},
|
|
16
|
+
}, children: _jsx(Tooltip, { title: message, children: _jsx("div", { children: message }) }) }));
|
|
15
17
|
}
|
|
@@ -1,38 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Suspense, isValidElement, lazy } from 'react';
|
|
3
|
-
import { LoadingEllipses } from '@jbrowse/core/ui';
|
|
4
3
|
import { observer } from 'mobx-react';
|
|
5
|
-
import
|
|
6
|
-
import { makeStyles } from 'tss-react/mui';
|
|
4
|
+
import BlockLoadingMessage from './BlockLoadingMessage';
|
|
7
5
|
import BlockMsg from './BlockMsg';
|
|
8
|
-
const
|
|
9
|
-
const useStyles = makeStyles()(theme => {
|
|
10
|
-
const bg = theme.palette.action.disabledBackground;
|
|
11
|
-
return {
|
|
12
|
-
loading: {
|
|
13
|
-
paddingLeft: '0.6em',
|
|
14
|
-
backgroundColor: theme.palette.background.default,
|
|
15
|
-
backgroundImage: `repeating-linear-gradient(45deg, transparent, transparent 5px, ${bg} 5px, ${bg} 10px)`,
|
|
16
|
-
textAlign: 'center',
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
});
|
|
20
|
-
const LoadingMessage = observer(({ model }) => {
|
|
21
|
-
const { classes } = useStyles();
|
|
22
|
-
const { status: blockStatus } = model;
|
|
23
|
-
const { message: displayStatus } = getParent(model, 2);
|
|
24
|
-
const status = displayStatus || blockStatus;
|
|
25
|
-
return (_jsx("div", { className: classes.loading, children: _jsx(LoadingEllipses, { message: status }) }));
|
|
26
|
-
});
|
|
6
|
+
const BlockErrorMessage = lazy(() => import('./BlockErrorMessage'));
|
|
27
7
|
const ServerSideRenderedBlockContent = observer(function ({ model, }) {
|
|
28
8
|
if (model.error) {
|
|
29
|
-
return (_jsx(Suspense, { fallback: null, children: _jsx(
|
|
9
|
+
return (_jsx(Suspense, { fallback: null, children: _jsx(BlockErrorMessage, { model: model }) }));
|
|
30
10
|
}
|
|
31
11
|
else if (model.message) {
|
|
32
12
|
return isValidElement(model.message) ? (model.message) : (_jsx(BlockMsg, { message: `${model.message}`, severity: "info" }));
|
|
33
13
|
}
|
|
34
14
|
else if (!model.filled) {
|
|
35
|
-
return _jsx(
|
|
15
|
+
return _jsx(BlockLoadingMessage, { model: model });
|
|
36
16
|
}
|
|
37
17
|
else {
|
|
38
18
|
return model.reactElement;
|
|
@@ -78,14 +78,14 @@ function stateModelFactory() {
|
|
|
78
78
|
return (_b = (_a = self.blockState.get(blockKey)) === null || _a === void 0 ? void 0 : _a.layout) === null || _b === void 0 ? void 0 : _b.getByID(id);
|
|
79
79
|
},
|
|
80
80
|
searchFeatureByID(id) {
|
|
81
|
+
var _a;
|
|
81
82
|
let ret;
|
|
82
|
-
self.blockState.
|
|
83
|
-
var _a;
|
|
83
|
+
for (const block of self.blockState.values()) {
|
|
84
84
|
const val = (_a = block.layout) === null || _a === void 0 ? void 0 : _a.getByID(id);
|
|
85
85
|
if (val) {
|
|
86
86
|
ret = val;
|
|
87
87
|
}
|
|
88
|
-
}
|
|
88
|
+
}
|
|
89
89
|
return ret;
|
|
90
90
|
},
|
|
91
91
|
}))
|
|
@@ -138,9 +138,9 @@ function stateModelFactory() {
|
|
|
138
138
|
self.setError();
|
|
139
139
|
self.setCurrStatsBpPerPx(0);
|
|
140
140
|
self.clearFeatureDensityStats();
|
|
141
|
-
|
|
141
|
+
for (const val of self.blockState.values()) {
|
|
142
142
|
val.doReload();
|
|
143
|
-
}
|
|
143
|
+
}
|
|
144
144
|
superReload();
|
|
145
145
|
},
|
|
146
146
|
};
|
|
@@ -230,17 +230,17 @@ function stateModelFactory() {
|
|
|
230
230
|
if (!view.initialized) {
|
|
231
231
|
return;
|
|
232
232
|
}
|
|
233
|
-
self.blockDefinitions.contentBlocks
|
|
233
|
+
for (const block of self.blockDefinitions.contentBlocks) {
|
|
234
234
|
blocksPresent[block.key] = true;
|
|
235
235
|
if (!self.blockState.has(block.key)) {
|
|
236
236
|
self.addBlock(block.key, block);
|
|
237
237
|
}
|
|
238
|
-
}
|
|
239
|
-
self.blockState.
|
|
238
|
+
}
|
|
239
|
+
for (const key of self.blockState.keys()) {
|
|
240
240
|
if (!blocksPresent[key]) {
|
|
241
241
|
self.deleteBlock(key);
|
|
242
242
|
}
|
|
243
|
-
}
|
|
243
|
+
}
|
|
244
244
|
}));
|
|
245
245
|
},
|
|
246
246
|
}))
|
|
@@ -20,7 +20,7 @@ export default function LaunchLinearGenomeViewF(pluginManager) {
|
|
|
20
20
|
view.setHideHeader(!nav);
|
|
21
21
|
}
|
|
22
22
|
if (highlight !== undefined) {
|
|
23
|
-
|
|
23
|
+
for (const h of highlight) {
|
|
24
24
|
const p = parseLocString(h, refName => assemblyManager.isValidRefName(refName, assembly));
|
|
25
25
|
const { start, end } = p;
|
|
26
26
|
if (start !== undefined && end !== undefined) {
|
|
@@ -31,13 +31,17 @@ export default function LaunchLinearGenomeViewF(pluginManager) {
|
|
|
31
31
|
assemblyName: assembly,
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
-
}
|
|
34
|
+
}
|
|
35
35
|
}
|
|
36
|
-
await handleSelectedRegion({
|
|
36
|
+
await handleSelectedRegion({
|
|
37
|
+
input: loc,
|
|
38
|
+
model: view,
|
|
39
|
+
assembly: asm,
|
|
40
|
+
});
|
|
37
41
|
const idsNotFound = [];
|
|
38
|
-
|
|
42
|
+
for (const track of tracks) {
|
|
39
43
|
tryTrack(view, track, idsNotFound);
|
|
40
|
-
}
|
|
44
|
+
}
|
|
41
45
|
if (idsNotFound.length) {
|
|
42
46
|
throw new Error(`Could not resolve identifiers: ${idsNotFound.join(',')}`);
|
|
43
47
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { LinearGenomeViewModel } from '..';
|
|
2
2
|
type LGV = LinearGenomeViewModel;
|
|
3
|
-
declare const Gridlines: ({ model }: {
|
|
3
|
+
declare const Gridlines: ({ model, offset, }: {
|
|
4
4
|
model: LGV;
|
|
5
|
+
offset?: number;
|
|
5
6
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
6
7
|
export default Gridlines;
|
|
@@ -6,15 +6,14 @@ import { makeTicks } from '../util';
|
|
|
6
6
|
const useStyles = makeStyles()(theme => ({
|
|
7
7
|
verticalGuidesZoomContainer: {
|
|
8
8
|
position: 'absolute',
|
|
9
|
+
top: 0,
|
|
9
10
|
height: '100%',
|
|
10
11
|
width: '100%',
|
|
11
|
-
zIndex: 1,
|
|
12
12
|
pointerEvents: 'none',
|
|
13
13
|
},
|
|
14
14
|
verticalGuidesContainer: {
|
|
15
15
|
position: 'absolute',
|
|
16
16
|
height: '100%',
|
|
17
|
-
zIndex: 1,
|
|
18
17
|
pointerEvents: 'none',
|
|
19
18
|
display: 'flex',
|
|
20
19
|
},
|
|
@@ -56,13 +55,13 @@ const RenderedVerticalGuides = observer(({ model }) => {
|
|
|
56
55
|
return null;
|
|
57
56
|
}) }));
|
|
58
57
|
});
|
|
59
|
-
const Gridlines = observer(function ({ model }) {
|
|
58
|
+
const Gridlines = observer(function ({ model, offset = 0, }) {
|
|
60
59
|
const { classes } = useStyles();
|
|
61
60
|
const offsetLeft = model.staticBlocks.offsetPx - model.offsetPx;
|
|
62
61
|
return (_jsx("div", { className: classes.verticalGuidesZoomContainer, style: {
|
|
63
62
|
transform: model.scaleFactor !== 1 ? `scaleX(${model.scaleFactor})` : undefined,
|
|
64
63
|
}, children: _jsx("div", { className: classes.verticalGuidesContainer, style: {
|
|
65
|
-
left: offsetLeft,
|
|
64
|
+
left: offsetLeft - offset,
|
|
66
65
|
width: model.staticBlocks.totalWidthPx,
|
|
67
66
|
}, children: _jsx(RenderedVerticalGuides, { model: model }) }) }));
|
|
68
67
|
});
|
|
@@ -8,9 +8,11 @@ import HeaderTrackSelectorButton from './HeaderTrackSelectorButton';
|
|
|
8
8
|
import HeaderZoomControls from './HeaderZoomControls';
|
|
9
9
|
import OverviewScalebar from './OverviewScalebar';
|
|
10
10
|
import SearchBox from './SearchBox';
|
|
11
|
+
import { HEADER_BAR_HEIGHT } from '../consts';
|
|
11
12
|
const useStyles = makeStyles()({
|
|
12
13
|
headerBar: {
|
|
13
14
|
display: 'flex',
|
|
15
|
+
height: HEADER_BAR_HEIGHT,
|
|
14
16
|
},
|
|
15
17
|
headerForm: {
|
|
16
18
|
flexWrap: 'nowrap',
|
|
@@ -1,21 +1,9 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
2
|
-
import {
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { lazy } from 'react';
|
|
3
3
|
import { LoadingEllipses } from '@jbrowse/core/ui';
|
|
4
|
-
import { getSession } from '@jbrowse/core/util';
|
|
5
4
|
import { observer } from 'mobx-react';
|
|
6
|
-
import
|
|
7
|
-
import TrackContainer from './TrackContainer';
|
|
8
|
-
import TracksContainer from './TracksContainer';
|
|
5
|
+
import LinearGenomeViewContainer from './LinearGenomeViewContainer';
|
|
9
6
|
const ImportForm = lazy(() => import('./ImportForm'));
|
|
10
|
-
const NoTracksActiveButton = lazy(() => import('./NoTracksActiveButton'));
|
|
11
|
-
const useStyles = makeStyles()({
|
|
12
|
-
rel: {
|
|
13
|
-
position: 'relative',
|
|
14
|
-
},
|
|
15
|
-
top: {
|
|
16
|
-
zIndex: 1000,
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
7
|
const LinearGenomeView = observer(function ({ model, }) {
|
|
20
8
|
const { error, initialized, hasDisplayedRegions } = model;
|
|
21
9
|
if (!initialized && !error) {
|
|
@@ -28,39 +16,4 @@ const LinearGenomeView = observer(function ({ model, }) {
|
|
|
28
16
|
return _jsx(LinearGenomeViewContainer, { model: model });
|
|
29
17
|
}
|
|
30
18
|
});
|
|
31
|
-
const LinearGenomeViewContainer = observer(function ({ model, }) {
|
|
32
|
-
const { tracks } = model;
|
|
33
|
-
const { classes } = useStyles();
|
|
34
|
-
const session = getSession(model);
|
|
35
|
-
const ref = useRef(null);
|
|
36
|
-
const MiniControlsComponent = model.MiniControlsComponent();
|
|
37
|
-
const HeaderComponent = model.HeaderComponent();
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
function handleSelectView(e) {
|
|
40
|
-
var _a, _b;
|
|
41
|
-
if (e.target instanceof Element && ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
|
|
42
|
-
(_b = session.setFocusedViewId) === null || _b === void 0 ? void 0 : _b.call(session, model.id);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
document.addEventListener('mousedown', handleSelectView);
|
|
46
|
-
document.addEventListener('keydown', handleSelectView);
|
|
47
|
-
return () => {
|
|
48
|
-
document.removeEventListener('mousedown', handleSelectView);
|
|
49
|
-
document.removeEventListener('keydown', handleSelectView);
|
|
50
|
-
};
|
|
51
|
-
}, [session, model]);
|
|
52
|
-
return (_jsxs("div", { className: classes.rel, ref: ref, onMouseLeave: () => {
|
|
53
|
-
session.setHovered(undefined);
|
|
54
|
-
}, onMouseMove: event => {
|
|
55
|
-
const c = ref.current;
|
|
56
|
-
if (!c) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
const { tracks } = model;
|
|
60
|
-
const leftPx = event.clientX - c.getBoundingClientRect().left;
|
|
61
|
-
const hoverPosition = model.pxToBp(leftPx);
|
|
62
|
-
const hoverFeature = tracks.find(t => t.displays[0].featureUnderMouse);
|
|
63
|
-
session.setHovered({ hoverPosition, hoverFeature });
|
|
64
|
-
}, children: [_jsx(HeaderComponent, { model: model }), _jsx(MiniControlsComponent, { model: model }), _jsx(TracksContainer, { model: model, children: !tracks.length ? (_jsx(Suspense, { fallback: null, children: _jsx(NoTracksActiveButton, { model: model }) })) : (tracks.map(track => (_jsx(TrackContainer, { model: model, track: track }, track.id)))) })] }));
|
|
65
|
-
});
|
|
66
19
|
export default LinearGenomeView;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Suspense, lazy, useEffect, useRef } from 'react';
|
|
3
|
+
import { VIEW_HEADER_HEIGHT } from '@jbrowse/core/ui';
|
|
4
|
+
import { getSession } from '@jbrowse/core/util';
|
|
5
|
+
import Paper from '@mui/material/Paper';
|
|
6
|
+
import { observer } from 'mobx-react';
|
|
7
|
+
import { makeStyles } from 'tss-react/mui';
|
|
8
|
+
import TrackContainer from './TrackContainer';
|
|
9
|
+
import TracksContainer from './TracksContainer';
|
|
10
|
+
const NoTracksActiveButton = lazy(() => import('./NoTracksActiveButton'));
|
|
11
|
+
const useStyles = makeStyles()(theme => ({
|
|
12
|
+
header: {
|
|
13
|
+
background: theme.palette.background.paper,
|
|
14
|
+
top: VIEW_HEADER_HEIGHT,
|
|
15
|
+
zIndex: 850,
|
|
16
|
+
},
|
|
17
|
+
pinnedTracks: {
|
|
18
|
+
position: 'sticky',
|
|
19
|
+
zIndex: 3,
|
|
20
|
+
},
|
|
21
|
+
rel: {
|
|
22
|
+
position: 'relative',
|
|
23
|
+
},
|
|
24
|
+
}));
|
|
25
|
+
const LinearGenomeViewContainer = observer(function ({ model, }) {
|
|
26
|
+
const { pinnedTracks, stickyViewHeaders, pinnedTracksTop, tracks, unpinnedTracks, } = model;
|
|
27
|
+
const { classes } = useStyles();
|
|
28
|
+
const session = getSession(model);
|
|
29
|
+
const ref = useRef(null);
|
|
30
|
+
const MiniControlsComponent = model.MiniControlsComponent();
|
|
31
|
+
const HeaderComponent = model.HeaderComponent();
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
function handleSelectView(e) {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
if (e.target instanceof Element && ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
|
|
36
|
+
(_b = session.setFocusedViewId) === null || _b === void 0 ? void 0 : _b.call(session, model.id);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
document.addEventListener('mousedown', handleSelectView);
|
|
40
|
+
document.addEventListener('keydown', handleSelectView);
|
|
41
|
+
return () => {
|
|
42
|
+
document.removeEventListener('mousedown', handleSelectView);
|
|
43
|
+
document.removeEventListener('keydown', handleSelectView);
|
|
44
|
+
};
|
|
45
|
+
}, [session, model]);
|
|
46
|
+
return (_jsxs("div", { className: classes.rel, ref: ref, onMouseLeave: () => {
|
|
47
|
+
session.setHovered(undefined);
|
|
48
|
+
}, onMouseMove: event => {
|
|
49
|
+
const c = ref.current;
|
|
50
|
+
if (!c) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const { tracks } = model;
|
|
54
|
+
const leftPx = event.clientX - c.getBoundingClientRect().left;
|
|
55
|
+
const hoverPosition = model.pxToBp(leftPx);
|
|
56
|
+
const hoverFeature = tracks.find(t => t.displays[0].featureUnderMouse);
|
|
57
|
+
session.setHovered({ hoverPosition, hoverFeature });
|
|
58
|
+
}, children: [_jsxs("div", { className: classes.header, style: { position: stickyViewHeaders ? 'sticky' : undefined }, children: [_jsx(HeaderComponent, { model: model }), _jsx(MiniControlsComponent, { model: model })] }), _jsx(TracksContainer, { model: model, children: !tracks.length ? (_jsx(Suspense, { fallback: null, children: _jsx(NoTracksActiveButton, { model: model }) })) : (_jsxs(_Fragment, { children: [pinnedTracks.length ? (_jsx(Paper, { elevation: 6, className: classes.pinnedTracks, style: { top: pinnedTracksTop }, children: pinnedTracks.map(track => (_jsx(TrackContainer, { model: model, track: track }, track.id))) })) : null, unpinnedTracks.map(track => (_jsx(TrackContainer, { model: model, track: track }, track.id)))] })) })] }));
|
|
59
|
+
});
|
|
60
|
+
export default LinearGenomeViewContainer;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from 'react';
|
|
3
|
-
import { getSession
|
|
4
|
-
import { Tooltip } from '@mui/material';
|
|
3
|
+
import { getSession } from '@jbrowse/core/util';
|
|
5
4
|
import { observer } from 'mobx-react';
|
|
6
5
|
import { makeStyles } from 'tss-react/mui';
|
|
6
|
+
import OverviewRubberbandHoverTooltip from './OverviewRubberbandHoverTooltip';
|
|
7
7
|
import RubberbandSpan from './RubberbandSpan';
|
|
8
8
|
import { getRelativeX } from './util';
|
|
9
9
|
const useStyles = makeStyles()({
|
|
@@ -17,24 +17,11 @@ const useStyles = makeStyles()({
|
|
|
17
17
|
height: '100%',
|
|
18
18
|
width: 1,
|
|
19
19
|
position: 'absolute',
|
|
20
|
-
zIndex: 10,
|
|
21
20
|
},
|
|
22
21
|
rel: {
|
|
23
22
|
position: 'relative',
|
|
24
23
|
},
|
|
25
24
|
});
|
|
26
|
-
const HoverTooltip = observer(function ({ model, open, guideX, overview, }) {
|
|
27
|
-
var _a;
|
|
28
|
-
const { classes } = useStyles();
|
|
29
|
-
const { cytobandOffset } = model;
|
|
30
|
-
const { assemblyManager } = getSession(model);
|
|
31
|
-
const px = overview.pxToBp(guideX - cytobandOffset);
|
|
32
|
-
const assembly = assemblyManager.get(px.assemblyName);
|
|
33
|
-
const cytoband = (_a = assembly === null || assembly === void 0 ? void 0 : assembly.cytobands) === null || _a === void 0 ? void 0 : _a.find(f => px.coord > f.get('start') &&
|
|
34
|
-
px.coord < f.get('end') &&
|
|
35
|
-
px.refName === assembly.getCanonicalRefName(f.get('refName')));
|
|
36
|
-
return (_jsx(Tooltip, { open: open, placement: "top", title: [stringify(px), cytoband === null || cytoband === void 0 ? void 0 : cytoband.get('name')].join(' '), arrow: true, children: _jsx("div", { className: classes.guide, style: { left: guideX } }) }));
|
|
37
|
-
});
|
|
38
25
|
const OverviewRubberband = observer(function OverviewRubberband({ model, overview, ControlComponent = _jsx("div", {}), }) {
|
|
39
26
|
const { cytobandOffset } = model;
|
|
40
27
|
const [startX, setStartX] = useState();
|
|
@@ -104,7 +91,7 @@ const OverviewRubberband = observer(function OverviewRubberband({ model, overvie
|
|
|
104
91
|
setGuideX(undefined);
|
|
105
92
|
}
|
|
106
93
|
if (startX === undefined) {
|
|
107
|
-
return (_jsxs("div", { className: classes.rel, children: [guideX !== undefined ? (_jsx(
|
|
94
|
+
return (_jsxs("div", { className: classes.rel, children: [guideX !== undefined ? (_jsx(OverviewRubberbandHoverTooltip, { model: model, open: !mouseDragging, overview: overview, guideX: guideX })) : null, _jsx("div", { className: classes.rubberbandControl, ref: controlsRef, onMouseDown: mouseDown, onMouseOut: mouseOut, onMouseMove: mouseMove, children: ControlComponent })] }));
|
|
108
95
|
}
|
|
109
96
|
let left = startX || 0;
|
|
110
97
|
let width = 0;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LinearGenomeViewModel } from '..';
|
|
2
|
+
import type { Base1DViewModel } from '@jbrowse/core/util/Base1DViewModel';
|
|
3
|
+
type LGV = LinearGenomeViewModel;
|
|
4
|
+
declare const OverviewRubberbandHoverTooltip: ({ model, open, guideX, overview, }: {
|
|
5
|
+
model: LGV;
|
|
6
|
+
open: boolean;
|
|
7
|
+
guideX: number;
|
|
8
|
+
overview: Base1DViewModel;
|
|
9
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export default OverviewRubberbandHoverTooltip;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { getSession, stringify } from '@jbrowse/core/util';
|
|
3
|
+
import { Tooltip } from '@mui/material';
|
|
4
|
+
import { observer } from 'mobx-react';
|
|
5
|
+
import { makeStyles } from 'tss-react/mui';
|
|
6
|
+
const useStyles = makeStyles()({
|
|
7
|
+
rubberbandControl: {
|
|
8
|
+
cursor: 'crosshair',
|
|
9
|
+
width: '100%',
|
|
10
|
+
minHeight: 8,
|
|
11
|
+
},
|
|
12
|
+
guide: {
|
|
13
|
+
pointerEvents: 'none',
|
|
14
|
+
height: '100%',
|
|
15
|
+
width: 1,
|
|
16
|
+
position: 'absolute',
|
|
17
|
+
},
|
|
18
|
+
rel: {
|
|
19
|
+
position: 'relative',
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
const OverviewRubberbandHoverTooltip = observer(function ({ model, open, guideX, overview, }) {
|
|
23
|
+
var _a;
|
|
24
|
+
const { classes } = useStyles();
|
|
25
|
+
const { cytobandOffset } = model;
|
|
26
|
+
const { assemblyManager } = getSession(model);
|
|
27
|
+
const px = overview.pxToBp(guideX - cytobandOffset);
|
|
28
|
+
const assembly = assemblyManager.get(px.assemblyName);
|
|
29
|
+
const cytoband = (_a = assembly === null || assembly === void 0 ? void 0 : assembly.cytobands) === null || _a === void 0 ? void 0 : _a.find(f => px.coord > f.get('start') &&
|
|
30
|
+
px.coord < f.get('end') &&
|
|
31
|
+
px.refName === assembly.getCanonicalRefName(f.get('refName')));
|
|
32
|
+
return (_jsx(Tooltip, { open: open, placement: "top", title: [stringify(px), cytoband === null || cytoband === void 0 ? void 0 : cytoband.get('name')].join(' '), arrow: true, children: _jsx("div", { className: classes.guide, style: { left: guideX } }) }));
|
|
33
|
+
});
|
|
34
|
+
export default OverviewRubberbandHoverTooltip;
|
|
@@ -11,15 +11,20 @@ const useStyles = makeStyles()({
|
|
|
11
11
|
cursor: 'crosshair',
|
|
12
12
|
width: '100%',
|
|
13
13
|
minHeight: 8,
|
|
14
|
+
zIndex: 825,
|
|
14
15
|
},
|
|
15
16
|
});
|
|
16
17
|
const Rubberband = observer(function ({ model, ControlComponent = _jsx("div", {}), }) {
|
|
17
18
|
const ref = useRef(null);
|
|
18
19
|
const { classes } = useStyles();
|
|
20
|
+
const { stickyViewHeaders, rubberbandTop } = model;
|
|
19
21
|
const { guideX, rubberbandOn, leftBpOffset, rightBpOffset, numOfBpSelected, width, left, anchorPosition, open, handleMenuItemClick, handleClose, mouseMove, mouseDown, mouseOut, } = useRangeSelect(ref, model);
|
|
20
|
-
return (_jsxs(_Fragment, { children: [guideX !== undefined ? (_jsx(VerticalGuide, { model: model, coordX: guideX })) : rubberbandOn ? (_jsx(RubberbandSpan, { leftBpOffset: leftBpOffset, rightBpOffset: rightBpOffset, numOfBpSelected: numOfBpSelected, width: width, left: left })) : null, anchorPosition ? (_jsx(Menu, { anchorReference: "anchorPosition", anchorPosition: {
|
|
22
|
+
return (_jsxs(_Fragment, { children: [guideX !== undefined ? (_jsx(VerticalGuide, { model: model, coordX: guideX })) : rubberbandOn ? (_jsx(RubberbandSpan, { leftBpOffset: leftBpOffset, rightBpOffset: rightBpOffset, numOfBpSelected: numOfBpSelected, width: width, left: left, top: rubberbandTop, sticky: stickyViewHeaders })) : null, anchorPosition ? (_jsx(Menu, { anchorReference: "anchorPosition", anchorPosition: {
|
|
21
23
|
left: anchorPosition.clientX,
|
|
22
24
|
top: anchorPosition.clientY,
|
|
23
|
-
}, onMenuItemClick: handleMenuItemClick, open: open, onClose: handleClose, menuItems: model.rubberBandMenuItems() })) : null, _jsx("div", { "data-testid": "rubberband_controls", className: classes.rubberbandControl,
|
|
25
|
+
}, onMenuItemClick: handleMenuItemClick, open: open, onClose: handleClose, menuItems: model.rubberBandMenuItems() })) : null, _jsx("div", { "data-testid": "rubberband_controls", className: classes.rubberbandControl, style: {
|
|
26
|
+
top: rubberbandTop,
|
|
27
|
+
position: stickyViewHeaders ? 'sticky' : undefined,
|
|
28
|
+
}, ref: ref, onMouseDown: mouseDown, onMouseMove: mouseMove, onMouseOut: mouseOut, children: ControlComponent })] }));
|
|
24
29
|
});
|
|
25
30
|
export default Rubberband;
|
|
@@ -3,11 +3,13 @@ interface Offset {
|
|
|
3
3
|
refName?: string;
|
|
4
4
|
oob?: boolean;
|
|
5
5
|
}
|
|
6
|
-
export default function RubberbandSpan({ leftBpOffset, rightBpOffset, numOfBpSelected, left, width, }: {
|
|
6
|
+
export default function RubberbandSpan({ leftBpOffset, rightBpOffset, numOfBpSelected, left, width, top, sticky, }: {
|
|
7
7
|
leftBpOffset: Offset;
|
|
8
8
|
rightBpOffset: Offset;
|
|
9
9
|
numOfBpSelected?: number;
|
|
10
10
|
left: number;
|
|
11
11
|
width: number;
|
|
12
|
+
top?: number;
|
|
13
|
+
sticky?: boolean;
|
|
12
14
|
}): import("react/jsx-runtime").JSX.Element;
|
|
13
15
|
export {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { stringify, toLocale } from '@jbrowse/core/util';
|
|
4
|
-
import {
|
|
4
|
+
import { Typography, alpha } from '@mui/material';
|
|
5
5
|
import { makeStyles } from 'tss-react/mui';
|
|
6
|
+
import RubberbandTooltip from './RubberbandTooltip';
|
|
6
7
|
const useStyles = makeStyles()(theme => {
|
|
7
8
|
const { tertiary } = theme.palette;
|
|
8
9
|
const background = alpha(tertiary.light, 0.7);
|
|
@@ -11,9 +12,8 @@ const useStyles = makeStyles()(theme => {
|
|
|
11
12
|
height: '100%',
|
|
12
13
|
background,
|
|
13
14
|
position: 'absolute',
|
|
14
|
-
zIndex:
|
|
15
|
+
zIndex: 830,
|
|
15
16
|
textAlign: 'center',
|
|
16
|
-
overflow: 'hidden',
|
|
17
17
|
},
|
|
18
18
|
rubberbandControl: {
|
|
19
19
|
cursor: 'crosshair',
|
|
@@ -21,32 +21,17 @@ const useStyles = makeStyles()(theme => {
|
|
|
21
21
|
minHeight: 8,
|
|
22
22
|
},
|
|
23
23
|
rubberbandText: {
|
|
24
|
-
color: tertiary.contrastText,
|
|
25
|
-
},
|
|
26
|
-
popover: {
|
|
27
|
-
mouseEvents: 'none',
|
|
28
|
-
cursor: 'crosshair',
|
|
29
|
-
},
|
|
30
|
-
paper: {
|
|
31
|
-
paddingLeft: theme.spacing(1),
|
|
32
|
-
paddingRight: theme.spacing(1),
|
|
24
|
+
color: theme.palette.tertiary.contrastText,
|
|
33
25
|
},
|
|
34
26
|
};
|
|
35
27
|
});
|
|
36
|
-
function
|
|
37
|
-
const { classes } = useStyles();
|
|
38
|
-
return (_jsx(Popover, { className: classes.popover, classes: { paper: classes.paper }, open: true, anchorEl: anchorEl, anchorOrigin: {
|
|
39
|
-
vertical: 'top',
|
|
40
|
-
horizontal: side === 'left' ? 'right' : 'left',
|
|
41
|
-
}, transformOrigin: {
|
|
42
|
-
vertical: 'bottom',
|
|
43
|
-
horizontal: side === 'left' ? 'left' : 'right',
|
|
44
|
-
}, keepMounted: true, disableRestoreFocus: true, children: _jsx(Typography, { children: text }) }));
|
|
45
|
-
}
|
|
46
|
-
export default function RubberbandSpan({ leftBpOffset, rightBpOffset, numOfBpSelected, left, width, }) {
|
|
28
|
+
export default function RubberbandSpan({ leftBpOffset, rightBpOffset, numOfBpSelected, left, width, top = 0, sticky = false, }) {
|
|
47
29
|
const { classes } = useStyles();
|
|
48
30
|
const [anchorEl, setAnchorEl] = useState(null);
|
|
49
|
-
return (_jsxs(_Fragment, { children: [anchorEl ? (_jsxs(_Fragment, { children: [_jsx(
|
|
50
|
-
|
|
51
|
-
|
|
31
|
+
return (_jsxs(_Fragment, { children: [anchorEl ? (_jsxs(_Fragment, { children: [_jsx(RubberbandTooltip, { side: "left", anchorEl: anchorEl, text: stringify(leftBpOffset) }), _jsx(RubberbandTooltip, { side: "right", anchorEl: anchorEl, text: stringify(rightBpOffset) })] })) : null, _jsx("div", { className: classes.rubberband, style: { left, width }, children: numOfBpSelected ? (_jsxs(Typography, { ref: el => {
|
|
32
|
+
setAnchorEl(el);
|
|
33
|
+
}, variant: "h6", className: classes.rubberbandText, style: {
|
|
34
|
+
top,
|
|
35
|
+
position: sticky ? 'sticky' : undefined,
|
|
36
|
+
}, children: [toLocale(numOfBpSelected), " bp"] })) : null })] }));
|
|
52
37
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Popover, Typography } from '@mui/material';
|
|
3
|
+
import { makeStyles } from 'tss-react/mui';
|
|
4
|
+
const useStyles = makeStyles()(theme => {
|
|
5
|
+
return {
|
|
6
|
+
popover: {
|
|
7
|
+
mouseEvents: 'none',
|
|
8
|
+
cursor: 'crosshair',
|
|
9
|
+
},
|
|
10
|
+
paper: {
|
|
11
|
+
paddingLeft: theme.spacing(1),
|
|
12
|
+
paddingRight: theme.spacing(1),
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
export default function RubberbandTooltip({ anchorEl, side, text, }) {
|
|
17
|
+
const { classes } = useStyles();
|
|
18
|
+
return (_jsx(Popover, { className: classes.popover, classes: { paper: classes.paper }, open: true, anchorEl: anchorEl, anchorOrigin: {
|
|
19
|
+
vertical: 'top',
|
|
20
|
+
horizontal: side === 'left' ? 'left' : 'right',
|
|
21
|
+
}, transformOrigin: {
|
|
22
|
+
vertical: 'bottom',
|
|
23
|
+
horizontal: side === 'left' ? 'right' : 'left',
|
|
24
|
+
}, keepMounted: true, disableRestoreFocus: true, children: _jsx(Typography, { children: text }) }));
|
|
25
|
+
}
|