@jbrowse/plugin-linear-genome-view 2.11.1 → 2.12.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 (53) hide show
  1. package/dist/BaseLinearDisplay/components/LinearBlocks.js +7 -7
  2. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +17 -1
  3. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +21 -0
  4. package/dist/BaseLinearDisplay/models/configSchema.d.ts +10 -0
  5. package/dist/BaseLinearDisplay/models/configSchema.js +15 -3
  6. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js +1 -0
  7. package/dist/LinearBareDisplay/configSchema.d.ts +5 -0
  8. package/dist/LinearBareDisplay/model.d.ts +17 -2
  9. package/dist/LinearBasicDisplay/components/AddFiltersDialog.d.ts +10 -0
  10. package/dist/LinearBasicDisplay/components/AddFiltersDialog.js +94 -0
  11. package/dist/LinearBasicDisplay/components/{SetMaxHeight.js → SetMaxHeightDialog.js} +7 -7
  12. package/dist/LinearBasicDisplay/configSchema.d.ts +5 -0
  13. package/dist/LinearBasicDisplay/model.d.ts +56 -21
  14. package/dist/LinearBasicDisplay/model.js +36 -5
  15. package/dist/LinearGenomeView/components/Gridlines.js +3 -4
  16. package/dist/LinearGenomeView/components/Highlight.js +20 -21
  17. package/dist/LinearGenomeView/components/OverviewScalebar.js +1 -2
  18. package/dist/LinearGenomeView/components/Scalebar.js +4 -5
  19. package/dist/LinearGenomeView/components/TrackLabel.js +4 -4
  20. package/dist/LinearGenomeView/components/TrackRenderingContainer.js +10 -5
  21. package/dist/LinearGenomeView/components/hooks.d.ts +2 -2
  22. package/dist/LinearGenomeView/components/hooks.js +8 -13
  23. package/dist/LinearGenomeView/model.d.ts +5 -22
  24. package/dist/LinearGenomeView/model.js +2 -2
  25. package/dist/index.d.ts +60 -129
  26. package/esm/BaseLinearDisplay/components/LinearBlocks.js +7 -7
  27. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +17 -1
  28. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +21 -0
  29. package/esm/BaseLinearDisplay/models/configSchema.d.ts +10 -0
  30. package/esm/BaseLinearDisplay/models/configSchema.js +15 -3
  31. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +1 -0
  32. package/esm/LinearBareDisplay/configSchema.d.ts +5 -0
  33. package/esm/LinearBareDisplay/model.d.ts +17 -2
  34. package/esm/LinearBasicDisplay/components/AddFiltersDialog.d.ts +10 -0
  35. package/esm/LinearBasicDisplay/components/AddFiltersDialog.js +69 -0
  36. package/esm/LinearBasicDisplay/components/{SetMaxHeight.js → SetMaxHeightDialog.js} +7 -7
  37. package/esm/LinearBasicDisplay/configSchema.d.ts +5 -0
  38. package/esm/LinearBasicDisplay/model.d.ts +56 -21
  39. package/esm/LinearBasicDisplay/model.js +37 -6
  40. package/esm/LinearGenomeView/components/Gridlines.js +3 -4
  41. package/esm/LinearGenomeView/components/Highlight.js +20 -21
  42. package/esm/LinearGenomeView/components/OverviewScalebar.js +1 -2
  43. package/esm/LinearGenomeView/components/Scalebar.js +4 -5
  44. package/esm/LinearGenomeView/components/TrackLabel.js +4 -4
  45. package/esm/LinearGenomeView/components/TrackRenderingContainer.js +10 -5
  46. package/esm/LinearGenomeView/components/hooks.d.ts +2 -2
  47. package/esm/LinearGenomeView/components/hooks.js +8 -10
  48. package/esm/LinearGenomeView/model.d.ts +5 -22
  49. package/esm/LinearGenomeView/model.js +3 -3
  50. package/esm/index.d.ts +60 -129
  51. package/package.json +2 -4
  52. /package/dist/LinearBasicDisplay/components/{SetMaxHeight.d.ts → SetMaxHeightDialog.d.ts} +0 -0
  53. /package/esm/LinearBasicDisplay/components/{SetMaxHeight.d.ts → SetMaxHeightDialog.d.ts} +0 -0
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
- const blockTypes_1 = require("@jbrowse/core/util/blockTypes");
8
7
  const mui_1 = require("tss-react/mui");
9
8
  const mobx_react_1 = require("mobx-react");
