@jbrowse/plugin-linear-genome-view 2.10.2 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/BaseLinearDisplay/components/BlockMsg.d.ts +2 -4
  2. package/dist/BaseLinearDisplay/components/BlockMsg.js +2 -3
  3. package/dist/BaseLinearDisplay/components/LinearBlocks.js +2 -2
  4. package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.d.ts +10 -2
  5. package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +40 -4
  6. package/dist/BaseLinearDisplay/components/TooLargeMessage.js +5 -4
  7. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +18 -4
  8. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +9 -2
  9. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js +0 -1
  10. package/dist/LaunchLinearGenomeView/index.js +24 -8
  11. package/dist/LinearBareDisplay/model.d.ts +18 -4
  12. package/dist/LinearBasicDisplay/components/SetMaxHeight.d.ts +1 -1
  13. package/dist/LinearBasicDisplay/model.d.ts +22 -4
  14. package/dist/LinearGenomeView/components/Cytobands.d.ts +1 -125
  15. package/dist/LinearGenomeView/components/ExportSvgDialog.js +9 -5
  16. package/dist/LinearGenomeView/components/Highlight.d.ts +7 -0
  17. package/dist/LinearGenomeView/components/Highlight.js +126 -0
  18. package/dist/LinearGenomeView/components/MiniControls.js +13 -15
  19. package/dist/LinearGenomeView/components/OverviewHighlight.d.ts +9 -0
  20. package/dist/LinearGenomeView/components/OverviewHighlight.js +62 -0
  21. package/dist/LinearGenomeView/components/OverviewRubberband.d.ts +1 -1
  22. package/dist/LinearGenomeView/components/OverviewScalebar.js +6 -1
  23. package/dist/LinearGenomeView/components/OverviewScalebarPolygon.d.ts +1 -1
  24. package/dist/LinearGenomeView/components/RefNameAutocomplete/index.d.ts +9 -9
  25. package/dist/LinearGenomeView/components/RefNameAutocomplete/index.js +28 -35
  26. package/dist/LinearGenomeView/components/Rubberband.d.ts +1 -1
  27. package/dist/LinearGenomeView/components/SearchBox.d.ts +1 -1
  28. package/dist/LinearGenomeView/components/SearchResultsTable.js +1 -1
  29. package/dist/LinearGenomeView/components/TrackContainer.js +10 -23
  30. package/dist/LinearGenomeView/components/TrackLabel.js +33 -6
  31. package/dist/LinearGenomeView/components/TracksContainer.js +2 -0
  32. package/dist/LinearGenomeView/components/ZoomControls.js +4 -4
  33. package/dist/LinearGenomeView/model.d.ts +70 -5
  34. package/dist/LinearGenomeView/model.js +111 -14
  35. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +1 -1
  36. package/dist/LinearGenomeView/util.d.ts +1 -1
  37. package/dist/index.d.ts +213 -21
  38. package/esm/BaseLinearDisplay/components/BlockMsg.d.ts +2 -4
  39. package/esm/BaseLinearDisplay/components/BlockMsg.js +3 -4
  40. package/esm/BaseLinearDisplay/components/LinearBlocks.js +2 -2
  41. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.d.ts +10 -2
  42. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +17 -4
  43. package/esm/BaseLinearDisplay/components/TooLargeMessage.js +5 -4
  44. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +18 -4
  45. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +9 -2
  46. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +0 -1
  47. package/esm/LaunchLinearGenomeView/index.js +25 -9
  48. package/esm/LinearBareDisplay/model.d.ts +18 -4
  49. package/esm/LinearBasicDisplay/components/SetMaxHeight.d.ts +1 -1
  50. package/esm/LinearBasicDisplay/model.d.ts +22 -4
  51. package/esm/LinearGenomeView/components/Cytobands.d.ts +1 -125
  52. package/esm/LinearGenomeView/components/ExportSvgDialog.js +9 -5
  53. package/esm/LinearGenomeView/components/Highlight.d.ts +7 -0
  54. package/esm/LinearGenomeView/components/Highlight.js +98 -0
  55. package/esm/LinearGenomeView/components/MiniControls.js +14 -16
  56. package/esm/LinearGenomeView/components/OverviewHighlight.d.ts +9 -0
  57. package/esm/LinearGenomeView/components/OverviewHighlight.js +57 -0
  58. package/esm/LinearGenomeView/components/OverviewRubberband.d.ts +1 -1
  59. package/esm/LinearGenomeView/components/OverviewScalebar.js +7 -2
  60. package/esm/LinearGenomeView/components/OverviewScalebarPolygon.d.ts +1 -1
  61. package/esm/LinearGenomeView/components/RefNameAutocomplete/index.d.ts +9 -9
  62. package/esm/LinearGenomeView/components/RefNameAutocomplete/index.js +28 -35
  63. package/esm/LinearGenomeView/components/Rubberband.d.ts +1 -1
  64. package/esm/LinearGenomeView/components/SearchBox.d.ts +1 -1
  65. package/esm/LinearGenomeView/components/SearchResultsTable.js +1 -1
  66. package/esm/LinearGenomeView/components/TrackContainer.js +10 -23
  67. package/esm/LinearGenomeView/components/TrackLabel.js +33 -6
  68. package/esm/LinearGenomeView/components/TracksContainer.js +2 -0
  69. package/esm/LinearGenomeView/components/ZoomControls.js +4 -4
  70. package/esm/LinearGenomeView/model.d.ts +70 -5
  71. package/esm/LinearGenomeView/model.js +112 -15
  72. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +1 -1
  73. package/esm/LinearGenomeView/util.d.ts +1 -1
  74. package/esm/index.d.ts +213 -21
  75. package/package.json +2 -2
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const react_1 = __importStar(require("react"));
30
+ const mobx_react_1 = require("mobx-react");
31
+ const mui_1 = require("tss-react/mui");
32
+ const colord_1 = require("@jbrowse/core/util/colord");
33
+ const util_1 = require("@jbrowse/core/util");
34
+ const ui_1 = require("@jbrowse/core/ui");
35
+ const material_1 = require("@mui/material");
36
+ // icons
37
+ const Link_1 = __importDefault(require("@mui/icons-material/Link"));
38
+ const Close_1 = __importDefault(require("@mui/icons-material/Close"));
39
+ const Bookmark_1 = __importDefault(require("@mui/icons-material/Bookmark"));
40
+ const useStyles = (0, mui_1.makeStyles)()(theme => {
41
+ var _a, _b;
42
+ return ({
43
+ highlight: {
44
+ height: '100%',
45
+ position: 'absolute',
46
+ overflow: 'hidden',
47
+ background: `${(0, colord_1.colord)((_b = (_a = theme.palette.highlight) === null || _a === void 0 ? void 0 : _a.main) !== null && _b !== void 0 ? _b : 'goldenrod')
48
+ .alpha(0.35)
49
+ .toRgbString()}`,
50
+ },
51
+ });
52
+ });
53
+ const Highlight = (0, mobx_react_1.observer)(function Highlight({ model, highlight, }) {
54
+ var _a, _b, _c;
55
+ const { classes } = useStyles();
56
+ const [open, setOpen] = (0, react_1.useState)(false);
57
+ const anchorEl = (0, react_1.useRef)(null);
58
+ const color = (_b = (_a = (0, material_1.useTheme)().palette.highlight) === null || _a === void 0 ? void 0 : _a.main) !== null && _b !== void 0 ? _b : 'goldenrod';
59
+ const session = (0, util_1.getSession)(model);
60
+ const { assemblyManager } = session;
61
+ const dismissHighlight = () => {
62
+ model.removeHighlight(highlight);
63
+ };
64
+ const menuItems = [
65
+ {
66
+ label: 'Dismiss highlight',
67
+ icon: Close_1.default,
68
+ onClick: () => dismissHighlight(),
69
+ },
70
+ {
71
+ label: 'Bookmark highlighted region',
72
+ icon: Bookmark_1.default,
73
+ onClick: () => {
74
+ let bookmarkWidget = session.widgets.get('GridBookmark');
75
+ if (!bookmarkWidget) {
76
+ bookmarkWidget = session.addWidget('GridBookmarkWidget', 'GridBookmark');
77
+ }
78
+ // @ts-ignore
79
+ bookmarkWidget.addBookmark(highlight);
80
+ dismissHighlight();
81
+ },
82
+ },
83
+ ];
84
+ function handleClose() {
85
+ setOpen(false);
86
+ }
87
+ // coords
88
+ const mapCoords = (r) => {
89
+ const s = model.bpToPx({
90
+ refName: r.refName,
91
+ coord: r.start,
92
+ });
93
+ const e = model.bpToPx({
94
+ refName: r.refName,
95
+ coord: r.end,
96
+ });
97
+ return s && e
98
+ ? {
99
+ width: Math.max(Math.abs(e.offsetPx - s.offsetPx), 3),
100
+ left: Math.min(s.offsetPx, e.offsetPx) - model.offsetPx,
101
+ }
102
+ : undefined;
103
+ };
104
+ const asm = assemblyManager.get(highlight === null || highlight === void 0 ? void 0 : highlight.assemblyName);
105
+ const h = mapCoords({
106
+ ...highlight,
107
+ refName: (_c = asm === null || asm === void 0 ? void 0 : asm.getCanonicalRefName(highlight.refName)) !== null && _c !== void 0 ? _c : highlight.refName,
108
+ });
109
+ return h ? (react_1.default.createElement("div", { className: classes.highlight, style: {
110
+ left: h.left,
111
+ width: h.width,
112
+ } },
113
+ react_1.default.createElement(material_1.Tooltip, { title: 'Highlighted from URL parameter', arrow: true },
114
+ react_1.default.createElement(material_1.IconButton, { ref: anchorEl, onClick: () => setOpen(true), style: { zIndex: 3 } },
115
+ react_1.default.createElement(Link_1.default, { fontSize: "small", sx: {
116
+ color: `${(0, colord_1.colord)(color).darken(0.2).toRgbString()}`,
117
+ } }))),
118
+ react_1.default.createElement(ui_1.Menu, { anchorEl: anchorEl.current, onMenuItemClick: (_event, callback) => {
119
+ callback(session);
120
+ handleClose();
121
+ }, open: open, onClose: handleClose, menuItems: menuItems }))) : null;
122
+ });
123
+ const HighlightGroup = (0, mobx_react_1.observer)(function HighlightGroup({ model, }) {
124
+ return model.highlight.map((highlight, idx) => (react_1.default.createElement(Highlight, { key: JSON.stringify(highlight) + '-' + idx, model: model, highlight: highlight })));
125
+ });
126
+ exports.default = HighlightGroup;
@@ -6,13 +6,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
7
  const mobx_react_1 = require("mobx-react");
