@jbrowse/plugin-linear-genome-view 3.0.4 → 3.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.
- 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/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 +0 -1
- package/dist/LinearGenomeView/components/Rubberband.js +25 -2
- package/dist/LinearGenomeView/components/RubberbandSpan.d.ts +3 -1
- package/dist/LinearGenomeView/components/RubberbandSpan.js +8 -6
- 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 +30 -5
- package/dist/LinearGenomeView/model.d.ts +4 -0
- package/dist/LinearGenomeView/model.js +27 -0
- package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +2 -2
- 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/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 +0 -1
- package/esm/LinearGenomeView/components/Rubberband.js +26 -3
- package/esm/LinearGenomeView/components/RubberbandSpan.d.ts +3 -1
- package/esm/LinearGenomeView/components/RubberbandSpan.js +8 -6
- 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 +32 -7
- package/esm/LinearGenomeView/model.d.ts +4 -0
- package/esm/LinearGenomeView/model.js +27 -0
- package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +2 -2
- package/package.json +3 -3
- package/dist/BaseLinearDisplay/components/BlockError.d.ts +0 -4
- package/esm/BaseLinearDisplay/components/BlockError.d.ts +0 -4
|
@@ -56,22 +56,21 @@ const RubberbandSpan = (0, react_1.lazy)(() => Promise.resolve().then(() => __im
|
|
|
56
56
|
const useStyles = (0, mui_1.makeStyles)()({
|
|
57
57
|
tracksContainer: {
|
|
58
58
|
position: 'relative',
|
|
59
|
-
overflow: 'hidden',
|
|
60
59
|
},
|
|
61
60
|
});
|
|
62
61
|
const TracksContainer = (0, mobx_react_1.observer)(function TracksContainer({ children, model, }) {
|
|
63
62
|
const { classes } = useStyles();
|
|
64
63
|
const { pluginManager } = (0, util_1.getEnv)(model);
|
|
65
64
|
const { mouseDown: mouseDown1, mouseUp } = (0, useSideScroll_1.useSideScroll)(model);
|
|
66
|
-
const { showGridlines, showCenterLine } = model;
|
|
65
|
+
const { stickyViewHeaders, pinnedTracksTop, showGridlines, showCenterLine } = model;
|
|
67
66
|
const ref = (0, react_1.useRef)(null);
|
|
68
67
|
const { guideX, rubberbandOn, leftBpOffset, rightBpOffset, numOfBpSelected, width, left, anchorPosition, open, handleMenuItemClick, handleClose, mouseMove, mouseDown: mouseDown2, } = (0, useRangeSelect_1.useRangeSelect)(ref, model, true);
|
|
69
68
|
(0, useWheelScroll_1.useWheelScroll)(ref, model);
|
|
70
69
|
const additional = pluginManager.evaluateExtensionPoint('LinearGenomeView-TracksContainerComponent', undefined, { model });
|
|
71
|
-
return ((0, jsx_runtime_1.jsxs)("div", { ref: ref, "data-testid": "
|
|
70
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: ref, "data-testid": "tracksContainer", className: classes.tracksContainer, onMouseDown: event => {
|
|
72
71
|
mouseDown1(event);
|
|
73
72
|
mouseDown2(event);
|
|
74
|
-
}, onMouseMove: mouseMove, onMouseUp: mouseUp, children: [showGridlines ? (0, jsx_runtime_1.jsx)(Gridlines_1.default, { model: model }) : null, (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: null, children: showCenterLine ? (0, jsx_runtime_1.jsx)(CenterLine, { model: model }) : null }), guideX !== undefined ? ((0, jsx_runtime_1.jsx)(VerticalGuide_1.default, { model: model, coordX: guideX })) : rubberbandOn ? ((0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: null, children: (0, jsx_runtime_1.jsx)(RubberbandSpan, { leftBpOffset: leftBpOffset, rightBpOffset: rightBpOffset, numOfBpSelected: numOfBpSelected, width: width, left: left }) })) : null, anchorPosition ? ((0, jsx_runtime_1.jsx)(ui_1.Menu, { anchorReference: "anchorPosition", anchorPosition: {
|
|
73
|
+
}, onMouseMove: mouseMove, onMouseUp: mouseUp, children: [showGridlines ? (0, jsx_runtime_1.jsx)(Gridlines_1.default, { model: model }) : null, (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: null, children: showCenterLine ? (0, jsx_runtime_1.jsx)(CenterLine, { model: model }) : null }), guideX !== undefined ? ((0, jsx_runtime_1.jsx)(VerticalGuide_1.default, { model: model, coordX: guideX })) : rubberbandOn ? ((0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: null, children: (0, jsx_runtime_1.jsx)(RubberbandSpan, { leftBpOffset: leftBpOffset, rightBpOffset: rightBpOffset, numOfBpSelected: numOfBpSelected, width: width, left: left, top: pinnedTracksTop, sticky: stickyViewHeaders }) })) : null, anchorPosition ? ((0, jsx_runtime_1.jsx)(ui_1.Menu, { anchorReference: "anchorPosition", anchorPosition: {
|
|
75
74
|
left: anchorPosition.clientX,
|
|
76
75
|
top: anchorPosition.clientY,
|
|
77
76
|
}, onMenuItemClick: handleMenuItemClick, open: open, onClose: handleClose, menuItems: model.rubberBandMenuItems() })) : null, (0, jsx_runtime_1.jsx)(Rubberband_1.default, { model: model, ControlComponent: (0, jsx_runtime_1.jsx)(Scalebar_1.default, { model: model, style: {
|
|
@@ -1,24 +1,49 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
+
const ui_1 = require("@jbrowse/core/ui");
|
|
4
5
|
const util_1 = require("@jbrowse/core/util");
|
|
6
|
+
const product_core_1 = require("@jbrowse/product-core");
|
|
5
7
|
const material_1 = require("@mui/material");
|
|
6
8
|
const mobx_react_1 = require("mobx-react");
|
|
7
9
|
const mui_1 = require("tss-react/mui");
|
|
10
|
+
const consts_1 = require("../consts");
|
|
8
11
|
const useStyles = (0, mui_1.makeStyles)()({
|
|
9
12
|
guide: {
|
|
10
13
|
pointerEvents: 'none',
|
|
11
14
|
height: '100%',
|
|
12
15
|
width: 1,
|
|
13
16
|
position: 'absolute',
|
|
14
|
-
|
|
17
|
+
background: 'red',
|
|
18
|
+
zIndex: 4,
|
|
19
|
+
},
|
|
20
|
+
tooltipTarget: {
|
|
21
|
+
position: 'sticky',
|
|
22
|
+
width: 1,
|
|
15
23
|
},
|
|
16
24
|
});
|
|
17
25
|
const VerticalGuide = (0, mobx_react_1.observer)(function VerticalGuide({ model, coordX, }) {
|
|
18
26
|
const { classes } = useStyles();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
const session = (0, util_1.getSession)(model);
|
|
28
|
+
let stickyViewHeaders = false;
|
|
29
|
+
if ((0, product_core_1.isSessionWithMultipleViews)(session)) {
|
|
30
|
+
;
|
|
31
|
+
({ stickyViewHeaders } = session);
|
|
32
|
+
}
|
|
33
|
+
let tooltipTop = 0;
|
|
34
|
+
if (stickyViewHeaders) {
|
|
35
|
+
tooltipTop = ui_1.VIEW_HEADER_HEIGHT;
|
|
36
|
+
if (!model.hideHeader) {
|
|
37
|
+
tooltipTop += consts_1.HEADER_BAR_HEIGHT;
|
|
38
|
+
if (!model.hideHeaderOverview) {
|
|
39
|
+
tooltipTop += consts_1.HEADER_OVERVIEW_HEIGHT;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Tooltip, { open: true, placement: "top", title: (0, util_1.stringify)(model.pxToBp(coordX)), arrow: true, children: (0, jsx_runtime_1.jsx)("div", { className: classes.tooltipTarget, style: {
|
|
44
|
+
left: coordX + 6,
|
|
45
|
+
top: tooltipTop,
|
|
46
|
+
position: stickyViewHeaders ? 'sticky' : undefined,
|
|
47
|
+
} }) }), (0, jsx_runtime_1.jsx)("div", { className: classes.guide, style: { left: coordX } })] }));
|
|
23
48
|
});
|
|
24
49
|
exports.default = VerticalGuide;
|
|
@@ -51,10 +51,14 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
|
|
|
51
51
|
leftOffset: undefined | BpOffset;
|
|
52
52
|
rightOffset: undefined | BpOffset;
|
|
53
53
|
} & {
|
|
54
|
+
readonly pinnedTracks: any[];
|
|
55
|
+
readonly unpinnedTracks: any[];
|
|
54
56
|
readonly trackLabelsSetting: any;
|
|
55
57
|
readonly width: number;
|
|
56
58
|
readonly interRegionPaddingWidth: number;
|
|
57
59
|
readonly assemblyNames: string[];
|
|
60
|
+
readonly stickyViewHeaders: boolean;
|
|
61
|
+
readonly pinnedTracksTop: number;
|
|
58
62
|
} & {
|
|
59
63
|
scaleBarDisplayPrefix(): string | undefined;
|
|
60
64
|
MiniControlsComponent(): React.FC<any>;
|
|
@@ -41,6 +41,7 @@ exports.stateModelFactory = stateModelFactory;
|
|
|
41
41
|
const react_1 = require("react");
|
|
42
42
|
const configuration_1 = require("@jbrowse/core/configuration");
|
|
43
43
|
const models_1 = require("@jbrowse/core/pluggableElementTypes/models");
|
|
44
|
+
const ui_1 = require("@jbrowse/core/ui");
|
|
44
45
|
const Icons_1 = require("@jbrowse/core/ui/Icons");
|
|
45
46
|
const util_1 = require("@jbrowse/core/util");
|
|
46
47
|
const Base1DUtils_1 = require("@jbrowse/core/util/Base1DUtils");
|
|
@@ -49,6 +50,7 @@ const calculateDynamicBlocks_1 = __importDefault(require("@jbrowse/core/util/cal
|
|
|
49
50
|
const calculateStaticBlocks_1 = __importDefault(require("@jbrowse/core/util/calculateStaticBlocks"));
|
|
50
51
|
const tracks_1 = require("@jbrowse/core/util/tracks");
|
|
51
52
|
const mst_1 = require("@jbrowse/core/util/types/mst");
|
|
53
|
+
const product_core_1 = require("@jbrowse/product-core");
|
|
52
54
|
const FolderOpen_1 = __importDefault(require("@mui/icons-material/FolderOpen"));
|
|
53
55
|
const Label_1 = __importDefault(require("@mui/icons-material/Label"));
|
|
54
56
|
const MenuOpen_1 = __importDefault(require("@mui/icons-material/MenuOpen"));
|
|
@@ -106,6 +108,12 @@ function stateModelFactory(pluginManager) {
|
|
|
106
108
|
rightOffset: undefined,
|
|
107
109
|
}))
|
|
108
110
|
.views(self => ({
|
|
111
|
+
get pinnedTracks() {
|
|
112
|
+
return self.tracks.filter(t => t.pinned);
|
|
113
|
+
},
|
|
114
|
+
get unpinnedTracks() {
|
|
115
|
+
return self.tracks.filter(t => !t.pinned);
|
|
116
|
+
},
|
|
109
117
|
get trackLabelsSetting() {
|
|
110
118
|
const sessionSetting = (0, configuration_1.getConf)((0, util_1.getSession)(self), [
|
|
111
119
|
'LinearGenomeViewPlugin',
|
|
@@ -127,6 +135,25 @@ function stateModelFactory(pluginManager) {
|
|
|
127
135
|
...new Set(self.displayedRegions.map(region => region.assemblyName)),
|
|
128
136
|
];
|
|
129
137
|
},
|
|
138
|
+
get stickyViewHeaders() {
|
|
139
|
+
const session = (0, util_1.getSession)(self);
|
|
140
|
+
return (0, product_core_1.isSessionWithMultipleViews)(session)
|
|
141
|
+
? session.stickyViewHeaders
|
|
142
|
+
: false;
|
|
143
|
+
},
|
|
144
|
+
get pinnedTracksTop() {
|
|
145
|
+
let pinnedTracksTop = 0;
|
|
146
|
+
if (this.stickyViewHeaders) {
|
|
147
|
+
pinnedTracksTop = ui_1.VIEW_HEADER_HEIGHT + consts_1.SCALE_BAR_HEIGHT;
|
|
148
|
+
if (!self.hideHeader) {
|
|
149
|
+
pinnedTracksTop += consts_1.HEADER_BAR_HEIGHT;
|
|
150
|
+
if (!self.hideHeaderOverview) {
|
|
151
|
+
pinnedTracksTop += consts_1.HEADER_OVERVIEW_HEIGHT;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return pinnedTracksTop;
|
|
156
|
+
},
|
|
130
157
|
}))
|
|
131
158
|
.views(self => ({
|
|
132
159
|
scaleBarDisplayPrefix() {
|
|
@@ -21,12 +21,12 @@ async function renderToSvg(model, opts) {
|
|
|
21
21
|
const session = (0, util_1.getSession)(model);
|
|
22
22
|
const { allThemes } = session;
|
|
23
23
|
const theme = allThemes === null || allThemes === void 0 ? void 0 : allThemes()[themeName];
|
|
24
|
-
const { width, tracks, showCytobands } = model;
|
|
24
|
+
const { width, pinnedTracks, unpinnedTracks, tracks, showCytobands } = model;
|
|
25
25
|
const shift = 50;
|
|
26
26
|
const c = +showCytobands * cytobandHeight;
|
|
27
27
|
const offset = headerHeight + rulerHeight + c + 10;
|
|
28
28
|
const height = (0, util_2.totalHeight)(tracks, textHeight, trackLabels) + offset + 100;
|
|
29
|
-
const displayResults = await Promise.all(
|
|
29
|
+
const displayResults = await Promise.all([...pinnedTracks, ...unpinnedTracks].map(async (track) => {
|
|
30
30
|
const display = track.displays[0];
|
|
31
31
|
await (0, mobx_1.when)(() => !display.renderProps().notReady);
|
|
32
32
|
return { track, result: await display.renderSvg({ ...opts, theme }) };
|
|
@@ -6,14 +6,17 @@ import ReportIcon from '@mui/icons-material/Report';
|
|
|
6
6
|
import { IconButton, Tooltip } from '@mui/material';
|
|
7
7
|
import { observer } from 'mobx-react';
|
|
8
8
|
import BlockMsg from './BlockMsg';
|
|
9
|
-
const
|
|
9
|
+
const BlockErrorMessage = observer(function ({ model, }) {
|
|
10
10
|
return (_jsx(BlockMsg, { message: `${model.error}`, severity: "error", action: _jsxs(_Fragment, { children: [_jsx(Tooltip, { title: "Reload track", children: _jsx(IconButton, { "data-testid": "reload_button", onClick: () => {
|
|
11
11
|
model.reload();
|
|
12
12
|
}, children: _jsx(RefreshIcon, {}) }) }), _jsx(Tooltip, { title: "Show stack trace", children: _jsx(IconButton, { onClick: () => {
|
|
13
13
|
getSession(model).queueDialog(onClose => [
|
|
14
14
|
ErrorMessageStackTraceDialog,
|
|
15
|
-
{
|
|
15
|
+
{
|
|
16
|
+
onClose,
|
|
17
|
+
error: model.error,
|
|
18
|
+
},
|
|
16
19
|
]);
|
|
17
20
|
}, children: _jsx(ReportIcon, {}) }) })] }) }));
|
|
18
21
|
});
|
|
19
|
-
export default
|
|
22
|
+
export default BlockErrorMessage;
|
|
@@ -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;
|
|
@@ -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,25 +1,48 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useRef } from 'react';
|
|
3
|
-
import { Menu } from '@jbrowse/core/ui';
|
|
3
|
+
import { Menu, VIEW_HEADER_HEIGHT } from '@jbrowse/core/ui';
|
|
4
|
+
import { getSession } from '@jbrowse/core/util';
|
|
5
|
+
import { isSessionWithMultipleViews } from '@jbrowse/product-core';
|
|
4
6
|
import { observer } from 'mobx-react';
|
|
5
7
|
import { makeStyles } from 'tss-react/mui';
|
|
6
8
|
import RubberbandSpan from './RubberbandSpan';
|
|
7
9
|
import VerticalGuide from './VerticalGuide';
|
|
8
10
|
import { useRangeSelect } from './useRangeSelect';
|
|
11
|
+
import { HEADER_BAR_HEIGHT, HEADER_OVERVIEW_HEIGHT } from '../consts';
|
|
9
12
|
const useStyles = makeStyles()({
|
|
10
13
|
rubberbandControl: {
|
|
11
14
|
cursor: 'crosshair',
|
|
12
15
|
width: '100%',
|
|
13
16
|
minHeight: 8,
|
|
17
|
+
zIndex: 825,
|
|
14
18
|
},
|
|
15
19
|
});
|
|
16
20
|
const Rubberband = observer(function ({ model, ControlComponent = _jsx("div", {}), }) {
|
|
17
21
|
const ref = useRef(null);
|
|
18
22
|
const { classes } = useStyles();
|
|
23
|
+
const session = getSession(model);
|
|
19
24
|
const { guideX, rubberbandOn, leftBpOffset, rightBpOffset, numOfBpSelected, width, left, anchorPosition, open, handleMenuItemClick, handleClose, mouseMove, mouseDown, mouseOut, } = useRangeSelect(ref, model);
|
|
20
|
-
|
|
25
|
+
let stickyViewHeaders = false;
|
|
26
|
+
if (isSessionWithMultipleViews(session)) {
|
|
27
|
+
;
|
|
28
|
+
({ stickyViewHeaders } = session);
|
|
29
|
+
}
|
|
30
|
+
let rubberbandControlTop = 0;
|
|
31
|
+
if (stickyViewHeaders) {
|
|
32
|
+
rubberbandControlTop = VIEW_HEADER_HEIGHT;
|
|
33
|
+
if (!model.hideHeader) {
|
|
34
|
+
rubberbandControlTop += HEADER_BAR_HEIGHT;
|
|
35
|
+
if (!model.hideHeaderOverview) {
|
|
36
|
+
rubberbandControlTop += HEADER_OVERVIEW_HEIGHT;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
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: rubberbandControlTop, sticky: stickyViewHeaders })) : null, anchorPosition ? (_jsx(Menu, { anchorReference: "anchorPosition", anchorPosition: {
|
|
21
41
|
left: anchorPosition.clientX,
|
|
22
42
|
top: anchorPosition.clientY,
|
|
23
|
-
}, onMenuItemClick: handleMenuItemClick, open: open, onClose: handleClose, menuItems: model.rubberBandMenuItems() })) : null, _jsx("div", { "data-testid": "rubberband_controls", className: classes.rubberbandControl,
|
|
43
|
+
}, onMenuItemClick: handleMenuItemClick, open: open, onClose: handleClose, menuItems: model.rubberBandMenuItems() })) : null, _jsx("div", { "data-testid": "rubberband_controls", className: classes.rubberbandControl, style: {
|
|
44
|
+
top: rubberbandControlTop,
|
|
45
|
+
position: stickyViewHeaders ? 'sticky' : undefined,
|
|
46
|
+
}, ref: ref, onMouseDown: mouseDown, onMouseMove: mouseMove, onMouseOut: mouseOut, children: ControlComponent })] }));
|
|
24
47
|
});
|
|
25
48
|
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 {};
|
|
@@ -11,9 +11,8 @@ const useStyles = makeStyles()(theme => {
|
|
|
11
11
|
height: '100%',
|
|
12
12
|
background,
|
|
13
13
|
position: 'absolute',
|
|
14
|
-
zIndex:
|
|
14
|
+
zIndex: 830,
|
|
15
15
|
textAlign: 'center',
|
|
16
|
-
overflow: 'hidden',
|
|
17
16
|
},
|
|
18
17
|
rubberbandControl: {
|
|
19
18
|
cursor: 'crosshair',
|
|
@@ -43,10 +42,13 @@ function Tooltip({ anchorEl, side, text, }) {
|
|
|
43
42
|
horizontal: side === 'left' ? 'left' : 'right',
|
|
44
43
|
}, keepMounted: true, disableRestoreFocus: true, children: _jsx(Typography, { children: text }) }));
|
|
45
44
|
}
|
|
46
|
-
export default function RubberbandSpan({ leftBpOffset, rightBpOffset, numOfBpSelected, left, width, }) {
|
|
45
|
+
export default function RubberbandSpan({ leftBpOffset, rightBpOffset, numOfBpSelected, left, width, top = 0, sticky = false, }) {
|
|
47
46
|
const { classes } = useStyles();
|
|
48
47
|
const [anchorEl, setAnchorEl] = useState(null);
|
|
49
|
-
return (_jsxs(_Fragment, { children: [anchorEl ? (_jsxs(_Fragment, { children: [_jsx(Tooltip, { side: "left", anchorEl: anchorEl, text: stringify(leftBpOffset) }), _jsx(Tooltip, { side: "right", anchorEl: anchorEl, text: stringify(rightBpOffset) })] })) : null, _jsx("div", { ref: el => {
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
return (_jsxs(_Fragment, { children: [anchorEl ? (_jsxs(_Fragment, { children: [_jsx(Tooltip, { side: "left", anchorEl: anchorEl, text: stringify(leftBpOffset) }), _jsx(Tooltip, { side: "right", anchorEl: anchorEl, text: stringify(rightBpOffset) })] })) : null, _jsx("div", { className: classes.rubberband, style: { left, width }, children: numOfBpSelected ? (_jsxs(Typography, { ref: el => {
|
|
49
|
+
setAnchorEl(el);
|
|
50
|
+
}, variant: "h6", className: classes.rubberbandText, style: {
|
|
51
|
+
top,
|
|
52
|
+
position: sticky ? 'sticky' : undefined,
|
|
53
|
+
}, children: [toLocale(numOfBpSelected), " bp"] })) : null })] }));
|
|
52
54
|
}
|