@jbrowse/plugin-linear-genome-view 2.13.0 → 2.14.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/LinearBlocks.js +2 -2
- package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +3 -1
- package/dist/BaseLinearDisplay/components/Tooltip.js +1 -1
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +1 -1
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +8 -5
- package/dist/BaseLinearDisplay/models/FeatureDensityMixin.js +2 -3
- package/dist/BaseLinearDisplay/models/renderSvg.d.ts +1 -1
- package/dist/BaseLinearDisplay/models/renderSvg.js +3 -1
- package/dist/BaseLinearDisplay/models/util.d.ts +1 -1
- package/dist/BaseLinearDisplay/models/util.js +3 -5
- package/dist/LaunchLinearGenomeView/index.js +12 -11
- package/dist/LinearBareDisplay/model.d.ts +1 -1
- package/dist/LinearBasicDisplay/components/AddFiltersDialog.js +9 -3
- package/dist/LinearBasicDisplay/components/SetMaxHeightDialog.js +6 -2
- package/dist/LinearBasicDisplay/model.d.ts +2 -4
- package/dist/LinearBasicDisplay/model.js +9 -3
- package/dist/LinearGenomeView/components/Cytobands.js +6 -23
- package/dist/LinearGenomeView/components/ExportSvgDialog.js +16 -6
- package/dist/LinearGenomeView/components/GetSequenceDialog.js +13 -16
- package/dist/LinearGenomeView/components/Header.js +6 -2
- package/dist/LinearGenomeView/components/Highlight.js +24 -25
- package/dist/LinearGenomeView/components/ImportForm.js +5 -2
- package/dist/LinearGenomeView/components/ImportFormRefNameAutocomplete.js +5 -1
- package/dist/LinearGenomeView/components/LinearGenomeView.d.ts +2 -3
- package/dist/LinearGenomeView/components/LinearGenomeView.js +5 -3
- package/dist/LinearGenomeView/components/MiniControls.js +6 -2
- package/dist/LinearGenomeView/components/OverviewHighlight.js +23 -30
- package/dist/LinearGenomeView/components/OverviewRubberband.js +1 -1
- package/dist/LinearGenomeView/components/OverviewScalebar.js +6 -11
- package/dist/LinearGenomeView/components/OverviewScalebarPolygon.js +1 -2
- package/dist/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.js +6 -5
- package/dist/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.js +6 -2
- package/dist/LinearGenomeView/components/RefNameAutocomplete/HelpDialog.js +3 -1
- package/dist/LinearGenomeView/components/RefNameAutocomplete/index.js +9 -7
- package/dist/LinearGenomeView/components/RubberbandSpan.js +3 -5
- package/dist/LinearGenomeView/components/Scalebar.js +2 -1
- package/dist/LinearGenomeView/components/SearchResultsDialog.js +3 -1
- package/dist/LinearGenomeView/components/SearchResultsTable.js +2 -3
- package/dist/LinearGenomeView/components/SequenceSearchDialog.js +15 -5
- package/dist/LinearGenomeView/components/TrackContainer.js +2 -2
- package/dist/LinearGenomeView/components/TrackLabel.js +15 -5
- package/dist/LinearGenomeView/components/TrackLabelDragHandle.js +3 -1
- package/dist/LinearGenomeView/components/TracksContainer.js +1 -1
- package/dist/LinearGenomeView/components/ZoomControls.js +10 -4
- package/dist/LinearGenomeView/components/hooks.d.ts +2 -2
- package/dist/LinearGenomeView/components/hooks.js +24 -26
- package/dist/LinearGenomeView/components/util.d.ts +2 -2
- package/dist/LinearGenomeView/model.d.ts +24 -13
- package/dist/LinearGenomeView/model.js +75 -46
- package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +0 -1
- package/dist/LinearGenomeView/svgcomponents/SVGRuler.js +1 -1
- package/dist/LinearGenomeView/util.d.ts +1 -1
- package/dist/LinearGenomeView/util.js +4 -9
- package/dist/index.d.ts +3 -414
- package/dist/searchUtils.js +4 -6
- package/esm/BaseLinearDisplay/components/LinearBlocks.js +2 -2
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +3 -1
- package/esm/BaseLinearDisplay/components/Tooltip.js +1 -1
- package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +1 -1
- package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +8 -5
- package/esm/BaseLinearDisplay/models/FeatureDensityMixin.js +2 -3
- package/esm/BaseLinearDisplay/models/renderSvg.d.ts +1 -1
- package/esm/BaseLinearDisplay/models/renderSvg.js +3 -1
- package/esm/BaseLinearDisplay/models/util.d.ts +1 -1
- package/esm/BaseLinearDisplay/models/util.js +3 -5
- package/esm/LaunchLinearGenomeView/index.js +13 -12
- package/esm/LinearBareDisplay/model.d.ts +1 -1
- package/esm/LinearBasicDisplay/components/AddFiltersDialog.js +9 -3
- package/esm/LinearBasicDisplay/components/SetMaxHeightDialog.js +6 -2
- package/esm/LinearBasicDisplay/model.d.ts +2 -4
- package/esm/LinearBasicDisplay/model.js +9 -3
- package/esm/LinearGenomeView/components/Cytobands.js +6 -23
- package/esm/LinearGenomeView/components/ExportSvgDialog.js +16 -6
- package/esm/LinearGenomeView/components/GetSequenceDialog.js +13 -16
- package/esm/LinearGenomeView/components/Header.js +6 -2
- package/esm/LinearGenomeView/components/Highlight.js +26 -27
- package/esm/LinearGenomeView/components/ImportForm.js +5 -2
- package/esm/LinearGenomeView/components/ImportFormRefNameAutocomplete.js +5 -1
- package/esm/LinearGenomeView/components/LinearGenomeView.d.ts +2 -3
- package/esm/LinearGenomeView/components/LinearGenomeView.js +5 -3
- package/esm/LinearGenomeView/components/MiniControls.js +6 -2
- package/esm/LinearGenomeView/components/OverviewHighlight.js +24 -31
- package/esm/LinearGenomeView/components/OverviewRubberband.js +1 -1
- package/esm/LinearGenomeView/components/OverviewScalebar.js +6 -11
- package/esm/LinearGenomeView/components/OverviewScalebarPolygon.js +1 -2
- package/esm/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.js +6 -5
- package/esm/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.js +6 -2
- package/esm/LinearGenomeView/components/RefNameAutocomplete/HelpDialog.js +3 -1
- package/esm/LinearGenomeView/components/RefNameAutocomplete/index.js +10 -8
- package/esm/LinearGenomeView/components/RubberbandSpan.js +3 -5
- package/esm/LinearGenomeView/components/Scalebar.js +2 -1
- package/esm/LinearGenomeView/components/SearchResultsDialog.js +3 -1
- package/esm/LinearGenomeView/components/SearchResultsTable.js +2 -3
- package/esm/LinearGenomeView/components/SequenceSearchDialog.js +15 -5
- package/esm/LinearGenomeView/components/TrackContainer.js +2 -2
- package/esm/LinearGenomeView/components/TrackLabel.js +15 -5
- package/esm/LinearGenomeView/components/TrackLabelDragHandle.js +3 -1
- package/esm/LinearGenomeView/components/TracksContainer.js +1 -1
- package/esm/LinearGenomeView/components/ZoomControls.js +10 -4
- package/esm/LinearGenomeView/components/hooks.d.ts +2 -2
- package/esm/LinearGenomeView/components/hooks.js +24 -26
- package/esm/LinearGenomeView/components/util.d.ts +2 -2
- package/esm/LinearGenomeView/model.d.ts +24 -13
- package/esm/LinearGenomeView/model.js +77 -48
- package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +0 -1
- package/esm/LinearGenomeView/svgcomponents/SVGRuler.js +1 -1
- package/esm/LinearGenomeView/util.d.ts +1 -1
- package/esm/LinearGenomeView/util.js +4 -9
- package/esm/index.d.ts +3 -414
- package/esm/searchUtils.js +4 -6
- package/package.json +3 -3
|
@@ -63,12 +63,13 @@ const LinearGenomeViewImportForm = (0, mobx_react_1.observer)(function ({ model,
|
|
|
63
63
|
const [value, setValue] = (0, react_1.useState)('');
|
|
64
64
|
const regions = assembly === null || assembly === void 0 ? void 0 : assembly.regions;
|
|
65
65
|
const assemblyLoaded = !!regions;
|
|
66
|
-
const r0 = regions ? (_a = regions[0]) === null || _a === void 0 ? void 0 : _a.refName : '';
|
|
66
|
+
const r0 = regions ? ((_a = regions[0]) === null || _a === void 0 ? void 0 : _a.refName) || '' : '';
|
|
67
67
|
// useEffect resets to an "initial state" of displaying first region from
|
|
68
68
|
// assembly after assembly change. needs to react to selectedAsm as well as
|
|
69
69
|
// r0 because changing assembly will run setValue('') and then r0 may not
|
|
70
70
|
// change if assembly names are the same across assemblies, but it still
|
|
71
71
|
// needs to be reset
|
|
72
|
+
/* biome-ignore lint/correctness/useExhaustiveDependencies: */
|
|
72
73
|
(0, react_1.useEffect)(() => {
|
|
73
74
|
setValue(r0);
|
|
74
75
|
}, [r0, selectedAsm]);
|
|
@@ -108,7 +109,9 @@ const LinearGenomeViewImportForm = (0, mobx_react_1.observer)(function ({ model,
|
|
|
108
109
|
react_1.default.createElement(material_1.Grid, { container: true, spacing: 1, justifyContent: "center", alignItems: "center" },
|
|
109
110
|
react_1.default.createElement(material_1.Grid, { item: true },
|
|
110
111
|
react_1.default.createElement(material_1.FormControl, null,
|
|
111
|
-
react_1.default.createElement(ui_1.AssemblySelector, { onChange: val =>
|
|
112
|
+
react_1.default.createElement(ui_1.AssemblySelector, { onChange: val => {
|
|
113
|
+
setSelectedAsm(val);
|
|
114
|
+
}, localStorageKey: "lgv", session: session, selected: selectedAsm }))),
|
|
112
115
|
react_1.default.createElement(material_1.Grid, { item: true }, selectedAsm ? (assemblyError ? (react_1.default.createElement(Close_1.default, { style: { color: 'red' } })) : assemblyLoaded ? (react_1.default.createElement(material_1.FormControl, null,
|
|
113
116
|
react_1.default.createElement(ImportFormRefNameAutocomplete_1.default, { value: value, setValue: setValue, selectedAsm: selectedAsm, setOption: setOption, model: model }))) : (react_1.default.createElement(material_1.CircularProgress, { size: 20, disableShrink: true }))) : null),
|
|
114
117
|
react_1.default.createElement(material_1.Grid, { item: true },
|
|
@@ -21,7 +21,11 @@ const ImportFormRefNameAutocomplete = (0, mobx_react_1.observer)(function ({ mod
|
|
|
21
21
|
textSearchManager,
|
|
22
22
|
rankSearchResults,
|
|
23
23
|
searchScope,
|
|
24
|
-
}), model: model, assemblyName: selectedAsm, value: value, minWidth: 270, onChange: str =>
|
|
24
|
+
}), model: model, assemblyName: selectedAsm, value: value, minWidth: 270, onChange: str => {
|
|
25
|
+
setValue(str);
|
|
26
|
+
}, onSelect: val => {
|
|
27
|
+
setOption(val);
|
|
28
|
+
}, TextFieldProps: {
|
|
25
29
|
variant: 'outlined',
|
|
26
30
|
helperText: 'Enter sequence name, feature name, or location',
|
|
27
31
|
} }));
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { LinearGenomeViewModel } from '..';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
model: LGV;
|
|
3
|
+
declare const LinearGenomeView: ({ model, }: {
|
|
4
|
+
model: LinearGenomeViewModel;
|
|
6
5
|
}) => React.JSX.Element;
|
|
7
6
|
export default LinearGenomeView;
|
|
@@ -48,7 +48,7 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
|
48
48
|
zIndex: 1000,
|
|
49
49
|
},
|
|
50
50
|
}));
|
|
51
|
-
const LinearGenomeView = (0, mobx_react_1.observer)(({ model })
|
|
51
|
+
const LinearGenomeView = (0, mobx_react_1.observer)(function ({ model, }) {
|
|
52
52
|
const { tracks, error, initialized, hasDisplayedRegions } = model;
|
|
53
53
|
const ref = (0, react_1.useRef)(null);
|
|
54
54
|
const session = (0, util_1.getSession)(model);
|
|
@@ -58,7 +58,7 @@ const LinearGenomeView = (0, mobx_react_1.observer)(({ model }) => {
|
|
|
58
58
|
// necessary for subviews to be focused properly
|
|
59
59
|
function handleSelectView(e) {
|
|
60
60
|
var _a, _b;
|
|
61
|
-
if (e.target instanceof Element && ((_a = ref
|
|
61
|
+
if (e.target instanceof Element && ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
|
|
62
62
|
(_b = session.setFocusedViewId) === null || _b === void 0 ? void 0 : _b.call(session, model.id);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -77,7 +77,9 @@ const LinearGenomeView = (0, mobx_react_1.observer)(({ model }) => {
|
|
|
77
77
|
}
|
|
78
78
|
const MiniControlsComponent = model.MiniControlsComponent();
|
|
79
79
|
const HeaderComponent = model.HeaderComponent();
|
|
80
|
-
return (react_1.default.createElement("div", { className: classes.rel, ref: ref, onMouseLeave: () =>
|
|
80
|
+
return (react_1.default.createElement("div", { className: classes.rel, ref: ref, onMouseLeave: () => {
|
|
81
|
+
session.setHovered(undefined);
|
|
82
|
+
}, onMouseMove: event => {
|
|
81
83
|
const c = ref.current;
|
|
82
84
|
if (!c) {
|
|
83
85
|
return;
|
|
@@ -32,9 +32,13 @@ const MiniControls = (0, mobx_react_1.observer)(function ({ model, }) {
|
|
|
32
32
|
react_1.default.createElement(material_1.Paper, { className: focusedViewId === id ? classes.focusedBackground : undefined },
|
|
33
33
|
react_1.default.createElement(CascadingMenuButton_1.default, { menuItems: model.menuItems() },
|
|
34
34
|
react_1.default.createElement(KeyboardArrowDown_1.default, { fontSize: "small" })),
|
|
35
|
-
react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_out", onClick: () =>
|
|
35
|
+
react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_out", onClick: () => {
|
|
36
|
+
model.zoom(bpPerPx * 2);
|
|
37
|
+
}, disabled: bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1 },
|
|
36
38
|
react_1.default.createElement(ZoomOut_1.default, { fontSize: "small" })),
|
|
37
|
-
react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_in", onClick: () =>
|
|
39
|
+
react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_in", onClick: () => {
|
|
40
|
+
model.zoom(bpPerPx / 2);
|
|
41
|
+
}, disabled: bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1 },
|
|
38
42
|
react_1.default.createElement(ZoomIn_1.default, { fontSize: "small" }))))) : null;
|
|
39
43
|
});
|
|
40
44
|
exports.default = MiniControls;
|
|
@@ -8,53 +8,46 @@ const mobx_react_1 = require("mobx-react");
|
|
|
8
8
|
const mui_1 = require("tss-react/mui");
|
|
9
9
|
const colord_1 = require("@jbrowse/core/util/colord");
|
|
10
10
|
const util_1 = require("@jbrowse/core/util");
|
|
11
|
-
const useStyles = (0, mui_1.makeStyles)()(theme => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
borderLeft: `1px solid ${(_d = (_c = theme.palette.highlight) === null || _c === void 0 ? void 0 : _c.main) !== null && _d !== void 0 ? _d : 'goldenrod'}`,
|
|
21
|
-
borderRight: `1px solid ${(_f = (_e = theme.palette.highlight) === null || _e === void 0 ? void 0 : _e.main) !== null && _f !== void 0 ? _f : 'goldenrod'}`,
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
});
|
|
11
|
+
const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
12
|
+
highlight: {
|
|
13
|
+
height: '100%',
|
|
14
|
+
position: 'absolute',
|
|
15
|
+
background: (0, colord_1.colord)(theme.palette.highlight.main).alpha(0.35).toRgbString(),
|
|
16
|
+
borderLeft: `1px solid ${theme.palette.highlight.main}`,
|
|
17
|
+
borderRight: `1px solid ${theme.palette.highlight.main}`,
|
|
18
|
+
},
|
|
19
|
+
}));
|
|
25
20
|
const OverviewHighlight = (0, mobx_react_1.observer)(function OverviewHighlight({ model, overview, }) {
|
|
26
21
|
const { classes } = useStyles();
|
|
27
|
-
const { cytobandOffset } = model;
|
|
22
|
+
const { highlight, cytobandOffset } = model;
|
|
28
23
|
const session = (0, util_1.getSession)(model);
|
|
29
24
|
const { assemblyManager } = session;
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
return highlight
|
|
26
|
+
.map(r => {
|
|
27
|
+
var _a;
|
|
28
|
+
const asm = assemblyManager.get(r.assemblyName);
|
|
29
|
+
const refName = (_a = asm === null || asm === void 0 ? void 0 : asm.getCanonicalRefName(r.refName)) !== null && _a !== void 0 ? _a : r.refName;
|
|
32
30
|
const s = overview.bpToPx({
|
|
33
31
|
...r,
|
|
34
|
-
|
|
32
|
+
refName,
|
|
33
|
+
coord: r.start,
|
|
35
34
|
});
|
|
36
35
|
const e = overview.bpToPx({
|
|
37
36
|
...r,
|
|
38
|
-
|
|
37
|
+
refName,
|
|
38
|
+
coord: r.end,
|
|
39
39
|
});
|
|
40
|
-
return s !== undefined && e
|
|
40
|
+
return s !== undefined && e !== undefined
|
|
41
41
|
? {
|
|
42
42
|
width: Math.abs(e - s),
|
|
43
43
|
left: s + cytobandOffset,
|
|
44
44
|
}
|
|
45
45
|
: undefined;
|
|
46
|
-
};
|
|
47
|
-
return model.highlight
|
|
48
|
-
.map(h => {
|
|
49
|
-
var _a;
|
|
50
|
-
const asm = assemblyManager.get(h === null || h === void 0 ? void 0 : h.assemblyName);
|
|
51
|
-
return mapCoords({
|
|
52
|
-
...h,
|
|
53
|
-
refName: (_a = asm === null || asm === void 0 ? void 0 : asm.getCanonicalRefName(h.refName)) !== null && _a !== void 0 ? _a : h.refName,
|
|
54
|
-
});
|
|
55
46
|
})
|
|
56
47
|
.filter(util_1.notEmpty)
|
|
57
|
-
.map(({ left, width }, idx) => (react_1.default.createElement("div", {
|
|
48
|
+
.map(({ left, width }, idx) => (react_1.default.createElement("div", {
|
|
49
|
+
/* biome-ignore lint/suspicious/noArrayIndexKey: */
|
|
50
|
+
key: `${left}_${width}_${idx}`, className: classes.highlight, style: {
|
|
58
51
|
width: width,
|
|
59
52
|
left: left,
|
|
60
53
|
} })));
|
|
@@ -140,7 +140,7 @@ const OverviewRubberband = (0, mobx_react_1.observer)(function OverviewRubberban
|
|
|
140
140
|
}
|
|
141
141
|
let left = startX || 0;
|
|
142
142
|
let width = 0;
|
|
143
|
-
if (
|
|
143
|
+
if (currentX !== undefined) {
|
|
144
144
|
left = currentX < startX ? currentX : startX;
|
|
145
145
|
width = currentX - startX;
|
|
146
146
|
}
|
|
@@ -148,8 +148,7 @@ const Scalebar = (0, mobx_react_1.observer)(function ({ model, scale, overview,
|
|
|
148
148
|
const { pluginManager } = (0, util_1.getEnv)(model);
|
|
149
149
|
const visibleRegions = dynamicBlocks.contentBlocks;
|
|
150
150
|
const overviewVisibleRegions = overview.dynamicBlocks;
|
|
151
|
-
const
|
|
152
|
-
const scalebarColor = tertiary ? tertiary.light : primary.light;
|
|
151
|
+
const scalebarColor = theme.palette.tertiary.light;
|
|
153
152
|
// catches possible null from at's below
|
|
154
153
|
if (!visibleRegions.length) {
|
|
155
154
|
return null;
|
|
@@ -187,23 +186,19 @@ const Scalebar = (0, mobx_react_1.observer)(function ({ model, scale, overview,
|
|
|
187
186
|
});
|
|
188
187
|
const OverviewScalebar = (0, mobx_react_1.observer)(function ({ model, children, }) {
|
|
189
188
|
const { classes } = useStyles();
|
|
190
|
-
const { totalBp, width, cytobandOffset, displayedRegions } = model;
|
|
189
|
+
const { minimumBlockWidth, totalBp, width, cytobandOffset, displayedRegions, } = model;
|
|
191
190
|
const modWidth = width - cytobandOffset;
|
|
191
|
+
const str = JSON.stringify(displayedRegions);
|
|
192
192
|
const overview = (0, react_1.useMemo)(() => {
|
|
193
193
|
const overview = Base1DViewModel_1.default.create({
|
|
194
|
-
displayedRegions: JSON.parse(
|
|
194
|
+
displayedRegions: JSON.parse(str),
|
|
195
195
|
interRegionPaddingWidth: 0,
|
|
196
|
-
minimumBlockWidth
|
|
196
|
+
minimumBlockWidth,
|
|
197
197
|
});
|
|
198
198
|
overview.setVolatileWidth(modWidth);
|
|
199
199
|
overview.showAllRegions();
|
|
200
200
|
return overview;
|
|
201
|
-
}, [
|
|
202
|
-
JSON.stringify(displayedRegions), // eslint-disable-line react-hooks/exhaustive-deps
|
|
203
|
-
model.minimumBlockWidth,
|
|
204
|
-
modWidth,
|
|
205
|
-
displayedRegions,
|
|
206
|
-
]);
|
|
201
|
+
}, [str, minimumBlockWidth, modWidth]);
|
|
207
202
|
const scale = totalBp / (modWidth - (displayedRegions.length - 1) * wholeSeqSpacer);
|
|
208
203
|
return (react_1.default.createElement("div", null,
|
|
209
204
|
react_1.default.createElement(OverviewRubberband_1.default, { model: model, overview: overview, ControlComponent: react_1.default.createElement(Scalebar, { model: model, overview: overview, scale: scale }) }),
|
|
@@ -14,8 +14,7 @@ const OverviewScalebarPolygon = (0, mobx_react_1.observer)(function ({ model, ov
|
|
|
14
14
|
const multiplier = Number(useOffset);
|
|
15
15
|
const { interRegionPaddingWidth, offsetPx, dynamicBlocks, cytobandOffset } = model;
|
|
16
16
|
const { contentBlocks, totalWidthPxWithoutBorders } = dynamicBlocks;
|
|
17
|
-
const
|
|
18
|
-
const polygonColor = tertiary ? tertiary.light : primary.light;
|
|
17
|
+
const polygonColor = theme.palette.tertiary.light;
|
|
19
18
|
// catches possible null from at's below
|
|
20
19
|
if (!contentBlocks.length) {
|
|
21
20
|
return null;
|
|
@@ -10,12 +10,13 @@ const material_1 = require("@mui/material");
|
|
|
10
10
|
const EndAdornment_1 = __importDefault(require("./EndAdornment"));
|
|
11
11
|
function AutocompleteTextField({ TextFieldProps, inputBoxVal, params, showHelp, setInputValue, setCurrentSearch, }) {
|
|
12
12
|
const { helperText, InputProps = {} } = TextFieldProps;
|
|
13
|
-
return (react_1.default.createElement(material_1.TextField, { onBlur: () =>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
setInputValue(inputBoxVal), ...params, ...TextFieldProps, size: "small", helperText: helperText, InputProps: {
|
|
13
|
+
return (react_1.default.createElement(material_1.TextField, { onBlur: () => {
|
|
14
|
+
setInputValue(inputBoxVal);
|
|
15
|
+
}, ...params, ...TextFieldProps, size: "small", helperText: helperText, InputProps: {
|
|
17
16
|
...params.InputProps,
|
|
18
17
|
...InputProps,
|
|
19
18
|
endAdornment: (react_1.default.createElement(EndAdornment_1.default, { showHelp: showHelp, endAdornment: params.InputProps.endAdornment })),
|
|
20
|
-
}, placeholder: "Search for location", onChange: e =>
|
|
19
|
+
}, placeholder: "Search for location", onChange: e => {
|
|
20
|
+
setCurrentSearch(e.target.value);
|
|
21
|
+
} }));
|
|
21
22
|
}
|
|
@@ -37,10 +37,14 @@ const HelpDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __import
|
|
|
37
37
|
function HelpAdornment() {
|
|
38
38
|
const [isHelpDialogDisplayed, setHelpDialogDisplayed] = (0, react_1.useState)(false);
|
|
39
39
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
40
|
-
react_1.default.createElement(material_1.IconButton, { onClick: () =>
|
|
40
|
+
react_1.default.createElement(material_1.IconButton, { onClick: () => {
|
|
41
|
+
setHelpDialogDisplayed(true);
|
|
42
|
+
}, size: "small" },
|
|
41
43
|
react_1.default.createElement(Help_1.default, { fontSize: "small" })),
|
|
42
44
|
isHelpDialogDisplayed ? (react_1.default.createElement(react_1.Suspense, { fallback: null },
|
|
43
|
-
react_1.default.createElement(HelpDialog, { handleClose: () =>
|
|
45
|
+
react_1.default.createElement(HelpDialog, { handleClose: () => {
|
|
46
|
+
setHelpDialogDisplayed(false);
|
|
47
|
+
} }))) : null));
|
|
44
48
|
}
|
|
45
49
|
function EndAdornment({ showHelp, endAdornment, }) {
|
|
46
50
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
@@ -44,5 +44,7 @@ function HelpDialog({ handleClose, }) {
|
|
|
44
44
|
" - use whitespace separated refname, start, end"))),
|
|
45
45
|
react_1.default.createElement(material_1.Divider, null),
|
|
46
46
|
react_1.default.createElement(material_1.DialogActions, null,
|
|
47
|
-
react_1.default.createElement(material_1.Button, { onClick: () =>
|
|
47
|
+
react_1.default.createElement(material_1.Button, { onClick: () => {
|
|
48
|
+
handleClose();
|
|
49
|
+
}, color: "primary" }, "Close"))));
|
|
48
50
|
}
|
|
@@ -62,24 +62,26 @@ const RefNameAutocomplete = (0, mobx_react_1.observer)(function ({ model, onSele
|
|
|
62
62
|
session.notifyError(`${e}`, e);
|
|
63
63
|
}
|
|
64
64
|
})();
|
|
65
|
-
}, [assemblyName, fetchResults, debouncedSearch, session
|
|
65
|
+
}, [assemblyName, fetchResults, debouncedSearch, session]);
|
|
66
66
|
const inputBoxVal = coarseVisibleLocStrings || value || '';
|
|
67
67
|
// heuristic, text width + 60 accommodates help icon and search icon
|
|
68
68
|
const width = Math.min(Math.max((0, util_1.measureText)(inputBoxVal, 14) + 100, minWidth), maxWidth);
|
|
69
|
-
const
|
|
70
|
-
const regionOptions = (
|
|
69
|
+
const refNames = assembly === null || assembly === void 0 ? void 0 : assembly.refNames;
|
|
70
|
+
const regionOptions = (refNames === null || refNames === void 0 ? void 0 : refNames.map(refName => ({
|
|
71
71
|
result: new BaseResults_1.RefSequenceResult({
|
|
72
|
-
refName
|
|
73
|
-
label:
|
|
72
|
+
refName,
|
|
73
|
+
label: refName,
|
|
74
74
|
matchedAttribute: 'refName',
|
|
75
75
|
}),
|
|
76
|
-
}))) || []
|
|
76
|
+
}))) || [];
|
|
77
77
|
// notes on implementation:
|
|
78
78
|
// The selectOnFocus setting helps highlight the field when clicked
|
|
79
79
|
return (react_1.default.createElement(material_1.Autocomplete, { "data-testid": "autocomplete", disableListWrap: true, disableClearable: true, disabled: !assemblyName, freeSolo: true, includeInputInList: true, selectOnFocus: true, style: { ...style, width }, value: inputBoxVal, loading: !loaded, inputValue: inputValue, onInputChange: (_event, newInputValue) => {
|
|
80
80
|
setInputValue(newInputValue);
|
|
81
81
|
onChange === null || onChange === void 0 ? void 0 : onChange(newInputValue);
|
|
82
|
-
}, loadingText: "loading results", open: open, onOpen: () =>
|
|
82
|
+
}, loadingText: "loading results", open: open, onOpen: () => {
|
|
83
|
+
setOpen(true);
|
|
84
|
+
}, onClose: () => {
|
|
83
85
|
setOpen(false);
|
|
84
86
|
setLoaded(true);
|
|
85
87
|
if (hasDisplayedRegions) {
|
|
@@ -29,10 +29,8 @@ const mui_1 = require("tss-react/mui");
|
|
|
29
29
|
const material_1 = require("@mui/material");
|
|
30
30
|
const util_1 = require("@jbrowse/core/util");
|
|
31
31
|
const useStyles = (0, mui_1.makeStyles)()(theme => {
|
|
32
|
-
const {
|
|
33
|
-
const background = tertiary
|
|
34
|
-
? (0, material_1.alpha)(tertiary.light, 0.7)
|
|
35
|
-
: (0, material_1.alpha)(primary.light, 0.7);
|
|
32
|
+
const { tertiary } = theme.palette;
|
|
33
|
+
const background = (0, material_1.alpha)(tertiary.light, 0.7);
|
|
36
34
|
return {
|
|
37
35
|
rubberband: {
|
|
38
36
|
height: '100%',
|
|
@@ -48,7 +46,7 @@ const useStyles = (0, mui_1.makeStyles)()(theme => {
|
|
|
48
46
|
minHeight: 8,
|
|
49
47
|
},
|
|
50
48
|
rubberbandText: {
|
|
51
|
-
color: tertiary
|
|
49
|
+
color: tertiary.contrastText,
|
|
52
50
|
},
|
|
53
51
|
popover: {
|
|
54
52
|
mouseEvents: 'none',
|
|
@@ -51,6 +51,7 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
|
51
51
|
},
|
|
52
52
|
}));
|
|
53
53
|
const RenderedRefNameLabels = (0, mobx_react_1.observer)(function ({ model }) {
|
|
54
|
+
var _a;
|
|
54
55
|
const { classes } = useStyles();
|
|
55
56
|
const { staticBlocks, offsetPx, scaleBarDisplayPrefix } = model;
|
|
56
57
|
// find the block that needs pinning to the left side for context
|
|
@@ -62,7 +63,7 @@ const RenderedRefNameLabels = (0, mobx_react_1.observer)(function ({ model }) {
|
|
|
62
63
|
});
|
|
63
64
|
const val = scaleBarDisplayPrefix();
|
|
64
65
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
65
|
-
staticBlocks.blocks[0].type !== 'ContentBlock' && val ? (react_1.default.createElement(material_1.Typography, { style: { left: 0, zIndex: 100 }, className: classes.refLabel }, val)) : null,
|
|
66
|
+
((_a = staticBlocks.blocks[0]) === null || _a === void 0 ? void 0 : _a.type) !== 'ContentBlock' && val ? (react_1.default.createElement(material_1.Typography, { style: { left: 0, zIndex: 100 }, className: classes.refLabel }, val)) : null,
|
|
66
67
|
staticBlocks.map((block, index) => {
|
|
67
68
|
return block.type === 'ContentBlock' &&
|
|
68
69
|
(block.isLeftEndOfDisplayedRegion || index === lastLeftBlock) ? (react_1.default.createElement(material_1.Typography, { key: `refLabel-${block.key}-${index}`, style: {
|
|
@@ -19,5 +19,7 @@ function SearchResultsDialog({ model, assemblyName, searchQuery, searchResults,
|
|
|
19
19
|
react_1.default.createElement(SearchResultsTable_1.default, { model: model, handleClose: handleClose, assemblyName: assemblyName, searchResults: searchResults })))),
|
|
20
20
|
react_1.default.createElement(material_1.Divider, null),
|
|
21
21
|
react_1.default.createElement(material_1.DialogActions, null,
|
|
22
|
-
react_1.default.createElement(material_1.Button, { onClick: () =>
|
|
22
|
+
react_1.default.createElement(material_1.Button, { onClick: () => {
|
|
23
|
+
handleClose();
|
|
24
|
+
}, color: "primary" }, "Cancel"))));
|
|
23
25
|
}
|
|
@@ -9,11 +9,10 @@ const material_1 = require("@mui/material");
|
|
|
9
9
|
const mobx_state_tree_1 = require("mobx-state-tree");
|
|
10
10
|
const util_1 = require("@jbrowse/core/util");
|
|
11
11
|
function SearchResultsTable({ searchResults, assemblyName: optAssemblyName, model, handleClose, }) {
|
|
12
|
-
var _a;
|
|
13
12
|
const session = (0, util_1.getSession)(model);
|
|
14
13
|
const { pluginManager } = (0, util_1.getEnv)(session);
|
|
15
14
|
const { assemblyManager } = session;
|
|
16
|
-
const assemblyName = optAssemblyName ||
|
|
15
|
+
const assemblyName = optAssemblyName || model.displayedRegions[0].assemblyName;
|
|
17
16
|
const assembly = assemblyManager.get(assemblyName);
|
|
18
17
|
if (!assembly) {
|
|
19
18
|
throw new Error(`assembly ${assemblyName} not found`);
|
|
@@ -57,7 +56,7 @@ function SearchResultsTable({ searchResults, assemblyName: optAssemblyName, mode
|
|
|
57
56
|
react_1.default.createElement(material_1.TableCell, { align: "right" }, "Location"),
|
|
58
57
|
react_1.default.createElement(material_1.TableCell, { align: "right" }, "Track"),
|
|
59
58
|
react_1.default.createElement(material_1.TableCell, { align: "right" }))),
|
|
60
|
-
react_1.default.createElement(material_1.TableBody, null, searchResults.map(result => (react_1.default.createElement(material_1.TableRow, { key:
|
|
59
|
+
react_1.default.createElement(material_1.TableBody, null, searchResults.map(result => (react_1.default.createElement(material_1.TableRow, { key: result.getId() },
|
|
61
60
|
react_1.default.createElement(material_1.TableCell, { component: "th", scope: "row" }, result.getLabel()),
|
|
62
61
|
react_1.default.createElement(material_1.TableCell, { align: "right" }, result.getLocation()),
|
|
63
62
|
react_1.default.createElement(material_1.TableCell, { align: "right" }, getTrackName(result.getTrackId()) || 'N/A'),
|
|
@@ -51,11 +51,19 @@ const SequenceSearchDialog = (0, mobx_react_1.observer)(function ({ model, handl
|
|
|
51
51
|
return (react_1.default.createElement(ui_1.Dialog, { maxWidth: "xl", open: true, onClose: handleClose, title: "Sequence search" },
|
|
52
52
|
react_1.default.createElement(material_1.DialogContent, { className: classes.dialogContent },
|
|
53
53
|
react_1.default.createElement(material_1.Typography, null, "Supply a sequence to search for. A track will be created with the resulting matches once submitted. You can also supply regex style expressions e.g. AACT(C|T)."),
|
|
54
|
-
react_1.default.createElement(material_1.TextField, { value: value, onChange: e =>
|
|
54
|
+
react_1.default.createElement(material_1.TextField, { value: value, onChange: e => {
|
|
55
|
+
setValue(e.target.value);
|
|
56
|
+
}, helperText: "Sequence search pattern" }),
|
|
55
57
|
react_1.default.createElement(material_1.FormGroup, null,
|
|
56
|
-
react_1.default.createElement(material_1.FormControlLabel, { control: react_1.default.createElement(material_1.Checkbox, { checked: searchForward, onChange: event =>
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
react_1.default.createElement(material_1.FormControlLabel, { control: react_1.default.createElement(material_1.Checkbox, { checked: searchForward, onChange: event => {
|
|
59
|
+
setSearchForward(event.target.checked);
|
|
60
|
+
} }), label: "Search forward strand" }),
|
|
61
|
+
react_1.default.createElement(material_1.FormControlLabel, { control: react_1.default.createElement(material_1.Checkbox, { checked: searchReverse, onChange: event => {
|
|
62
|
+
setSearchReverse(event.target.checked);
|
|
63
|
+
} }), label: "Search reverse strand" }),
|
|
64
|
+
react_1.default.createElement(material_1.FormControlLabel, { control: react_1.default.createElement(material_1.Checkbox, { checked: caseInsensitive, onChange: event => {
|
|
65
|
+
setCaseInsensitive(event.target.checked);
|
|
66
|
+
} }), label: "Case insensitive" })),
|
|
59
67
|
error ? react_1.default.createElement(material_1.Typography, { color: "error" }, `${error}`) : null),
|
|
60
68
|
react_1.default.createElement(material_1.DialogActions, null,
|
|
61
69
|
react_1.default.createElement(material_1.Button, { onClick: () => {
|
|
@@ -85,6 +93,8 @@ const SequenceSearchDialog = (0, mobx_react_1.observer)(function ({ model, handl
|
|
|
85
93
|
}
|
|
86
94
|
handleClose();
|
|
87
95
|
}, variant: "contained", color: "primary" }, "Submit"),
|
|
88
|
-
react_1.default.createElement(material_1.Button, { onClick: () =>
|
|
96
|
+
react_1.default.createElement(material_1.Button, { onClick: () => {
|
|
97
|
+
handleClose();
|
|
98
|
+
}, variant: "contained", color: "secondary" }, "Close"))));
|
|
89
99
|
});
|
|
90
100
|
exports.default = SequenceSearchDialog;
|
|
@@ -49,9 +49,9 @@ const useStyles = (0, mui_1.makeStyles)()({
|
|
|
49
49
|
const TrackContainer = (0, mobx_react_1.observer)(function ({ model, track, }) {
|
|
50
50
|
const { classes } = useStyles();
|
|
51
51
|
const display = track.displays[0];
|
|
52
|
-
const { draggingTrackId } = model;
|
|
52
|
+
const { draggingTrackId, showTrackOutlines } = model;
|
|
53
53
|
const ref = (0, react_1.useRef)(null);
|
|
54
|
-
return (react_1.default.createElement(material_1.Paper, { ref: ref, className: classes.root, variant:
|
|
54
|
+
return (react_1.default.createElement(material_1.Paper, { ref: ref, className: classes.root, variant: showTrackOutlines ? 'outlined' : undefined, elevation: showTrackOutlines ? undefined : 0, onClick: event => {
|
|
55
55
|
var _a;
|
|
56
56
|
if (event.detail === 2 && !track.displays[0].featureIdUnderMouse) {
|
|
57
57
|
const left = ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left) || 0;
|
|
@@ -53,27 +53,37 @@ const TrackLabel = (0, mobx_react_1.observer)(react_1.default.forwardRef(functio
|
|
|
53
53
|
{
|
|
54
54
|
label: minimized ? 'Restore track' : 'Minimize track',
|
|
55
55
|
icon: minimized ? Add_1.default : Minimize_1.default,
|
|
56
|
-
onClick: () =>
|
|
56
|
+
onClick: () => {
|
|
57
|
+
track.setMinimized(!minimized);
|
|
58
|
+
},
|
|
57
59
|
},
|
|
58
60
|
{
|
|
59
61
|
label: 'Move track to top',
|
|
60
62
|
icon: KeyboardDoubleArrowUp_1.default,
|
|
61
|
-
onClick: () =>
|
|
63
|
+
onClick: () => {
|
|
64
|
+
view.moveTrackToTop(track.id);
|
|
65
|
+
},
|
|
62
66
|
},
|
|
63
67
|
{
|
|
64
68
|
label: 'Move track up',
|
|
65
69
|
icon: KeyboardArrowUp_1.default,
|
|
66
|
-
onClick: () =>
|
|
70
|
+
onClick: () => {
|
|
71
|
+
view.moveTrackUp(track.id);
|
|
72
|
+
},
|
|
67
73
|
},
|
|
68
74
|
{
|
|
69
75
|
label: 'Move track down',
|
|
70
76
|
icon: KeyboardArrowDown_1.default,
|
|
71
|
-
onClick: () =>
|
|
77
|
+
onClick: () => {
|
|
78
|
+
view.moveTrackDown(track.id);
|
|
79
|
+
},
|
|
72
80
|
},
|
|
73
81
|
{
|
|
74
82
|
label: 'Move track to bottom',
|
|
75
83
|
icon: KeyboardDoubleArrowDown_1.default,
|
|
76
|
-
onClick: () =>
|
|
84
|
+
onClick: () => {
|
|
85
|
+
view.moveTrackToBottom(track.id);
|
|
86
|
+
},
|
|
77
87
|
},
|
|
78
88
|
],
|
|
79
89
|
},
|
|
@@ -26,7 +26,9 @@ function TrackLabelDragHandle({ trackId, view, track, }) {
|
|
|
26
26
|
event.dataTransfer.setDragImage(parent, 20, 20);
|
|
27
27
|
view.setDraggingTrackId(track.id);
|
|
28
28
|
}
|
|
29
|
-
}, onDragEnd: () =>
|
|
29
|
+
}, onDragEnd: () => {
|
|
30
|
+
view.setDraggingTrackId(undefined);
|
|
31
|
+
}, "data-testid": `dragHandle-${view.id}-${trackId}` },
|
|
30
32
|
react_1.default.createElement(DragIndicator_1.default, { className: classes.dragHandleIcon, fontSize: "small" })));
|
|
31
33
|
}
|
|
32
34
|
exports.default = TrackLabelDragHandle;
|
|
@@ -53,7 +53,7 @@ const TracksContainer = (0, mobx_react_1.observer)(function TracksContainer({ ch
|
|
|
53
53
|
const { pluginManager } = (0, util_1.getEnv)(model);
|
|
54
54
|
const { mouseDown: mouseDown1, mouseUp } = (0, hooks_1.useSideScroll)(model);
|
|
55
55
|
const ref = (0, react_1.useRef)(null);
|
|
56
|
-
const { guideX, rubberbandOn, leftBpOffset, rightBpOffset, numOfBpSelected, width, left, anchorPosition,
|
|
56
|
+
const { guideX, rubberbandOn, leftBpOffset, rightBpOffset, numOfBpSelected, width, left, anchorPosition, open, handleMenuItemClick, handleClose, mouseMove, mouseDown: mouseDown2, } = (0, hooks_1.useRangeSelect)(ref, model, true);
|
|
57
57
|
(0, hooks_1.useWheelScroll)(ref, model);
|
|
58
58
|
const additional = pluginManager.evaluateExtensionPoint('LinearGenomeView-TracksContainerComponent', undefined, { model });
|
|
59
59
|
return (react_1.default.createElement("div", { ref: ref, "data-testid": "trackContainer", className: classes.tracksContainer, onMouseDown: event => {
|
|
@@ -49,12 +49,18 @@ const ZoomControls = (0, mobx_react_1.observer)(function ({ model, }) {
|
|
|
49
49
|
const [value, setValue] = (0, react_1.useState)(-Math.log2(bpPerPx) * 100);
|
|
50
50
|
(0, react_1.useEffect)(() => {
|
|
51
51
|
setValue(-Math.log2(bpPerPx) * 100);
|
|
52
|
-
}, [
|
|
52
|
+
}, [bpPerPx]);
|
|
53
53
|
return (react_1.default.createElement("div", { className: classes.container },
|
|
54
|
-
react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_out", onClick: () =>
|
|
54
|
+
react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_out", onClick: () => {
|
|
55
|
+
model.zoom(bpPerPx * 2);
|
|
56
|
+
}, disabled: bpPerPx >= maxBpPerPx - 0.0001, size: "large" },
|
|
55
57
|
react_1.default.createElement(ZoomOut_1.default, null)),
|
|
56
|
-
react_1.default.createElement(material_1.Slider, { size: "small", className: classes.slider, value: value, min: -Math.log2(maxBpPerPx) * 100, max: -Math.log2(minBpPerPx) * 100, onChange: (_, val) =>
|
|
57
|
-
|
|
58
|
+
react_1.default.createElement(material_1.Slider, { size: "small", className: classes.slider, value: value, min: -Math.log2(maxBpPerPx) * 100, max: -Math.log2(minBpPerPx) * 100, onChange: (_, val) => {
|
|
59
|
+
setValue(val);
|
|
60
|
+
}, onChangeCommitted: () => model.zoomTo(2 ** (-value / 100)) }),
|
|
61
|
+
react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_in", onClick: () => {
|
|
62
|
+
model.zoom(model.bpPerPx / 2);
|
|
63
|
+
}, disabled: bpPerPx <= minBpPerPx + 0.0001, size: "large" },
|
|
58
64
|
react_1.default.createElement(ZoomIn_1.default, null))));
|
|
59
65
|
});
|
|
60
66
|
exports.default = ZoomControls;
|
|
@@ -16,7 +16,7 @@ export declare function useRangeSelect(ref: React.RefObject<HTMLDivElement>, mod
|
|
|
16
16
|
mouseDown: (event: React.MouseEvent<HTMLDivElement>) => void;
|
|
17
17
|
mouseMove: (event: React.MouseEvent<HTMLDivElement>) => void;
|
|
18
18
|
mouseOut: () => void;
|
|
19
|
-
handleMenuItemClick: (_: unknown, callback:
|
|
19
|
+
handleMenuItemClick: (_: unknown, callback: () => void) => void;
|
|
20
20
|
rubberbandOn?: undefined;
|
|
21
21
|
handleClose?: undefined;
|
|
22
22
|
leftBpOffset?: undefined;
|
|
@@ -32,7 +32,7 @@ export declare function useRangeSelect(ref: React.RefObject<HTMLDivElement>, mod
|
|
|
32
32
|
mouseMove: (event: React.MouseEvent<HTMLDivElement>) => void;
|
|
33
33
|
mouseOut: () => void;
|
|
34
34
|
handleClose: () => void;
|
|
35
|
-
handleMenuItemClick: (_: unknown, callback:
|
|
35
|
+
handleMenuItemClick: (_: unknown, callback: () => void) => void;
|
|
36
36
|
leftBpOffset: {
|
|
37
37
|
coord: number;
|
|
38
38
|
index: number;
|