8
8
  const material_1 = require("@mui/material");
9
+ const CascadingMenuButton_1 = __importDefault(require("@jbrowse/core/ui/CascadingMenuButton"));
10
+ const mui_1 = require("tss-react/mui");
11
+ const util_1 = require("@jbrowse/core/util");
9
12
  // icons
10
13
  const ZoomIn_1 = __importDefault(require("@mui/icons-material/ZoomIn"));
11
14
  const ZoomOut_1 = __importDefault(require("@mui/icons-material/ZoomOut"));
12
15
  const KeyboardArrowDown_1 = __importDefault(require("@mui/icons-material/KeyboardArrowDown"));
13
- const CascadingMenuButton_1 = __importDefault(require("@jbrowse/core/ui/CascadingMenuButton"));
14
- const mui_1 = require("tss-react/mui");
15
- const util_1 = require("@jbrowse/core/util");
16
16
  const useStyles = (0, mui_1.makeStyles)()(theme => ({
17
17
  background: {
18
18
  position: 'absolute',
@@ -21,22 +21,20 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
21
21
  background: theme.palette.background.paper,
22
22
  },
23
23
  focusedBackground: {
24
- background: theme.palette.secondary.light,
25
- svg: {
26
- fill: theme.palette.secondary.contrastText,
27
- },
24
+ background: (0, material_1.alpha)(theme.palette.secondary.light, 0.2),
28
25
  },
29
26
  }));
