@jbrowse/plugin-linear-genome-view 3.6.5 → 3.7.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 (63) hide show
  1. package/dist/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +1 -1
  2. package/dist/BaseLinearDisplay/components/BaseLinearDisplay.js +3 -18
  3. package/dist/BaseLinearDisplay/components/BlockMsg.js +2 -0
  4. package/dist/BaseLinearDisplay/components/LinearBlocks.d.ts +1 -5
  5. package/dist/BaseLinearDisplay/components/LinearBlocks.js +5 -38
  6. package/dist/BaseLinearDisplay/components/MaxHeightReachedIndicator.d.ts +3 -0
  7. package/dist/BaseLinearDisplay/components/MaxHeightReachedIndicator.js +27 -0
  8. package/dist/BaseLinearDisplay/components/MenuPage.d.ts +8 -0
  9. package/dist/BaseLinearDisplay/components/MenuPage.js +26 -0
  10. package/dist/BaseLinearDisplay/components/RenderedBlocks.d.ts +9 -0
  11. package/dist/BaseLinearDisplay/components/RenderedBlocks.js +27 -0
  12. package/dist/BaseLinearDisplay/components/Tooltip.d.ts +1 -0
  13. package/dist/BaseLinearDisplay/components/Tooltip.js +5 -2
  14. package/dist/BaseLinearDisplay/components/types.d.ts +1 -0
  15. package/dist/BaseLinearDisplay/components/types.js +2 -0
  16. package/dist/BaseLinearDisplay/index.d.ts +2 -2
  17. package/dist/BaseLinearDisplay/index.js +2 -2
  18. package/dist/BaseLinearDisplay/{models/BaseLinearDisplayModel.d.ts → model.d.ts} +17 -4
  19. package/dist/BaseLinearDisplay/{models/BaseLinearDisplayModel.js → model.js} +22 -7
  20. package/dist/BaseLinearDisplay/models/autorunFeatureDensityStats.d.ts +1 -1
  21. package/dist/BaseLinearDisplay/models/configSchema.js +2 -2
  22. package/dist/BaseLinearDisplay/models/renderSvg.d.ts +1 -1
  23. package/dist/LinearBareDisplay/model.d.ts +17 -2
  24. package/dist/LinearBasicDisplay/model.d.ts +17 -2
  25. package/dist/LinearGenomeView/components/RegionWidthEditorDialog.js +1 -1
  26. package/dist/LinearGenomeView/components/SequenceSearchDialog.js +1 -1
  27. package/dist/LinearGenomeView/components/TrackContainer.js +7 -3
  28. package/dist/LinearGenomeView/components/useRangeSelect.js +10 -14
  29. package/dist/LinearGenomeView/model.js +1 -1
  30. package/dist/LinearGenomeView/util.js +1 -1
  31. package/dist/index.d.ts +17 -2
  32. package/esm/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +1 -1
  33. package/esm/BaseLinearDisplay/components/BaseLinearDisplay.js +3 -18
  34. package/esm/BaseLinearDisplay/components/BlockMsg.js +2 -0
  35. package/esm/BaseLinearDisplay/components/LinearBlocks.d.ts +1 -5
  36. package/esm/BaseLinearDisplay/components/LinearBlocks.js +2 -37
  37. package/esm/BaseLinearDisplay/components/MaxHeightReachedIndicator.d.ts +3 -0
  38. package/esm/BaseLinearDisplay/components/MaxHeightReachedIndicator.js +24 -0
  39. package/esm/BaseLinearDisplay/components/MenuPage.d.ts +8 -0
  40. package/esm/BaseLinearDisplay/components/MenuPage.js +24 -0
  41. package/esm/BaseLinearDisplay/components/RenderedBlocks.d.ts +9 -0
  42. package/esm/BaseLinearDisplay/components/RenderedBlocks.js +22 -0
  43. package/esm/BaseLinearDisplay/components/Tooltip.d.ts +1 -0
  44. package/esm/BaseLinearDisplay/components/Tooltip.js +5 -2
  45. package/esm/BaseLinearDisplay/components/types.d.ts +1 -0
  46. package/esm/BaseLinearDisplay/components/types.js +1 -0
  47. package/esm/BaseLinearDisplay/index.d.ts +2 -2
  48. package/esm/BaseLinearDisplay/index.js +1 -1
  49. package/esm/BaseLinearDisplay/{models/BaseLinearDisplayModel.d.ts → model.d.ts} +17 -4
  50. package/esm/BaseLinearDisplay/{models/BaseLinearDisplayModel.js → model.js} +22 -7
  51. package/esm/BaseLinearDisplay/models/autorunFeatureDensityStats.d.ts +1 -1
  52. package/esm/BaseLinearDisplay/models/configSchema.js +2 -2
  53. package/esm/BaseLinearDisplay/models/renderSvg.d.ts +1 -1
  54. package/esm/LinearBareDisplay/model.d.ts +17 -2
  55. package/esm/LinearBasicDisplay/model.d.ts +17 -2
  56. package/esm/LinearGenomeView/components/RegionWidthEditorDialog.js +1 -1
  57. package/esm/LinearGenomeView/components/SequenceSearchDialog.js +1 -1
  58. package/esm/LinearGenomeView/components/TrackContainer.js +7 -3
  59. package/esm/LinearGenomeView/components/useRangeSelect.js +11 -15
  60. package/esm/LinearGenomeView/model.js +1 -1
  61. package/esm/LinearGenomeView/util.js +1 -1
  62. package/esm/index.d.ts +17 -2
  63. package/package.json +3 -3