10
9
  const Block_1 = require("../../BaseLinearDisplay/components/Block");
@@ -50,13 +49,13 @@ const RenderedVerticalGuides = (0, mobx_react_1.observer)(({ model }) => {
50
49
  const { staticBlocks, bpPerPx } = model;
51
50
  return (react_1.default.createElement(react_1.default.Fragment, null, staticBlocks.map((block, index) => {
52
51
  const k = `${block.key}-${index}`;
53
- if (block instanceof blockTypes_1.ContentBlock) {
52
+ if (block.type === 'ContentBlock') {
54
53
  return react_1.default.createElement(RenderedBlockLines, { key: k, block: block, bpPerPx: bpPerPx });
55
54
  }
56
- else if (block instanceof blockTypes_1.ElidedBlock) {
55
+ else if (block.type === 'ElidedBlock') {
57
56
  return react_1.default.createElement(Block_1.ElidedBlock, { key: k, width: block.widthPx });
58
57
  }
59
- else if (block instanceof blockTypes_1.InterRegionPaddingBlock) {
58
+ else if (block.type === 'InterRegionPaddingBlock') {
60
59
  return (react_1.default.createElement(Block_1.InterRegionPaddingBlock, { key: k, width: block.widthPx, boundary: block.variant === 'boundary' }));
61
60
  }
62
61
  return null;
@@ -61,26 +61,6 @@ const Highlight = (0, mobx_react_1.observer)(function Highlight({ model, highlig
61
61
  const dismissHighlight = () => {
62
62
  model.removeHighlight(highlight);
63
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
64
  function handleClose() {
85
65
  setOpen(false);
86
66
  }
@@ -118,7 +98,26 @@ const Highlight = (0, mobx_react_1.observer)(function Highlight({ model, highlig
118
98
  react_1.default.createElement(ui_1.Menu, { anchorEl: anchorEl.current, onMenuItemClick: (_event, callback) => {
119
99
  callback(session);
120
100
  handleClose();
121
- }, open: open, onClose: handleClose, menuItems: menuItems }))) : null;
101
+ }, open: open, onClose: handleClose, menuItems: [
102
+ {
103
+ label: 'Dismiss highlight',
104
+ icon: Close_1.default,
105
+ onClick: () => dismissHighlight(),
106
+ },
107
+ {
108
+ label: 'Bookmark highlighted region',
109
+ icon: Bookmark_1.default,
110
+ onClick: () => {
111
+ let bookmarkWidget = session.widgets.get('GridBookmark');
112
+ if (!bookmarkWidget) {
113
+ bookmarkWidget = session.addWidget('GridBookmarkWidget', 'GridBookmark');
114
+ }
115
+ // @ts-ignore
116
+ bookmarkWidget.addBookmark(highlight);
117
+ dismissHighlight();
118
+ },
119
+ },
120
+ ] }))) : null;
122
121
  });
123
122
  const HighlightGroup = (0, mobx_react_1.observer)(function HighlightGroup({ model, }) {
124
123
  return model.highlight.map((highlight, idx) => (react_1.default.createElement(Highlight, { key: JSON.stringify(highlight) + '-' + idx, model: model, highlight: highlight })));
@@ -33,7 +33,6 @@ const mobx_react_1 = require("mobx-react");
33
33
  // core
34
34
  const Base1DViewModel_1 = __importDefault(require("@jbrowse/core/util/Base1DViewModel"));
35
35
  const util_1 = require("@jbrowse/core/util");
36
- const blockTypes_1 = require("@jbrowse/core/util/blockTypes");
37
36
  // locals
38
37
  const __1 = require("..");
39
38
  const util_2 = require("../util");
@@ -176,7 +175,7 @@ const Scalebar = (0, mobx_react_1.observer)(function ({ model, scale, overview,
176
175
  borderColor: color,
177
176
  } }),
178
177
  overviewVisibleRegions.map((block, idx) => {
179
- return !(block instanceof blockTypes_1.ContentBlock) ? (react_1.default.createElement("div", { key: `${JSON.stringify(block)}-${idx}`, className: classes.scalebarContig, style: {
178
+ return !(block.type === 'ContentBlock') ? (react_1.default.createElement("div", { key: `${JSON.stringify(block)}-${idx}`, className: classes.scalebarContig, style: {
180
179
  width: block.widthPx,
181
180
  left: block.offsetPx,
182
181
  backgroundColor: '#999',
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const material_1 = require("@mui/material");
7
7
  const mui_1 = require("tss-react/mui");
8
- const blockTypes_1 = require("@jbrowse/core/util/blockTypes");
9
8
  const mobx_react_1 = require("mobx-react");
10
9
  const react_1 = __importDefault(require("react"));
11
10
  const Block_1 = require("../../BaseLinearDisplay/components/Block");
@@ -61,7 +60,7 @@ const RenderedRefNameLabels = (0, mobx_react_1.observer)(({ model }) => {
61
60
  }
62
61
  });
63
62
  return (react_1.default.createElement(react_1.default.Fragment, null, model.staticBlocks.map((block, index) => {
64
- return block instanceof blockTypes_1.ContentBlock &&
63
+ return block.type === 'ContentBlock' &&
65
64
  (block.isLeftEndOfDisplayedRegion || index === lastLeftBlock) ? (react_1.default.createElement(material_1.Typography, { key: `refLabel-${block.key}-${index}`, style: {
66
65
  left: index === lastLeftBlock
67
66
  ? Math.max(0, -model.offsetPx)
@@ -88,13 +87,13 @@ const RenderedScalebarLabels = (0, mobx_react_1.observer)(({ model }) => {
88
87
  return (react_1.default.createElement(react_1.default.Fragment, null, staticBlocks.map((block, idx) => {
89
88
  const { key, widthPx } = block;
90
89
  const k = `${key}-${idx}`;
91
- if (block instanceof blockTypes_1.ContentBlock) {
90
+ if (block.type === 'ContentBlock') {
92
91
  return react_1.default.createElement(RenderedBlockTicks, { key: k, block: block, bpPerPx: bpPerPx });
93
92
  }
94
- else if (block instanceof blockTypes_1.ElidedBlock) {
93
+ else if (block.type === 'ElidedBlock') {
95
94
  return react_1.default.createElement(Block_1.ElidedBlock, { key: k, width: widthPx });
96
95
  }
97
- else if (block instanceof blockTypes_1.InterRegionPaddingBlock) {
96
+ else if (block.type === 'InterRegionPaddingBlock') {
98
97
  return (react_1.default.createElement(Block_1.InterRegionPaddingBlock, { key: k, width: widthPx, style: { background: 'none' }, boundary: block.variant === 'boundary' }));
99
98
  }
100
99
  return null;
@@ -30,10 +30,7 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
30
30
  },
31
31
  },
32
32
  trackName: {
33
- margin: '0 auto',
34
- width: '90%',
35
33
  fontSize: '0.8rem',
36
- pointerEvents: 'none',
37
34
  },
38
35
  iconButton: {
39
36
  padding: theme.spacing(1),
@@ -87,7 +84,10 @@ const TrackLabel = (0, mobx_react_1.observer)(react_1.default.forwardRef(functio
87
84
  react_1.default.createElement(TrackLabelDragHandle_1.default, { track: track, trackId: trackId, view: view }),
88
85
  react_1.default.createElement(material_1.IconButton, { onClick: () => view.hideTrack(trackId), className: classes.iconButton, title: "close this track" },
89
86
  react_1.default.createElement(Close_1.default, { fontSize: "small" })),
90
- react_1.default.createElement(material_1.Typography, { variant: "body1", component: "span", className: classes.trackName },
87
+ react_1.default.createElement(material_1.Typography, { variant: "body1", component: "span", className: classes.trackName, onMouseDown: event => {
88
+ // avoid becoming a click-and-drag action on the lgv
89
+ event.stopPropagation();
90
+ } },
91
91
  react_1.default.createElement(ui_1.SanitizedHTML, { html: [trackName, minimized ? '(minimized)' : '']
92
92
  .filter(f => !!f)
93
93
  .join(' ') })),
@@ -51,19 +51,24 @@ const TrackRenderingContainer = (0, mobx_react_1.observer)(function ({ model, tr
51
51
  const { classes } = useStyles();
52
52
  const display = track.displays[0];
53
53
  const { height, RenderingComponent, DisplayBlurb } = display;
54
+ const { trackRefs, id, scaleFactor } = model;
54
55
  const trackId = (0, configuration_1.getConf)(track, 'trackId');
55
56
  const ref = (0, react_1.useRef)(null);
56
57
  const minimized = track.minimized;
57
58
  (0, react_1.useEffect)(() => {
58
59
  if (ref.current) {
59
- model.trackRefs[trackId] = ref.current;
60
+ trackRefs[trackId] = ref.current;
60
61
  }
61
62
  return () => {
62
- delete model.trackRefs[trackId];
63
+ delete trackRefs[trackId];
63
64
  };
64
- }, [model.trackRefs, trackId]);
65
- return (react_1.default.createElement("div", { className: classes.trackRenderingContainer, style: { height: minimized ? 20 : height }, onScroll: evt => display.setScrollTop(evt.currentTarget.scrollTop), onDragEnter: onDragEnter, "data-testid": `trackRenderingContainer-${model.id}-${trackId}` }, !minimized ? (react_1.default.createElement(react_1.default.Fragment, null,
66
- react_1.default.createElement("div", { ref: ref, className: classes.renderingComponentContainer, style: { transform: `scaleX(${model.scaleFactor})` } },
65
+ }, [trackRefs, trackId]);
66
+ return (react_1.default.createElement("div", { className: classes.trackRenderingContainer, style: {
67
+ height: minimized ? 20 : height,
68
+ }, onScroll: evt => display.setScrollTop(evt.currentTarget.scrollTop), onDragEnter: onDragEnter, "data-testid": `trackRenderingContainer-${id}-${trackId}` }, !minimized ? (react_1.default.createElement(react_1.default.Fragment, null,
69
+ react_1.default.createElement("div", { ref: ref, className: classes.renderingComponentContainer, style: {
70
+ transform: scaleFactor !== 1 ? `scaleX(${scaleFactor})` : undefined,
71
+ } },
67
72
  react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(ui_1.LoadingEllipses, null) },
68
73
  react_1.default.createElement(RenderingComponent, { model: display, onHorizontalScroll: model.horizontalScroll }))),
69
74
  DisplayBlurb ? (react_1.default.createElement("div", { style: {
@@ -42,7 +42,7 @@ export declare function useRangeSelect(ref: React.RefObject<HTMLDivElement>, mod
42
42
  offset: number;
43
43
  start: number;
44
44
  end: number;
45
- reversed: boolean;
45
+ reversed?: boolean | undefined;
46
46
  };
47
47
  rightBpOffset: {
48
48
  coord: number;
@@ -53,7 +53,7 @@ export declare function useRangeSelect(ref: React.RefObject<HTMLDivElement>, mod
53
53
  offset: number;
54
54
  start: number;
55
55
  end: number;
56
- reversed: boolean;
56
+ reversed?: boolean | undefined;
57
57
  };
58
58
  anchorPosition: AnchorPosition | undefined;
59
59
  numOfBpSelected: number;
@@ -1,11 +1,7 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.useWheelScroll = exports.useRangeSelect = exports.useSideScroll = void 0;
7
4
  const react_1 = require("react");
8
- const normalize_wheel_1 = __importDefault(require("normalize-wheel"));
9
5
  const util_1 = require("./util");
10
6
  function useSideScroll(model) {
11
7
  const [mouseDragging, setMouseDragging] = (0, react_1.useState)(false);
@@ -214,11 +210,10 @@ function useWheelScroll(ref, model) {
214
210
  const curr = ref.current;
215
211
  // if ctrl is held down, zoom in with y-scroll
216
212
  // else scroll horizontally with x-scroll
217
- function onWheel(origEvent) {
218
- const event = (0, normalize_wheel_1.default)(origEvent);
219
- if (origEvent.ctrlKey === true) {
220
- origEvent.preventDefault();
221
- delta.current += event.pixelY / 500;
213
+ function onWheel(event) {
214
+ if (event.ctrlKey === true) {
215
+ event.preventDefault();
216
+ delta.current += event.deltaY / 500;
222
217
  model.setScaleFactor(delta.current < 0 ? 1 - delta.current : 1 / (1 + delta.current));
223
218
  if (timeout.current) {
224
219
  clearTimeout(timeout.current);
@@ -227,7 +222,7 @@ function useWheelScroll(ref, model) {
227
222
  model.setScaleFactor(1);
228
223
  model.zoomTo(delta.current > 0
229
224
  ? model.bpPerPx * (1 + delta.current)
230
- : model.bpPerPx / (1 - delta.current), origEvent.clientX - ((curr === null || curr === void 0 ? void 0 : curr.getBoundingClientRect().left) || 0));
225
+ : model.bpPerPx / (1 - delta.current), event.clientX - ((curr === null || curr === void 0 ? void 0 : curr.getBoundingClientRect().left) || 0));
231
226
  delta.current = 0;
232
227
  }, 300);
233
228
  }
@@ -235,10 +230,10 @@ function useWheelScroll(ref, model) {
235
230
  // this is needed to stop the event from triggering "back button
236
231
  // action" on MacOSX etc. but is a heuristic to avoid preventing the
237
232
  // inner-track scroll behavior
238
- if (Math.abs(event.pixelX) > Math.abs(2 * event.pixelY)) {
239
- origEvent.preventDefault();
233
+ if (Math.abs(event.deltaX) > Math.abs(2 * event.deltaY)) {
234
+ event.preventDefault();
240
235
  }
241
- delta.current += event.pixelX;
236
+ delta.current += event.deltaX;
242
237
  if (!scheduled.current) {
243
238
  // use rAF to make it so multiple event handlers aren't fired per-frame
244
239
  // see https://calendar.perfplanet.com/2013/the-runtime-performance-checklist/
@@ -62,16 +62,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
62
62
  type: import("mobx-state-tree").IType<string | undefined, string, string>;
63
63
  offsetPx: import("mobx-state-tree").IType<number | undefined, number, number>;
64
64
  bpPerPx: import("mobx-state-tree").IType<number | undefined, number, number>;
65
- displayedRegions: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
66
- refName: import("mobx-state-tree").ISimpleType<string>;
67
- start: import("mobx-state-tree").ISimpleType<number>;
68
- end: import("mobx-state-tree").ISimpleType<number>;
69
- reversed: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
70
- } & {
71
- assemblyName: import("mobx-state-tree").ISimpleType<string>;
72
- }, {
73
- setRefName(newRefName: string): void;
74
- }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
65
+ displayedRegions: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IType<Region[], Region[], Region[]>, [undefined]>;
75
66
  tracks: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IAnyType>;
76
67
  hideHeader: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
77
68
  hideHeaderOverview: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
@@ -364,6 +355,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
364
355
  getSelectedRegions(leftOffset?: BpOffset, rightOffset?: BpOffset): {
365
356
  start: number;
366
357
  end: number;
358
+ type: string;
367
359
  regionNumber?: number | undefined;
368
360
  reversed?: boolean | undefined;
369
361
  refName: string;
@@ -584,7 +576,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
584
576
  offset: number;
585
577
  start: number;
586
578
  end: number;
587
- reversed: boolean;
579
+ reversed?: boolean | undefined;
588
580
  };
589
581
  /**
590
582
  * #getter
@@ -598,7 +590,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
598
590
  offset: number;
599
591
  start: number;
600
592
  end: number;
601
- reversed: boolean;
593
+ reversed?: boolean | undefined;
602
594
  } | undefined;
603
595
  } & {
604
596
  afterCreate(): void;
@@ -611,16 +603,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
611
603
  type: import("mobx-state-tree").IType<string | undefined, string, string>;
612
604
  offsetPx: import("mobx-state-tree").IType<number | undefined, number, number>;
613
605
  bpPerPx: import("mobx-state-tree").IType<number | undefined, number, number>;
614
- displayedRegions: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
615
- refName: import("mobx-state-tree").ISimpleType<string>;
616
- start: import("mobx-state-tree").ISimpleType<number>;
617
- end: import("mobx-state-tree").ISimpleType<number>;
618
- reversed: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
619
- } & {
620
- assemblyName: import("mobx-state-tree").ISimpleType<string>;
621
- }, {
622
- setRefName(newRefName: string): void;
623
- }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
606
+ displayedRegions: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IType<Region[], Region[], Region[]>, [undefined]>;
624
607
  tracks: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IAnyType>;
625
608
  hideHeader: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
626
609
  hideHeaderOverview: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
@@ -120,7 +120,7 @@ function stateModelFactory(pluginManager) {
120
120
  * advised to use the entire set of chromosomes if your assembly is very
121
121
  * fragmented
122
122
  */
123
- displayedRegions: mobx_state_tree_1.types.array(mst_1.Region),
123
+ displayedRegions: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.frozen(), []),
124
124
  /**
125
125
  * #property
126
126
  * array of currently displayed tracks state models instances
@@ -317,7 +317,7 @@ function stateModelFactory(pluginManager) {
317
317
  * #getter
318
318
  */
319
319
  get totalBp() {
320
- return self.displayedRegions.reduce((a, b) => a + b.end - b.start, 0);
320
+ return (0, util_1.sum)(self.displayedRegions.map(r => r.end - r.start));
321
321
  },
322
322
  /**
323
323
  * #getter