30
27
  const MiniControls = (0, mobx_react_1.observer)(function ({ model, }) {
31
- const { classes, cx } = useStyles();
28
+ const { classes } = useStyles();
32
29
  const { id, bpPerPx, maxBpPerPx, minBpPerPx, scaleFactor, hideHeader } = model;
33
30
  const { focusedViewId } = (0, util_1.getSession)(model);
34
- return hideHeader ? (react_1.default.createElement(material_1.Paper, { className: cx(classes.background, focusedViewId === id ? classes.focusedBackground : undefined) },
35
- react_1.default.createElement(CascadingMenuButton_1.default, { menuItems: model.menuItems() },
36
- react_1.default.createElement(KeyboardArrowDown_1.default, { fontSize: "small" })),
37
- react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_out", onClick: () => model.zoom(bpPerPx * 2), disabled: bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1 },
38
- react_1.default.createElement(ZoomOut_1.default, { fontSize: "small" })),
39
- react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_in", onClick: () => model.zoom(bpPerPx / 2), disabled: bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1 },
40
- react_1.default.createElement(ZoomIn_1.default, { fontSize: "small" })))) : null;
31
+ return hideHeader ? (react_1.default.createElement(material_1.Paper, { className: classes.background },
32
+ react_1.default.createElement(material_1.Paper, { className: focusedViewId === id ? classes.focusedBackground : undefined },
33
+ react_1.default.createElement(CascadingMenuButton_1.default, { menuItems: model.menuItems() },
34
+ react_1.default.createElement(KeyboardArrowDown_1.default, { fontSize: "small" })),
35
+ react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_out", onClick: () => model.zoom(bpPerPx * 2), disabled: bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1 },
36
+ react_1.default.createElement(ZoomOut_1.default, { fontSize: "small" })),
37
+ react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_in", onClick: () => model.zoom(bpPerPx / 2), disabled: bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1 },
38
+ react_1.default.createElement(ZoomIn_1.default, { fontSize: "small" }))))) : null;
41
39
  });