@@ -9,6 +9,11 @@ function useRangeSelect(ref, model, shiftOnly) {
9
9
  const [anchorPosition, setAnchorPosition] = (0, react_1.useState)();
10
10
  const [guideX, setGuideX] = (0, react_1.useState)();
11
11
  const mouseDragging = startX !== undefined && anchorPosition === undefined;
12
+ const handleClose = (0, react_1.useCallback)(() => {
13
+ setAnchorPosition(undefined);
14
+ setStartX(undefined);
15
+ setCurrentX(undefined);
16
+ }, []);
12
17
  (0, react_1.useEffect)(() => {
13
18
  function computeOffsets(offsetX) {
14
19
  if (startX === undefined) {
@@ -31,6 +36,10 @@ function useRangeSelect(ref, model, shiftOnly) {
31
36
  if (startX !== undefined && ref.current) {
32
37
  const { clientX, clientY } = event;
33
38
  const offsetX = (0, util_1.getRelativeX)(event, ref.current);
39
+ if (Math.abs(offsetX - startX) <= 3) {
40
+ handleClose();
41
+ return;
42
+ }
34
43
  setAnchorPosition({
35
44
  offsetX,
36
45
  clientX,
@@ -52,15 +61,7 @@ function useRangeSelect(ref, model, shiftOnly) {
52
61
  };
53
62
  }
54
63
  return () => { };
55
- }, [startX, mouseDragging, model, ref]);
56
- (0, react_1.useEffect)(() => {
57
- if (!mouseDragging &&
58
- currentX !== undefined &&
59
- startX !== undefined &&
60
- Math.abs(currentX - startX) <= 3) {
61
- handleClose();
62
- }
63
- }, [mouseDragging, currentX, startX]);
64
+ }, [startX, mouseDragging, model, ref, handleClose]);
64
65
  function mouseDown(event) {
65
66
  if (shiftOnly && !event.shiftKey) {
66
67
  return;
@@ -87,11 +88,6 @@ function useRangeSelect(ref, model, shiftOnly) {
87
88
  function mouseOut() {
88
89
  setGuideX(undefined);
89
90
  }
90
- function handleClose() {
91
- setAnchorPosition(undefined);
92
- setStartX(undefined);
93
- setCurrentX(undefined);
94
- }
95
91
  function handleMenuItemClick(_, callback) {
96
92
  callback();
97
93
  handleClose();
@@ -687,7 +687,7 @@ function stateModelFactory(pluginManager) {
687
687
  onClick: self.horizontallyFlip,
688
688
  },
689
689
  {
690
- label: 'Color by CDS',
690
+ label: 'Color by CDS and draw amino acids',
691
691
  type: 'checkbox',
692
692
  checked: self.colorByCDS,
693
693
  icon: Palette_1.default,
@@ -9,7 +9,7 @@ const util_1 = require("@jbrowse/core/util");
9
9
  function chooseGridPitch(scale, minMajorPitchPx, minMinorPitchPx) {
10
10
  scale = Math.abs(scale);
11
11
  const minMajorPitchBp = minMajorPitchPx * scale;
12
- const majorMagnitude = Number.parseInt(Number(minMajorPitchBp).toExponential().split(/e/i)[1], 10);
12
+ const majorMagnitude = +minMajorPitchBp.toExponential().split(/e/i)[1];
13
13
  let majorPitch = 10 ** majorMagnitude;
14
14
  while (majorPitch < minMajorPitchBp) {
15
15
  majorPitch *= 2;
package/dist/index.d.ts CHANGED
@@ -176,6 +176,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
176
176
  regionCannotBeRenderedText(_region: import("@jbrowse/core/util").Region): "" | "Force load to see features";
177
177
  regionCannotBeRendered(_region: import("@jbrowse/core/util").Region): import("react/jsx-runtime").JSX.Element | null;
178
178
  } & {
179
+ mouseoverExtraInformation: string | undefined;
179
180
  featureIdUnderMouse: undefined | string;
180
181
  contextMenuFeature: undefined | import("@jbrowse/core/util").Feature;
181
182
  } & {
@@ -190,9 +191,22 @@ export default class LinearGenomeViewPlugin extends Plugin {
190
191
  } & {
191
192
  readonly features: import("@jbrowse/core/util/compositeMap").default<string, import("@jbrowse/core/util").Feature>;
192
193
  readonly featureUnderMouse: import("@jbrowse/core/util").Feature | undefined;
194
+ readonly layoutFeatures: import("@jbrowse/core/util/compositeMap").default<string, [number, number, number, number] | [number, number, number, number, {
195
+ label?: string;
196
+ description?: string;
197
+ refName: string;
198
+ }]>;
193
199
  getFeatureOverlapping(blockKey: string, x: number, y: number): string | undefined;
194
- getFeatureByID(blockKey: string, id: string): [number, number, number, number] | undefined;
195
- searchFeatureByID(id: string): [number, number, number, number] | undefined;
200
+ getFeatureByID(blockKey: string, id: string): ([number, number, number, number] | [number, number, number, number, {
201
+ label?: string;
202
+ description?: string;
203
+ refName: string;
204
+ }]) | undefined;
205
+ searchFeatureByID(id: string): ([number, number, number, number] | [number, number, number, number, {
206
+ label?: string;
207
+ description?: string;
208
+ refName: string;
209
+ }]) | undefined;
196
210
  } & {
197
211
  addBlock(key: string, block: import("@jbrowse/core/util/blockTypes").BaseBlock): void;
198
212
  deleteBlock(key: string): void;
@@ -201,6 +215,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
201
215
  clearFeatureSelection(): void;
202
216
  setFeatureIdUnderMouse(feature?: string): void;
203
217
  setContextMenuFeature(feature?: import("@jbrowse/core/util").Feature): void;
218
+ setMouseoverExtraInformation(extra?: string): void;
204
219
  } & {
205
220
  reload(): Promise<void>;
206
221
  } & {
@@ -1,4 +1,4 @@
1
- import type { BaseLinearDisplayModel } from '../models/BaseLinearDisplayModel';
1
+ import type { BaseLinearDisplayModel } from '../model';
2
2
  declare const BaseLinearDisplay: (props: {
3
3
  model: BaseLinearDisplayModel;
4
4
  children?: React.ReactNode;
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Suspense, useRef, useState } from 'react';
3
3
  import { getConf } from '@jbrowse/core/configuration';
4
- import { Menu } from '@jbrowse/core/ui';
5
4
  import { observer } from 'mobx-react';
6
5
  import { makeStyles } from 'tss-react/mui';
7
6
  import LinearBlocks from './LinearBlocks';
7
+ import MenuPage from './MenuPage';
8
8
  const useStyles = makeStyles()({
9
9
  display: {
10
10
  position: 'relative',
@@ -23,8 +23,6 @@ const BaseLinearDisplay = observer(function (props) {
23
23
  const [contextCoord, setContextCoord] = useState();
24
24
  const { model, children } = props;
25
25
  const { TooltipComponent, DisplayMessageComponent, height } = model;
26
- const items = model.contextMenuItems();
27
- const open = Boolean(contextCoord) && items.length > 0;
28
26
  return (_jsxs("div", { ref: ref, "data-testid": `display-${getConf(model, 'displayId')}`, className: classes.display, onContextMenu: event => {
29
27
  event.preventDefault();
30
28
  if (contextCoord) {
@@ -42,22 +40,9 @@ const BaseLinearDisplay = observer(function (props) {
42
40
  setOffsetMouseCoord([event.clientX - left, event.clientY - top]);
43
41
  setClientMouseCoord([event.clientX, event.clientY]);
44
42
  setClientRect(rect);
45
- }, children: [DisplayMessageComponent ? (_jsx(DisplayMessageComponent, { model: model })) : (_jsx(LinearBlocks, { ...props })), children, _jsx(Suspense, { fallback: null, children: _jsx(TooltipComponent, { model: model, height: height, offsetMouseCoord: offsetMouseCoord, clientMouseCoord: clientMouseCoord, clientRect: clientRect, mouseCoord: offsetMouseCoord }) }), open ? (_jsx(Menu, { open: true, onMenuItemClick: (_, callback) => {
46
- callback();
43
+ }, children: [DisplayMessageComponent ? (_jsx(DisplayMessageComponent, { model: model })) : (_jsx(LinearBlocks, { ...props })), children, _jsx(Suspense, { fallback: null, children: _jsx(TooltipComponent, { model: model, height: height, offsetMouseCoord: offsetMouseCoord, clientMouseCoord: clientMouseCoord, clientRect: clientRect, mouseCoord: offsetMouseCoord }) }), contextCoord ? (_jsx(MenuPage, { contextCoord: contextCoord, model: model, onClose: () => {
47
44
  setContextCoord(undefined);
48
- }, onClose: () => {
49
- setContextCoord(undefined);
50
- model.setContextMenuFeature(undefined);
51
- }, slotProps: {
52
- transition: {
53
- onExit: () => {
54
- setContextCoord(undefined);
55
- model.setContextMenuFeature(undefined);
56
- },
57
- },
58
- }, anchorReference: "anchorPosition", anchorPosition: contextCoord
59
- ? { top: contextCoord[1], left: contextCoord[0] }
60
- : undefined, menuItems: items })) : null] }));
45
+ } })) : null] }));
61
46
  });
62
47
  export default BaseLinearDisplay;
63
48
  export { default as Tooltip } from './Tooltip';
@@ -13,5 +13,7 @@ export default function BlockMsg({ message, severity, action, }) {
13
13
  message: classes.ellipses,
14
14
  }, onMouseDown: event => {
15
15
  event.stopPropagation();
16
+ }, onClick: event => {
17
+ event.stopPropagation();
16
18
  }, children: _jsx(Tooltip, { title: message, children: _jsx("div", { children: message }) }) }));
17
19
  }
@@ -1,8 +1,4 @@
1
- import type { BaseLinearDisplayModel } from '../models/BaseLinearDisplayModel';
2
- declare const RenderedBlocks: ({ model, }: {
3
- model: BaseLinearDisplayModel;
4
- }) => import("react/jsx-runtime").JSX.Element;
5
- export { RenderedBlocks };
1
+ import type { BaseLinearDisplayModel } from '../model';
6
2
  declare const LinearBlocks: ({ model, }: {
7
3
  model: BaseLinearDisplayModel;
8
4
  }) => import("react/jsx-runtime").JSX.Element;
@@ -1,8 +1,8 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { getContainingView } from '@jbrowse/core/util';
3
3
  import { observer } from 'mobx-react';
4
4
  import { makeStyles } from 'tss-react/mui';
5
- import { ContentBlock as ContentBlockComponent, ElidedBlock as ElidedBlockComponent, InterRegionPaddingBlock as InterRegionPaddingBlockComponent, } from './Block';
5
+ import RenderedBlocks from './RenderedBlocks';
6
6
  const useStyles = makeStyles()({
7
7
  linearBlocks: {
8
8
  whiteSpace: 'nowrap',
@@ -11,42 +11,7 @@ const useStyles = makeStyles()({
11
11
  minHeight: '100%',
12
12
  display: 'flex',
13
13
  },
14
- heightOverflowed: {
15
- position: 'absolute',
16
- color: 'rgb(77,77,77)',
17
- borderBottom: '2px solid rgb(77,77,77)',
18
- textShadow: 'white 0px 0px 1px',
19
- whiteSpace: 'nowrap',
20
- width: '100%',
21
- fontWeight: 'bold',
22
- textAlign: 'center',
23
- zIndex: 999,
24
- boxSizing: 'border-box',
25
- },
26
- });
27
- const RenderedBlocks = observer(function ({ model, }) {
28
- const { classes } = useStyles();
29
- const { blockDefinitions, blockState } = model;
30
- return (_jsx(_Fragment, { children: blockDefinitions.map(block => {
31
- const key = `${model.id}-${block.key}`;
32
- if (block.type === 'ContentBlock') {
33
- const state = blockState.get(block.key);
34
- return (_jsxs(ContentBlockComponent, { block: block, children: [(state === null || state === void 0 ? void 0 : state.ReactComponent) ? (_jsx(state.ReactComponent, { model: state })) : null, (state === null || state === void 0 ? void 0 : state.maxHeightReached) ? (_jsx("div", { className: classes.heightOverflowed, style: {
35
- top: state.layout.getTotalHeight() - 16,
36
- pointerEvents: 'none',
37
- height: 16,
38
- }, children: "Max height reached" })) : null] }, key));
39
- }
40
- if (block.type === 'ElidedBlock') {
41
- return _jsx(ElidedBlockComponent, { width: block.widthPx }, key);
42
- }
43
- if (block.type === 'InterRegionPaddingBlock') {
44
- return (_jsx(InterRegionPaddingBlockComponent, { width: block.widthPx, style: { background: 'none' }, boundary: block.variant === 'boundary' }, key));
45
- }
46
- throw new Error(`invalid block type ${JSON.stringify(block)}`);
47
- }) }));
48
14
  });
49
- export { RenderedBlocks };
50
15
  const LinearBlocks = observer(function ({ model, }) {
51
16
  const { classes } = useStyles();
52
17
  const { blockDefinitions } = model;
@@ -0,0 +1,3 @@
1
+ export default function MaxHeightReached({ top }: {
2
+ top: number;
3
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { makeStyles } from 'tss-react/mui';
3
+ const useStyles = makeStyles()({
4
+ heightOverflowed: {
5
+ position: 'absolute',
6
+ color: 'rgb(77,77,77)',
7
+ borderBottom: '2px solid rgb(77,77,77)',
8
+ textShadow: 'white 0px 0px 1px',
9
+ whiteSpace: 'nowrap',
10
+ width: '100%',
11
+ fontWeight: 'bold',
12
+ textAlign: 'center',
13
+ zIndex: 999,
14
+ boxSizing: 'border-box',
15
+ },
16
+ });
17
+ export default function MaxHeightReached({ top }) {
18
+ const { classes } = useStyles();
19
+ return (_jsx("div", { className: classes.heightOverflowed, style: {
20
+ top,
21
+ pointerEvents: 'none',
22
+ height: 16,
23
+ }, children: "Max height reached" }));
24
+ }
@@ -0,0 +1,8 @@
1
+ import type { Coord } from './types';
2
+ import type { BaseLinearDisplayModel } from '../model';
3
+ declare const MenuPage: ({ onClose, contextCoord, model, }: {
4
+ model: BaseLinearDisplayModel;
5
+ contextCoord: Coord;
6
+ onClose: () => void;
7
+ }) => import("react/jsx-runtime").JSX.Element;
8
+ export default MenuPage;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Menu } from '@jbrowse/core/ui';
3
+ import { observer } from 'mobx-react';
4
+ const MenuPage = observer(function ({ onClose, contextCoord, model, }) {
5
+ const items = model.contextMenuItems();
6
+ return (_jsx(Menu, { open: items.length > 0, onMenuItemClick: (_, callback) => {
7
+ callback();
8
+ onClose();
9
+ }, onClose: () => {
10
+ onClose();
11
+ model.setContextMenuFeature(undefined);
12
+ }, slotProps: {
13
+ transition: {
14
+ onExit: () => {
15
+ onClose();
16
+ model.setContextMenuFeature(undefined);
17
+ },
18
+ },
19
+ }, anchorReference: "anchorPosition", anchorPosition: {
20
+ top: contextCoord[1],
21
+ left: contextCoord[0],
22
+ }, menuItems: items }));
23
+ });
24
+ export default MenuPage;
@@ -0,0 +1,9 @@
1
+ import type { BlockSet } from '@jbrowse/core/util/blockTypes';
2
+ declare const RenderedBlocks: ({ model, }: {
3
+ model: {
4
+ id: string;
5
+ blockDefinitions: BlockSet;
6
+ blockState: any;
7
+ };
8
+ }) => import("react/jsx-runtime").JSX.Element[];
9
+ export default RenderedBlocks;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { observer } from 'mobx-react';
3
+ import { ContentBlock as ContentBlockComponent, ElidedBlock as ElidedBlockComponent, InterRegionPaddingBlock as InterRegionPaddingBlockComponent, } from './Block';
4
+ import MaxHeightReached from './MaxHeightReachedIndicator';
5
+ const RenderedBlocks = observer(function ({ model, }) {
6
+ const { blockDefinitions, blockState } = model;
7
+ return blockDefinitions.map(block => {
8
+ const key = `${model.id}-${block.key}`;
9
+ if (block.type === 'ContentBlock') {
10
+ const state = blockState.get(block.key);
11
+ return (_jsxs(ContentBlockComponent, { block: block, children: [(state === null || state === void 0 ? void 0 : state.ReactComponent) ? (_jsx(state.ReactComponent, { model: state })) : null, (state === null || state === void 0 ? void 0 : state.maxHeightReached) ? (_jsx(MaxHeightReached, { top: state.layout.getTotalHeight() - 16 })) : null] }, key));
12
+ }
13
+ else if (block.type === 'ElidedBlock') {
14
+ return _jsx(ElidedBlockComponent, { width: block.widthPx }, key);
15
+ }
16
+ else if (block.type === 'InterRegionPaddingBlock') {
17
+ return (_jsx(InterRegionPaddingBlockComponent, { width: block.widthPx, style: { background: 'none' }, boundary: block.variant === 'boundary' }, key));
18
+ }
19
+ throw new Error(`invalid block type ${JSON.stringify(block)}`);
20
+ });
21
+ });
22
+ export default RenderedBlocks;
@@ -4,6 +4,7 @@ type Coord = [number, number];
4
4
  declare const Tooltip: ({ model, clientMouseCoord, }: {
5
5
  model: {
6
6
  featureUnderMouse: Feature | undefined;
7
+ mouseoverExtraInformation: string | undefined;
7
8
  configuration: AnyConfigurationModel;
8
9
  };
9
10
  clientMouseCoord: Coord;
@@ -8,11 +8,14 @@ const TooltipContents = forwardRef(function TooltipContents2({ message }, ref) {
8
8
  return (_jsx("div", { ref: ref, children: isValidElement(message) ? (message) : message ? (_jsx(SanitizedHTML, { html: String(message) })) : null }));
9
9
  });
10
10
  const Tooltip = observer(function ({ model, clientMouseCoord, }) {
11
- const { featureUnderMouse } = model;
11
+ const { featureUnderMouse, mouseoverExtraInformation } = model;
12
12
  const x = clientMouseCoord[0] + 15;
13
13
  const y = clientMouseCoord[1];
14
14
  const contents = featureUnderMouse
15
- ? getConf(model, 'mouseover', { feature: featureUnderMouse })
15
+ ? getConf(model, 'mouseover', {
16
+ feature: featureUnderMouse,
17
+ mouseoverExtraInformation,
18
+ })
16
19
  : undefined;
17
20
  return featureUnderMouse && contents ? (_jsx(BaseTooltip, { clientPoint: { x, y }, children: _jsx(TooltipContents, { message: contents }) })) : null;
18
21
  });
@@ -0,0 +1 @@
1
+ export type Coord = [number, number];
@@ -0,0 +1 @@
1
+ export {};
@@ -1,7 +1,7 @@
1
1
  export { default as baseLinearDisplayConfigSchema } from './models/configSchema';
2
2
  export type { BlockModel } from './models/serverSideRenderedBlock';
3
- export { BaseLinearDisplay } from './models/BaseLinearDisplayModel';
4
- export type { BaseLinearDisplayModel, BaseLinearDisplayStateModel, ExportSvgDisplayOptions, } from './models/BaseLinearDisplayModel';
3
+ export { BaseLinearDisplay } from './model';
4
+ export type { BaseLinearDisplayModel, BaseLinearDisplayStateModel, ExportSvgDisplayOptions, } from './model';
5
5
  export { BlockMsg, Tooltip, default as BaseLinearDisplayComponent, } from './components/BaseLinearDisplay';
6
6
  export { default as TrackHeightMixin } from './models/TrackHeightMixin';
7
7
  export { default as FeatureDensityMixin } from './models/FeatureDensityMixin';
@@ -1,5 +1,5 @@
1
1
  export { default as baseLinearDisplayConfigSchema } from './models/configSchema';
2
- export { BaseLinearDisplay } from './models/BaseLinearDisplayModel';
2
+ export { BaseLinearDisplay } from './model';
3
3
  export { BlockMsg, Tooltip, default as BaseLinearDisplayComponent, } from './components/BaseLinearDisplay';
4
4
  export { default as TrackHeightMixin } from './models/TrackHeightMixin';
5
5
  export { default as FeatureDensityMixin } from './models/FeatureDensityMixin';
@@ -1,6 +1,6 @@
1
1
  import type React from 'react';
2
2
  import CompositeMap from '@jbrowse/core/util/compositeMap';
3
- import type { ExportSvgOptions } from '../../LinearGenomeView/types';
3
+ import type { ExportSvgOptions } from '../LinearGenomeView/types';
4
4
  import type { MenuItem } from '@jbrowse/core/ui';
5
5
  import type { AnyReactComponentType, Feature } from '@jbrowse/core/util';
6
6
  import type { BaseBlock } from '@jbrowse/core/util/blockTypes';
@@ -13,7 +13,17 @@ export interface Layout {
13
13
  maxY: number;
14
14
  name: string;
15
15
  }
16
- type LayoutRecord = [number, number, number, number];
16
+ type LayoutRecord = [number, number, number, number] | [
17
+ number,
18
+ number,
19
+ number,
20
+ number,
21
+ {
22
+ label?: string;
23
+ description?: string;
24
+ refName: string;
25
+ }
26
+ ];
17
27
  export interface ExportSvgDisplayOptions extends ExportSvgOptions {
18
28
  overrideHeight: number;
19
29
  theme: ThemeOptions;
@@ -61,7 +71,7 @@ export declare const BaseLinearDisplay: import("mobx-state-tree").IModelType<{
61
71
  setStatus(message: string): void;
62
72
  setLoading(newStopToken: string): void;
63
73
  setMessage(messageText: string): void;
64
- setRendered(props: import("./serverSideRenderedBlock").RenderedProps | undefined): void;
74
+ setRendered(props: import("./models/serverSideRenderedBlock").RenderedProps | undefined): void;
65
75
  setError(error: unknown): void;
66
76
  reload(): void;
67
77
  beforeDestroy(): void;
@@ -187,6 +197,7 @@ export declare const BaseLinearDisplay: import("mobx-state-tree").IModelType<{
187
197
  regionCannotBeRenderedText(_region: import("@jbrowse/core/util").Region): "" | "Force load to see features";
188
198
  regionCannotBeRendered(_region: import("@jbrowse/core/util").Region): import("react/jsx-runtime").JSX.Element | null;
189
199
  } & {
200
+ mouseoverExtraInformation: string | undefined;
190
201
  featureIdUnderMouse: undefined | string;
191
202
  contextMenuFeature: undefined | Feature;
192
203
  } & {
@@ -201,6 +212,7 @@ export declare const BaseLinearDisplay: import("mobx-state-tree").IModelType<{
201
212
  } & {
202
213
  readonly features: CompositeMap<string, Feature>;
203
214
  readonly featureUnderMouse: Feature | undefined;
215
+ readonly layoutFeatures: CompositeMap<string, LayoutRecord>;
204
216
  getFeatureOverlapping(blockKey: string, x: number, y: number): string | undefined;
205
217
  getFeatureByID(blockKey: string, id: string): LayoutRecord | undefined;
206
218
  searchFeatureByID(id: string): LayoutRecord | undefined;
@@ -212,6 +224,7 @@ export declare const BaseLinearDisplay: import("mobx-state-tree").IModelType<{
212
224
  clearFeatureSelection(): void;
213
225
  setFeatureIdUnderMouse(feature?: string): void;
214
226
  setContextMenuFeature(feature?: Feature): void;
227
+ setMouseoverExtraInformation(extra?: string): void;
215
228
  } & {
216
229
  reload(): Promise<void>;
217
230
  } & {
@@ -264,7 +277,7 @@ export declare const BaseLinearDisplay: import("mobx-state-tree").IModelType<{
264
277
  setStatus(message: string): void;
265
278
  setLoading(newStopToken: string): void;
266
279
  setMessage(messageText: string): void;
267
- setRendered(props: import("./serverSideRenderedBlock").RenderedProps | undefined): void;
280
+ setRendered(props: import("./models/serverSideRenderedBlock").RenderedProps | undefined): void;
268
281
  setError(error: unknown): void;
269
282
  reload(): void;
270
283
  beforeDestroy(): void;
@@ -10,11 +10,11 @@ import MenuOpenIcon from '@mui/icons-material/MenuOpen';
10
10
  import copy from 'copy-to-clipboard';
11
11
  import { autorun } from 'mobx';
12
12
  import { addDisposer, isAlive, types } from 'mobx-state-tree';
13
- import FeatureDensityMixin from './FeatureDensityMixin';
14
- import TrackHeightMixin from './TrackHeightMixin';
15
- import configSchema from './configSchema';
16
- import BlockState from './serverSideRenderedBlock';
17
- const Tooltip = lazy(() => import('../components/Tooltip'));
13
+ import FeatureDensityMixin from './models/FeatureDensityMixin';
14
+ import TrackHeightMixin from './models/TrackHeightMixin';
15
+ import configSchema from './models/configSchema';
16
+ import BlockState from './models/serverSideRenderedBlock';
17
+ const Tooltip = lazy(() => import('./components/Tooltip'));
18
18
  function stateModelFactory() {
19
19
  return types
20
20
  .compose('BaseLinearDisplay', BaseDisplay, TrackHeightMixin(), FeatureDensityMixin(), types.model({
@@ -22,6 +22,7 @@ function stateModelFactory() {
22
22
  configuration: ConfigurationReference(configSchema),
23
23
  }))
24
24
  .volatile(() => ({
25
+ mouseoverExtraInformation: undefined,
25
26
  featureIdUnderMouse: undefined,
26
27
  contextMenuFeature: undefined,
27
28
  }))
@@ -77,6 +78,15 @@ function stateModelFactory() {
77
78
  const feat = self.featureIdUnderMouse;
78
79
  return feat ? this.features.get(feat) : undefined;
79
80
  },
81
+ get layoutFeatures() {
82
+ const featureMaps = [];
83
+ for (const block of self.blockState.values()) {
84
+ if (block.layout) {
85
+ featureMaps.push(block.layout.rectangles);
86
+ }
87
+ }
88
+ return new CompositeMap(featureMaps);
89
+ },
80
90
  getFeatureOverlapping(blockKey, x, y) {
81
91
  var _a, _b;
82
92
  return (_b = (_a = self.blockState.get(blockKey)) === null || _a === void 0 ? void 0 : _a.layout) === null || _b === void 0 ? void 0 : _b.getByCoord(x, y);
@@ -154,6 +164,9 @@ function stateModelFactory() {
154
164
  setContextMenuFeature(feature) {
155
165
  self.contextMenuFeature = feature;
156
166
  },
167
+ setMouseoverExtraInformation(extra) {
168
+ self.mouseoverExtraInformation = extra;
169
+ },
157
170
  }))
158
171
  .actions(self => {
159
172
  const { reload: superReload } = self;
@@ -231,11 +244,13 @@ function stateModelFactory() {
231
244
  self.setContextMenuFeature(self.features.get(f));
232
245
  }
233
246
  },
234
- onMouseMove(_, featureId) {
247
+ onMouseMove(_, featureId, extra) {
235
248
  self.setFeatureIdUnderMouse(featureId);
249
+ self.setMouseoverExtraInformation(extra);
236
250
  },
237
251
  onMouseLeave(_) {
238
252
  self.setFeatureIdUnderMouse(undefined);
253
+ self.setMouseoverExtraInformation(undefined);
239
254
  },
240
255
  onContextMenu() {
241
256
  self.setContextMenuFeature(undefined);
@@ -246,7 +261,7 @@ function stateModelFactory() {
246
261
  }))
247
262
  .actions(self => ({
248
263
  async renderSvg(opts) {
249
- const { renderBaseLinearDisplaySvg } = await import('./renderSvg');
264
+ const { renderBaseLinearDisplaySvg } = await import('./models/renderSvg');
250
265
  return renderBaseLinearDisplaySvg(self, opts);
251
266
  },
252
267
  afterAttach() {
@@ -1,2 +1,2 @@
1
- import type { BaseLinearDisplayModel } from './BaseLinearDisplayModel';
1
+ import type { BaseLinearDisplayModel } from '../model';
2
2
  export default function autorunFeatureDensityStats(self: BaseLinearDisplayModel): Promise<void>;
@@ -19,8 +19,8 @@ const baseLinearDisplayConfigSchema = ConfigurationSchema('BaseLinearDisplay', {
19
19
  mouseover: {
20
20
  type: 'string',
21
21
  description: 'text to display when the cursor hovers over a feature',
22
- defaultValue: `jexl:get(feature,'name')`,
23
- contextVariable: ['feature'],
22
+ defaultValue: `jexl:join('<br/>',get(feature,'_mouseOver')||get(feature,'name')||get(feature,'id'),mouseoverExtraInformation||'')`,
23
+ contextVariable: ['feature', 'mouseoverExtraInformation'],
24
24
  },
25
25
  jexlFilters: {
26
26
  type: 'stringArray',
@@ -1,5 +1,5 @@
1
- import type { BaseLinearDisplayModel } from './BaseLinearDisplayModel';
2
1
  import type { ExportSvgOptions } from '../../LinearGenomeView/types';
2
+ import type { BaseLinearDisplayModel } from '../model';
3
3
  import type { ThemeOptions } from '@mui/material';
4
4
  export declare function renderBaseLinearDisplaySvg(self: BaseLinearDisplayModel, opts: ExportSvgOptions & {
5
5
  overrideHeight: number;
@@ -171,6 +171,7 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
171
171
  regionCannotBeRenderedText(_region: import("@jbrowse/core/util").Region): "" | "Force load to see features";
172
172
  regionCannotBeRendered(_region: import("@jbrowse/core/util").Region): import("react/jsx-runtime").JSX.Element | null;
173
173
  } & {
174
+ mouseoverExtraInformation: string | undefined;
174
175
  featureIdUnderMouse: undefined | string;
175
176
  contextMenuFeature: undefined | import("@jbrowse/core/util").Feature;
176
177
  } & {
@@ -185,9 +186,22 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
185
186
  } & {
186
187
  readonly features: import("@jbrowse/core/util/compositeMap").default<string, import("@jbrowse/core/util").Feature>;
187
188
  readonly featureUnderMouse: import("@jbrowse/core/util").Feature | undefined;
189
+ readonly layoutFeatures: import("@jbrowse/core/util/compositeMap").default<string, [number, number, number, number] | [number, number, number, number, {
190
+ label?: string;
191
+ description?: string;
192
+ refName: string;
193
+ }]>;
188
194
  getFeatureOverlapping(blockKey: string, x: number, y: number): string | undefined;
189
- getFeatureByID(blockKey: string, id: string): [number, number, number, number] | undefined;
190
- searchFeatureByID(id: string): [number, number, number, number] | undefined;
195
+ getFeatureByID(blockKey: string, id: string): ([number, number, number, number] | [number, number, number, number, {
196
+ label?: string;
197
+ description?: string;
198
+ refName: string;
199
+ }]) | undefined;
200
+ searchFeatureByID(id: string): ([number, number, number, number] | [number, number, number, number, {
201
+ label?: string;
202
+ description?: string;
203
+ refName: string;
204
+ }]) | undefined;
191
205
  } & {
192
206
  addBlock(key: string, block: import("@jbrowse/core/util/blockTypes").BaseBlock): void;
193
207
  deleteBlock(key: string): void;
@@ -196,6 +210,7 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
196
210
  clearFeatureSelection(): void;
197
211
  setFeatureIdUnderMouse(feature?: string): void;
198
212
  setContextMenuFeature(feature?: import("@jbrowse/core/util").Feature): void;
213
+ setMouseoverExtraInformation(extra?: string): void;
199
214
  } & {
200
215
  reload(): Promise<void>;
201
216
  } & {
@@ -179,6 +179,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
179
179
  regionCannotBeRenderedText(_region: import("@jbrowse/core/util").Region): "" | "Force load to see features";
180
180
  regionCannotBeRendered(_region: import("@jbrowse/core/util").Region): import("react/jsx-runtime").JSX.Element | null;
181
181
  } & {
182
+ mouseoverExtraInformation: string | undefined;
182
183
  featureIdUnderMouse: undefined | string;
183
184
  contextMenuFeature: undefined | import("@jbrowse/core/util").Feature;
184
185
  } & {
@@ -193,9 +194,22 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
193
194
  } & {
194
195
  readonly features: import("@jbrowse/core/util/compositeMap").default<string, import("@jbrowse/core/util").Feature>;
195
196
  readonly featureUnderMouse: import("@jbrowse/core/util").Feature | undefined;
197
+ readonly layoutFeatures: import("@jbrowse/core/util/compositeMap").default<string, [number, number, number, number] | [number, number, number, number, {
198
+ label?: string;
199
+ description?: string;
200
+ refName: string;
201
+ }]>;
196
202
  getFeatureOverlapping(blockKey: string, x: number, y: number): string | undefined;
197
- getFeatureByID(blockKey: string, id: string): [number, number, number, number] | undefined;
198
- searchFeatureByID(id: string): [number, number, number, number] | undefined;
203
+ getFeatureByID(blockKey: string, id: string): ([number, number, number, number] | [number, number, number, number, {
204
+ label?: string;
205
+ description?: string;
206
+ refName: string;
207
+ }]) | undefined;
208
+ searchFeatureByID(id: string): ([number, number, number, number] | [number, number, number, number, {
209
+ label?: string;
210
+ description?: string;
211
+ refName: string;
212
+ }]) | undefined;
199
213
  } & {
200
214
  addBlock(key: string, block: import("@jbrowse/core/util/blockTypes").BaseBlock): void;
201
215
  deleteBlock(key: string): void;
@@ -204,6 +218,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
204
218
  clearFeatureSelection(): void;
205
219
  setFeatureIdUnderMouse(feature?: string): void;
206
220
  setContextMenuFeature(feature?: import("@jbrowse/core/util").Feature): void;
221
+ setMouseoverExtraInformation(extra?: string): void;
207
222
  } & {
208
223
  reload(): Promise<void>;
209
224
  } & {