42
40
  exports.default = MiniControls;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { Base1DViewModel } from '@jbrowse/core/util/Base1DViewModel';
3
+ import { LinearGenomeViewModel } from '../model';
4
+ type LGV = LinearGenomeViewModel;
5
+ declare const OverviewHighlight: ({ model, overview, }: {
6
+ model: LGV;
7
+ overview: Base1DViewModel;
8
+ }) => React.JSX.Element[];
9
+ export default OverviewHighlight;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const mobx_react_1 = require("mobx-react");
8
+ const mui_1 = require("tss-react/mui");
9
+ const colord_1 = require("@jbrowse/core/util/colord");
10
+ const util_1 = require("@jbrowse/core/util");
11
+ const useStyles = (0, mui_1.makeStyles)()(theme => {
12
+ var _a, _b, _c, _d, _e, _f;
13
+ return ({
14
+ highlight: {
15
+ height: '100%',
16
+ position: 'absolute',
17
+ background: `${(0, colord_1.colord)((_b = (_a = theme.palette.highlight) === null || _a === void 0 ? void 0 : _a.main) !== null && _b !== void 0 ? _b : 'goldenrod')
18
+ .alpha(0.35)
19
+ .toRgbString()}`,
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
+ });
25
+ const OverviewHighlight = (0, mobx_react_1.observer)(function OverviewHighlight({ model, overview, }) {
26
+ const { classes } = useStyles();
27
+ const { cytobandOffset } = model;
28
+ const session = (0, util_1.getSession)(model);
29
+ const { assemblyManager } = session;
30
+ // coords
31
+ const mapCoords = (r) => {
32
+ const s = overview.bpToPx({
33
+ ...r,
34
+ coord: r.reversed ? r.end : r.start,
35
+ });
36
+ const e = overview.bpToPx({
37
+ ...r,
38
+ coord: r.reversed ? r.start : r.end,
39
+ });
40
+ return s !== undefined && e != undefined
41
+ ? {
42
+ width: Math.abs(e - s),
43
+ left: s + cytobandOffset,
44
+ }
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
+ })
56
+ .filter(util_1.notEmpty)
57
+ .map(({ left, width }, idx) => (react_1.default.createElement("div", { key: `${left}_${width}_${idx}`, className: classes.highlight, style: {
58
+ width: width,
59
+ left: left,
60
+ } })));
61
+ });
62
+ exports.default = OverviewHighlight;
@@ -5,6 +5,6 @@ type LGV = LinearGenomeViewModel;
5
5
  declare const OverviewRubberband: ({ model, overview, ControlComponent, }: {
6
6
  model: LGV;
7
7
  overview: Base1DViewModel;
8
- ControlComponent?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined;
8
+ ControlComponent?: React.ReactElement;
9
9
  }) => React.JSX.Element;
10
10
  export default OverviewRubberband;
@@ -41,6 +41,7 @@ const util_3 = require("./util");
41
41
  const OverviewRubberband_1 = __importDefault(require("./OverviewRubberband"));
42
42
  const Cytobands_1 = __importDefault(require("./Cytobands"));
43
43
  const OverviewScalebarPolygon_1 = __importDefault(require("./OverviewScalebarPolygon"));
44
+ const OverviewHighlight_1 = __importDefault(require("./OverviewHighlight"));
44
45
  const wholeSeqSpacer = 2;
45
46
  const useStyles = (0, mui_1.makeStyles)()(theme => ({
46
47
  scalebar: {
@@ -145,6 +146,7 @@ const Scalebar = (0, mobx_react_1.observer)(function ({ model, scale, overview,
145
146
  const { classes } = useStyles();
146
147
  const theme = (0, material_1.useTheme)();
147
148
  const { dynamicBlocks, showCytobands, cytobandOffset } = model;
149
+ const { pluginManager } = (0, util_1.getEnv)(model);
148
150
  const visibleRegions = dynamicBlocks.contentBlocks;
149
151
  const overviewVisibleRegions = overview.dynamicBlocks;
150
152
  const { tertiary, primary } = theme.palette;
@@ -165,6 +167,7 @@ const Scalebar = (0, mobx_react_1.observer)(function ({ model, scale, overview,
165
167
  }) || 0;
166
168
  const color = showCytobands ? '#f00' : scalebarColor;
167
169
  const transparency = showCytobands ? 0.1 : 0.3;
170
+ const additional = pluginManager.evaluateExtensionPoint('LinearGenomeView-OverviewScalebarComponent', undefined, { model, overview });
168
171
  return (react_1.default.createElement("div", { className: classes.scalebar },
169
172
  react_1.default.createElement("div", { className: classes.scalebarVisibleRegion, style: {
170
173
  width: lastOverviewPx - firstOverviewPx,
@@ -179,7 +182,9 @@ const Scalebar = (0, mobx_react_1.observer)(function ({ model, scale, overview,
179
182
  backgroundColor: '#999',
180
183
  backgroundImage: 'repeating-linear-gradient(90deg, transparent, transparent 1px, rgba(255,255,255,.5) 1px, rgba(255,255,255,.5) 3px)',
181
184
  } })) : (react_1.default.createElement(OverviewBox, { scale: scale, block: block, model: model, overview: overview, key: `${JSON.stringify(block)}-${idx}` }));
182
- })));
185
+ }),
186
+ react_1.default.createElement(OverviewHighlight_1.default, { model: model, overview: overview }),
187
+ additional));
183
188
  });
184
189
  const OverviewScalebar = (0, mobx_react_1.observer)(function ({ model, children, }) {
185
190
  const { classes } = useStyles();
@@ -4,6 +4,6 @@ import { LinearGenomeViewModel } from '..';
4
4
  declare const OverviewScalebarPolygon: ({ model, overview, useOffset, }: {
5
5
  model: LinearGenomeViewModel;
6
6
  overview: Base1DViewModel;
7
- useOffset?: boolean | undefined;
7
+ useOffset?: boolean;
8
8
  }) => React.JSX.Element | null;
9
9
  export default OverviewScalebarPolygon;
@@ -4,15 +4,15 @@ import { TextFieldProps as TFP } from '@mui/material';
4
4
  import { LinearGenomeViewModel } from '../../model';
5
5
  declare const RefNameAutocomplete: ({ model, onSelect, assemblyName, style, fetchResults, onChange, value, showHelp, minWidth, maxWidth, TextFieldProps, }: {
6
6
  model: LinearGenomeViewModel;
7
- onSelect?: ((region: BaseResult) => void) | undefined;
8
- onChange?: ((val: string) => void) | undefined;
9
- assemblyName?: string | undefined;
10
- value?: string | undefined;
7
+ onSelect?: (region: BaseResult) => void;
8
+ onChange?: (val: string) => void;
9
+ assemblyName?: string;
10
+ value?: string;
11
11
  fetchResults: (query: string) => Promise<BaseResult[]>;
12
- style?: React.CSSProperties | undefined;
13
- minWidth?: number | undefined;
14
- maxWidth?: number | undefined;
15
- showHelp?: boolean | undefined;
16
- TextFieldProps?: TFP | undefined;
12
+ style?: React.CSSProperties;
13
+ minWidth?: number;
14
+ maxWidth?: number;
15
+ showHelp?: boolean;
16
+ TextFieldProps?: TFP;
17
17
  }) => React.JSX.Element;
18
18
  export default RefNameAutocomplete;
@@ -45,7 +45,8 @@ const RefNameAutocomplete = (0, mobx_react_1.observer)(function ({ model, onSele
45
45
  const assembly = assemblyName ? assemblyManager.get(assemblyName) : undefined;
46
46
  const { coarseVisibleLocStrings, hasDisplayedRegions } = model;
47
47
  (0, react_1.useEffect)(() => {
48
- let active = true;
48
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
49
+ ;
49
50
  (async () => {
50
51
  try {
51
52
  if (debouncedSearch === '' || !assemblyName) {
@@ -53,21 +54,14 @@ const RefNameAutocomplete = (0, mobx_react_1.observer)(function ({ model, onSele
53
54
  }
54
55
  setLoaded(false);
55
56
  const results = await fetchResults(debouncedSearch);
56
- if (active) {
57
- setLoaded(true);
58
- setSearchOptions((0, util_2.getDeduplicatedResult)(results));
59
- }
57
+ setLoaded(true);
58
+ setSearchOptions((0, util_2.getDeduplicatedResult)(results));
60
59
  }
61
60
  catch (e) {
62
61
  console.error(e);
63
- if (active) {
64
- session.notify(`${e}`, 'error');
65
- }
62
+ session.notifyError(`${e}`, e);
66
63
  }
67
64
  })();
68
- return () => {
69
- active = false;
70
- };
71
65
  }, [assemblyName, fetchResults, debouncedSearch, session, model]);
72
66
  const inputBoxVal = coarseVisibleLocStrings || value || '';
73
67
  // heuristic, text width + 60 accommodates help icon and search icon
@@ -82,29 +76,28 @@ const RefNameAutocomplete = (0, mobx_react_1.observer)(function ({ model, onSele
82
76
  }))) || [], [regions]);
83
77
  // notes on implementation:
84
78
  // The selectOnFocus setting helps highlight the field when clicked
85
- return (react_1.default.createElement(react_1.default.Fragment, null,
86
- 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) => {
87
- setInputValue(newInputValue);
88
- onChange === null || onChange === void 0 ? void 0 : onChange(newInputValue);
89
- }, loadingText: "loading results", open: open, onOpen: () => setOpen(true), onClose: () => {
90
- setOpen(false);
91
- setLoaded(true);
92
- if (hasDisplayedRegions) {
93
- setCurrentSearch('');
94
- setSearchOptions(undefined);
95
- }
96
- }, onChange: (_event, selectedOption) => {
97
- if (!selectedOption || !assemblyName) {
98
- return;
99
- }
100
- if (typeof selectedOption === 'string') {
101
- // handles string inputs on keyPress enter
102
- onSelect === null || onSelect === void 0 ? void 0 : onSelect(new BaseResults_1.default({ label: selectedOption }));
103
- }
104
- else {
105
- onSelect === null || onSelect === void 0 ? void 0 : onSelect(selectedOption.result);
106
- }
107
- setInputValue(inputBoxVal);
108
- }, options: (searchOptions === null || searchOptions === void 0 ? void 0 : searchOptions.length) ? searchOptions : regionOptions, getOptionDisabled: option => option.group === 'limitOption', filterOptions: (opts, { inputValue }) => (0, util_2.getFiltered)(opts, inputValue), renderInput: params => (react_1.default.createElement(AutocompleteTextField_1.default, { showHelp: showHelp, params: params, inputBoxVal: inputBoxVal, TextFieldProps: TextFieldProps, setCurrentSearch: setCurrentSearch, setInputValue: setInputValue })), getOptionLabel: opt => typeof opt === 'string' ? opt : opt.result.getDisplayString() })));
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
+ setInputValue(newInputValue);
81
+ onChange === null || onChange === void 0 ? void 0 : onChange(newInputValue);
82
+ }, loadingText: "loading results", open: open, onOpen: () => setOpen(true), onClose: () => {
83
+ setOpen(false);
84
+ setLoaded(true);
85
+ if (hasDisplayedRegions) {
86
+ setCurrentSearch('');
87
+ setSearchOptions(undefined);
88
+ }
89
+ }, onChange: (_event, selectedOption) => {
90
+ if (!selectedOption || !assemblyName) {
91
+ return;
92
+ }
93
+ if (typeof selectedOption === 'string') {
94
+ // handles string inputs on keyPress enter
95
+ onSelect === null || onSelect === void 0 ? void 0 : onSelect(new BaseResults_1.default({ label: selectedOption }));
96
+ }
97
+ else {
98
+ onSelect === null || onSelect === void 0 ? void 0 : onSelect(selectedOption.result);
99
+ }
100
+ setInputValue(inputBoxVal);
101
+ }, options: (searchOptions === null || searchOptions === void 0 ? void 0 : searchOptions.length) ? searchOptions : regionOptions, getOptionDisabled: option => option.group === 'limitOption', filterOptions: (opts, { inputValue }) => (0, util_2.getFiltered)(opts, inputValue), renderInput: params => (react_1.default.createElement(AutocompleteTextField_1.default, { showHelp: showHelp, params: params, inputBoxVal: inputBoxVal, TextFieldProps: TextFieldProps, setCurrentSearch: setCurrentSearch, setInputValue: setInputValue })), getOptionLabel: opt => typeof opt === 'string' ? opt : opt.result.getDisplayString() }));
109
102
  });
110
103
  exports.default = RefNameAutocomplete;
@@ -3,6 +3,6 @@ import { LinearGenomeViewModel } from '..';
3
3
  type LGV = LinearGenomeViewModel;
4
4
  declare const Rubberband: ({ model, ControlComponent, }: {
5
5
  model: LGV;
6
- ControlComponent?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined;
6
+ ControlComponent?: React.ReactElement;
7
7
  }) => React.JSX.Element;
8
8
  export default Rubberband;
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { LinearGenomeViewModel } from '..';
3
3
  declare const SearchBox: ({ model, showHelp, }: {
4
- showHelp?: boolean | undefined;
4
+ showHelp?: boolean;
5
5
  model: LinearGenomeViewModel;
6
6
  }) => React.JSX.Element;
7
7
  export default SearchBox;
@@ -74,7 +74,7 @@ function SearchResultsTable({ searchResults, assemblyName: optAssemblyName, mode
74
74
  }
75
75
  catch (e) {
76
76
  console.error(e);
77
- session.notify(`${e}`, 'error');
77
+ session.notifyError(`${e}`, e);
78
78
  }
79
79
  handleClose();
80
80
  }, color: "primary", variant: "contained" }, "Go")))))))));
@@ -33,7 +33,6 @@ const mobx_react_1 = require("mobx-react");
33
33
  const mobx_state_tree_1 = require("mobx-state-tree");
34
34
  const react_error_boundary_1 = require("react-error-boundary");
35
35
  const ui_1 = require("@jbrowse/core/ui");
36
- const util_1 = require("@jbrowse/core/util");
37
36
  const TrackLabelContainer_1 = __importDefault(require("./TrackLabelContainer"));
38
37
  const TrackRenderingContainer_1 = __importDefault(require("./TrackRenderingContainer"));
39
38
  const useStyles = (0, mui_1.makeStyles)()({
@@ -46,40 +45,28 @@ const useStyles = (0, mui_1.makeStyles)()({
46
45
  position: 'relative',
47
46
  zIndex: 2,
48
47
  },
49
- overlay: {
50
- pointerEvents: 'none',
51
- position: 'absolute',
52
- top: 0,
53
- left: 0,
54
- width: '100%',
55
- zIndex: 3,
56
- },
57
48
  });
58
49
  const TrackContainer = (0, mobx_react_1.observer)(function ({ model, track, }) {
59
50
  const { classes } = useStyles();
60
51
  const display = track.displays[0];
61
52
  const { draggingTrackId } = model;
62
- const ref2 = (0, react_1.useRef)(null);
63
- const dimmed = draggingTrackId !== undefined && draggingTrackId !== display.id;
64
- const debouncedOnDragEnter = (0, util_1.useDebouncedCallback)(() => {
65
- if ((0, mobx_state_tree_1.isAlive)(display) && dimmed) {
66
- model.moveTrack(draggingTrackId, track.id);
67
- }
68
- }, 100);
69
- return (react_1.default.createElement(material_1.Paper, { ref: ref2, className: classes.root, variant: "outlined", onClick: event => {
53
+ const ref = (0, react_1.useRef)(null);
54
+ return (react_1.default.createElement(material_1.Paper, { ref: ref, className: classes.root, variant: "outlined", onClick: event => {
70
55
  var _a;
71
56
  if (event.detail === 2 && !track.displays[0].featureIdUnderMouse) {
72
- const left = ((_a = ref2.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left) || 0;
57
+ const left = ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left) || 0;
73
58
  model.zoomTo(model.bpPerPx / 2, event.clientX - left, true);
74
59
  }
75
60
  } },
76
61
  react_1.default.createElement(TrackLabelContainer_1.default, { track: track, view: model }),
77
62
  react_1.default.createElement(react_error_boundary_1.ErrorBoundary, { FallbackComponent: e => react_1.default.createElement(ui_1.ErrorMessage, { error: e.error }) },
78
- react_1.default.createElement(TrackRenderingContainer_1.default, { model: model, track: track, onDragEnter: debouncedOnDragEnter })),
79
- react_1.default.createElement("div", { className: classes.overlay, style: {
80
- height: display.height,
81
- background: dimmed ? 'rgba(0, 0, 0, 0.4)' : undefined,
82
- }, onDragEnter: debouncedOnDragEnter }),
63
+ react_1.default.createElement(TrackRenderingContainer_1.default, { model: model, track: track, onDragEnter: () => {
64
+ if ((0, mobx_state_tree_1.isAlive)(display) &&
65
+ draggingTrackId !== undefined &&
66
+ draggingTrackId !== display.id) {
67
+ model.moveTrack(draggingTrackId, track.id);
68
+ }
69
+ } })),
83
70
  react_1.default.createElement(ui_1.ResizeHandle, { onDrag: display.resizeHeight, className: classes.resizeHandle })));
84
71
  });
85
72
  exports.default = TrackContainer;
@@ -17,6 +17,10 @@ const MoreVert_1 = __importDefault(require("@mui/icons-material/MoreVert"));
17
17
  const Close_1 = __importDefault(require("@mui/icons-material/Close"));
18
18
  const Minimize_1 = __importDefault(require("@mui/icons-material/Minimize"));
19
19
  const Add_1 = __importDefault(require("@mui/icons-material/Add"));
20
+ const KeyboardDoubleArrowDown_1 = __importDefault(require("@mui/icons-material/KeyboardDoubleArrowDown"));
21
+ const KeyboardDoubleArrowUp_1 = __importDefault(require("@mui/icons-material/KeyboardDoubleArrowUp"));
22
+ const KeyboardArrowDown_1 = __importDefault(require("@mui/icons-material/KeyboardArrowDown"));
23
+ const KeyboardArrowUp_1 = __importDefault(require("@mui/icons-material/KeyboardArrowUp"));
20
24
  const TrackLabelDragHandle_1 = __importDefault(require("./TrackLabelDragHandle"));
21
25
  const useStyles = (0, mui_1.makeStyles)()(theme => ({
22
26
  root: {
@@ -24,9 +28,6 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
24
28
  '&:hover': {
25
29
  background: theme.palette.background.paper,
26
30
  },
27
- transition: theme.transitions.create(['background'], {
28
- duration: theme.transitions.duration.shortest,
29
- }),
30
31
  },
31
32
  trackName: {
32
33
  margin: '0 auto',
@@ -49,9 +50,35 @@ const TrackLabel = (0, mobx_react_1.observer)(react_1.default.forwardRef(functio
49
50
  const trackName = (0, tracks_1.getTrackName)(trackConf, session);
50
51
  const items = [
51
52
  {
52
- label: minimized ? 'Restore track' : 'Minimize track',
53
- icon: minimized ? Add_1.default : Minimize_1.default,
54
- onClick: () => track.setMinimized(!minimized),
53
+ label: 'Track order',
54
+ type: 'subMenu',
55
+ subMenu: [
56
+ {
57
+ label: minimized ? 'Restore track' : 'Minimize track',
58
+ icon: minimized ? Add_1.default : Minimize_1.default,
59
+ onClick: () => track.setMinimized(!minimized),
60
+ },
61
+ {
62
+ label: 'Move track to top',
63
+ icon: KeyboardDoubleArrowUp_1.default,
64
+ onClick: () => view.moveTrackToTop(track.id),
65
+ },
66
+ {
67
+ label: 'Move track up',
68
+ icon: KeyboardArrowUp_1.default,
69
+ onClick: () => view.moveTrackUp(track.id),
70
+ },
71
+ {
72
+ label: 'Move track down',
73
+ icon: KeyboardArrowDown_1.default,
74
+ onClick: () => view.moveTrackDown(track.id),
75
+ },
76
+ {
77
+ label: 'Move track to bottom',
78
+ icon: KeyboardDoubleArrowDown_1.default,
79
+ onClick: () => view.moveTrackToBottom(track.id),
80
+ },
81
+ ],
55
82
  },
56
83
  ...(((_a = session.getTrackActionMenuItems) === null || _a === void 0 ? void 0 : _a.call(session, trackConf)) || []),
57
84
  ...track.trackMenuItems(),
@@ -41,6 +41,7 @@ const Gridlines_1 = __importDefault(require("./Gridlines"));
41
41
  const CenterLine_1 = __importDefault(require("./CenterLine"));
42
42
  const VerticalGuide_1 = __importDefault(require("./VerticalGuide"));
43
43
  const RubberbandSpan_1 = __importDefault(require("./RubberbandSpan"));
44
+ const Highlight_1 = __importDefault(require("./Highlight"));
44
45
  const useStyles = (0, mui_1.makeStyles)()({
45
46
  tracksContainer: {
46
47
  position: 'relative',
@@ -67,6 +68,7 @@ const TracksContainer = (0, mobx_react_1.observer)(function TracksContainer({ ch
67
68
  top: anchorPosition.clientY,
68
69
  }, onMenuItemClick: handleMenuItemClick, open: open, onClose: handleClose, menuItems: model.rubberBandMenuItems() })) : null,
69
70
  react_1.default.createElement(Rubberband_1.default, { model: model, ControlComponent: react_1.default.createElement(Scalebar_1.default, { model: model, style: { height: __1.SCALE_BAR_HEIGHT, boxSizing: 'border-box' } }) }),
71
+ react_1.default.createElement(Highlight_1.default, { model: model }),
70
72
  additional,
71
73
  children));
72
74
  });
@@ -45,16 +45,16 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
45
45
  }));
46
46
  const ZoomControls = (0, mobx_react_1.observer)(function ({ model, }) {
47
47
  const { classes } = useStyles();
48
- const { maxBpPerPx, minBpPerPx, bpPerPx, scaleFactor } = model;
48
+ const { maxBpPerPx, minBpPerPx, bpPerPx } = 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
  }, [setValue, 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: () => model.zoom(bpPerPx * 2), disabled: bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1, size: "large" },
54
+ react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_out", onClick: () => model.zoom(bpPerPx * 2), disabled: bpPerPx >= maxBpPerPx - 0.0001, size: "large" },
55
55
  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) => setValue(val), onChangeCommitted: () => model.zoomTo(2 ** (-value / 100)), disabled: scaleFactor !== 1 }),
57
- react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_in", onClick: () => model.zoom(model.bpPerPx / 2), disabled: bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1, size: "large" },
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) => setValue(val), onChangeCommitted: () => model.zoomTo(2 ** (-value / 100)) }),
57
+ react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_in", onClick: () => model.zoom(model.bpPerPx / 2), disabled: bpPerPx <= minBpPerPx + 0.0001, size: "large" },
58
58
  react_1.default.createElement(ZoomIn_1.default, null))));
59
59
  });
60
60
  exports.default = ZoomControls;