higlass 1.13.5 → 1.13.6

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 (131) hide show
  1. package/README.md +48 -54
  2. package/app/globals.d.ts +1 -1
  3. package/app/missing-types.d.ts +4 -1
  4. package/app/scripts/AddTrackDialog.jsx +3 -3
  5. package/app/scripts/AddTrackPositionMenu.jsx +2 -2
  6. package/app/scripts/Annotations1dTrack.js +1 -1
  7. package/app/scripts/Annotations2dTrack.js +3 -5
  8. package/app/scripts/Autocomplete.jsx +14 -21
  9. package/app/scripts/AxisPixi.js +6 -10
  10. package/app/scripts/BarTrack.js +3 -3
  11. package/app/scripts/BedLikeTrack.js +12 -13
  12. package/app/scripts/Button.jsx +1 -1
  13. package/app/scripts/CNVIntervalTrack.js +1 -1
  14. package/app/scripts/CenterTrack.jsx +8 -7
  15. package/app/scripts/Chromosome2DAnnotations.js +1 -1
  16. package/app/scripts/Chromosome2DLabels.js +1 -1
  17. package/app/scripts/ChromosomeGrid.js +49 -38
  18. package/app/scripts/ChromosomeInfo.js +1 -1
  19. package/app/scripts/CombinedTrack.js +3 -1
  20. package/app/scripts/ConfigTrackMenu.jsx +1 -1
  21. package/app/scripts/ConfigViewMenu.jsx +2 -2
  22. package/app/scripts/ContextMenuContainer.jsx +1 -2
  23. package/app/scripts/ContextMenuItem.jsx +1 -0
  24. package/app/scripts/CrossRule.js +1 -1
  25. package/app/scripts/CustomTrackDialog.jsx +2 -2
  26. package/app/scripts/Dialog.jsx +2 -2
  27. package/app/scripts/DragListeningDiv.jsx +1 -1
  28. package/app/scripts/DraggableDiv.jsx +2 -3
  29. package/app/scripts/ExportLinkDialog.jsx +1 -1
  30. package/app/scripts/GalleryTracks.jsx +77 -78
  31. package/app/scripts/GenomePositionSearchBox.jsx +10 -9
  32. package/app/scripts/HeatmapOptions.jsx +4 -2
  33. package/app/scripts/HeatmapTiledPixiTrack.js +23 -32
  34. package/app/scripts/HiGlassComponent.jsx +75 -98
  35. package/app/scripts/Horizontal1dHeatmapTrack.js +1 -1
  36. package/app/scripts/Horizontal2DDomainsTrack.js +1 -1
  37. package/app/scripts/HorizontalChromosomeLabels.js +28 -22
  38. package/app/scripts/HorizontalGeneAnnotationsTrack.js +1 -1
  39. package/app/scripts/HorizontalHeatmapTrack.js +2 -2
  40. package/app/scripts/HorizontalMultivecTrack.js +6 -7
  41. package/app/scripts/HorizontalRule.js +1 -2
  42. package/app/scripts/HorizontalTiled1DPixiTrack.js +4 -4
  43. package/app/scripts/HorizontalTiledPlot.jsx +9 -9
  44. package/app/scripts/LeftTrackModifier.js +4 -0
  45. package/app/scripts/ListWrapper.jsx +1 -2
  46. package/app/scripts/MapboxTilesTrack.js +1 -2
  47. package/app/scripts/Modal.jsx +2 -2
  48. package/app/scripts/MoveableTrack.jsx +10 -12
  49. package/app/scripts/NestedContextMenu.jsx +2 -1
  50. package/app/scripts/OSMTileIdsTrack.js +1 -1
  51. package/app/scripts/OverlayTrack.js +4 -4
  52. package/app/scripts/PixiTrack.js +27 -13
  53. package/app/scripts/PlotTypeChooser.jsx +3 -4
  54. package/app/scripts/SearchField.js +5 -5
  55. package/app/scripts/SeriesListItems.jsx +3 -4
  56. package/app/scripts/SeriesListMenu.jsx +6 -11
  57. package/app/scripts/SeriesListSubmenuMixin.jsx +1 -1
  58. package/app/scripts/SketchInlinePicker.jsx +2 -2
  59. package/app/scripts/SortableList.jsx +1 -1
  60. package/app/scripts/Tiled1DPixiTrack.js +5 -1
  61. package/app/scripts/TiledPixiTrack.js +232 -99
  62. package/app/scripts/TiledPlot.jsx +33 -43
  63. package/app/scripts/TilesetFinder.jsx +12 -4
  64. package/app/scripts/Track.js +1 -1
  65. package/app/scripts/TrackArea.jsx +4 -0
  66. package/app/scripts/TrackControl.jsx +2 -2
  67. package/app/scripts/TrackRenderer.jsx +30 -31
  68. package/app/scripts/ValueIntervalTrack.js +1 -1
  69. package/app/scripts/VerticalRule.js +2 -2
  70. package/app/scripts/VerticalTiledPlot.jsx +7 -7
  71. package/app/scripts/ViewConfigEditor.jsx +1 -1
  72. package/app/scripts/ViewContextMenu.jsx +4 -4
  73. package/app/scripts/ViewHeader.jsx +6 -7
  74. package/app/scripts/ViewportTracker2D.js +1 -1
  75. package/app/scripts/api.js +5 -6
  76. package/app/scripts/configs/available-track-types.js +1 -1
  77. package/app/scripts/configs/positions-by-datatype.js +2 -2
  78. package/app/scripts/configs/themes.js +0 -1
  79. package/app/scripts/configs/tracks-info-by-type.js +11 -8
  80. package/app/scripts/configs/tracks-info.js +2 -2
  81. package/app/scripts/d3-context-menu.js +3 -4
  82. package/app/scripts/data-fetchers/DataFetcher.js +35 -36
  83. package/app/scripts/data-fetchers/genbank-fetcher.js +6 -10
  84. package/app/scripts/data-fetchers/local-tile-fetcher.js +2 -6
  85. package/app/scripts/hglib.jsx +1 -1
  86. package/app/scripts/hocs/with-modal.jsx +32 -10
  87. package/app/scripts/hocs/with-pub-sub.js +12 -3
  88. package/app/scripts/hocs/with-theme.jsx +21 -14
  89. package/app/scripts/icons.jsx +3 -2
  90. package/app/scripts/mixwith.js +2 -2
  91. package/app/scripts/plugins/get-data-fetcher.js +2 -3
  92. package/app/scripts/services/chrom-info.js +32 -4
  93. package/app/scripts/services/element-resize-listener.js +2 -2
  94. package/app/scripts/services/index.js +0 -1
  95. package/app/scripts/services/tile-proxy.js +368 -281
  96. package/app/scripts/services/worker.js +30 -28
  97. package/app/scripts/test-helpers/test-helpers.jsx +3 -3
  98. package/app/scripts/types.ts +50 -44
  99. package/app/scripts/utils/LruCache.js +3 -2
  100. package/app/scripts/utils/assert.js +19 -0
  101. package/app/scripts/utils/background-task-scheduler.js +2 -0
  102. package/app/scripts/utils/color-domain-to-rgba-array.js +13 -3
  103. package/app/scripts/utils/dict-items.js +1 -0
  104. package/app/scripts/utils/dict-keys.js +1 -0
  105. package/app/scripts/utils/dict-values.js +1 -0
  106. package/app/scripts/utils/expand-combined-tracks.js +11 -7
  107. package/app/scripts/utils/fill-in-min-widths.js +47 -21
  108. package/app/scripts/utils/flatten.js +0 -1
  109. package/app/scripts/utils/get-aggregation-function.js +1 -1
  110. package/app/scripts/utils/get-default-track-for-datatype.js +36 -10
  111. package/app/scripts/utils/get-higlass-components.js +27 -3
  112. package/app/scripts/utils/get-track-position-by-uid.js +8 -1
  113. package/app/scripts/utils/get-xylofon.js +12 -9
  114. package/app/scripts/utils/has-parent.js +5 -5
  115. package/app/scripts/utils/hex-string-to-int.js +1 -1
  116. package/app/scripts/utils/interval-tree.js +222 -177
  117. package/app/scripts/utils/load-chrom-infos.js +4 -1
  118. package/app/scripts/utils/pixi-text-to-svg.js +5 -9
  119. package/app/scripts/utils/range-query-2d.js +3 -3
  120. package/app/scripts/utils/reduce.js +12 -5
  121. package/app/scripts/utils/segments-to-rows.js +14 -11
  122. package/app/scripts/utils/show-mouse-position.js +16 -0
  123. package/app/scripts/utils/svg-line.js +7 -8
  124. package/app/scripts/utils/type-guards.js +16 -7
  125. package/app/scripts/utils/visit-positioned-tracks.js +7 -5
  126. package/app/styles/d3-context-menu.css +0 -1
  127. package/app/styles/prism.css +1 -0
  128. package/dist/hglib.js +78064 -77770
  129. package/dist/hglib.min.js +109 -109
  130. package/dist/higlass.mjs +82736 -82442
  131. package/package.json +13 -18
@@ -1,41 +1,41 @@
1
1
  // @ts-nocheck
2
- import React from 'react';
3
- import PropTypes from 'prop-types';
4
- import { select, pointer } from 'd3-selection';
2
+ import clsx from 'clsx';
3
+ import { ElementQueries, ResizeSensor } from 'css-element-queries';
5
4
  import { scaleLinear } from 'd3-scale';
6
- import slugid from 'slugid';
5
+ import { pointer, select } from 'd3-selection';
7
6
  import * as PIXI from 'pixi.js';
7
+ import PropTypes from 'prop-types';
8
+ import createPubSub, { globalPubSub } from 'pub-sub-es';
9
+ import React from 'react';
8
10
  import ReactDOM from 'react-dom';
9
11
  import ReactGridLayout from 'react-grid-layout';
10
- import { ResizeSensor, ElementQueries } from 'css-element-queries';
11
- import vkbeautify from 'vkbeautify';
12
+ import slugid from 'slugid';
12
13
  import parse from 'url-parse';
13
- import createPubSub, { globalPubSub } from 'pub-sub-es';
14
- import clsx from 'clsx';
14
+ import vkbeautify from 'vkbeautify';
15
15
 
16
- import TiledPlot from './TiledPlot';
17
- import GenomePositionSearchBox from './GenomePositionSearchBox';
18
- import ExportLinkDialog from './ExportLinkDialog';
19
- import ViewHeader from './ViewHeader';
20
16
  import ChromosomeInfo from './ChromosomeInfo';
17
+ import ExportLinkDialog from './ExportLinkDialog';
18
+ import GenomePositionSearchBox from './GenomePositionSearchBox';
19
+ import TiledPlot from './TiledPlot';
21
20
  import ViewConfigEditor from './ViewConfigEditor';
21
+ import ViewHeader from './ViewHeader';
22
22
 
23
- import createSymbolIcon from './symbol';
24
- import { all as icons } from './icons';
25
23
  import createApi from './api';
24
+ import { all as icons } from './icons';
25
+ import createSymbolIcon from './symbol';
26
26
 
27
+ import { Provider as ModalProvider } from './hocs/with-modal';
27
28
  // Higher-order components
28
29
  import { Provider as PubSubProvider } from './hocs/with-pub-sub';
29
- import { Provider as ModalProvider } from './hocs/with-modal';
30
30
  import { Provider as ThemeProvider } from './hocs/with-theme';
31
31
 
32
32
  // Services
33
33
  import {
34
34
  chromInfo,
35
35
  createDomEvent,
36
+ requestsInFlight,
36
37
  setTileProxyAuthHeader,
37
38
  tileProxy,
38
- requestsInFlight,
39
39
  } from './services';
40
40
 
41
41
  // Utils
@@ -64,16 +64,16 @@ import {
64
64
 
65
65
  // Configs
66
66
  import {
67
- DEFAULT_SERVER,
68
67
  DEFAULT_CONTAINER_PADDING_X,
69
68
  DEFAULT_CONTAINER_PADDING_Y,
69
+ DEFAULT_SERVER,
70
70
  DEFAULT_VIEW_MARGIN,
71
71
  DEFAULT_VIEW_PADDING,
72
72
  GLOBALS,
73
- MOUSE_TOOL_MOVE,
74
- MOUSE_TOOL_SELECT,
75
73
  LOCATION_LISTENER_PREFIX,
76
74
  LONG_DRAG_TIMEOUT,
75
+ MOUSE_TOOL_MOVE,
76
+ MOUSE_TOOL_SELECT,
77
77
  SHORT_DRAG_TIMEOUT,
78
78
  THEME_DARK,
79
79
  THEME_LIGHT,
@@ -81,10 +81,10 @@ import {
81
81
  } from './configs';
82
82
 
83
83
  // Styles
84
- import styles from '../styles/HiGlass.module.scss'; // eslint-disable-line no-unused-vars
85
- import stylesMTHeader from '../styles/ViewHeader.module.scss'; // eslint-disable-line no-unused-vars
84
+ import styles from '../styles/HiGlass.module.scss';
85
+ import stylesMTHeader from '../styles/ViewHeader.module.scss';
86
86
 
87
- import '../styles/HiGlass.scss'; // eslint-disable-line no-unused-vars
87
+ import '../styles/HiGlass.scss';
88
88
 
89
89
  const NUM_GRID_COLUMNS = 12;
90
90
  const DEFAULT_NEW_VIEW_HEIGHT = 12;
@@ -116,6 +116,7 @@ class HiGlassComponent extends React.Component {
116
116
  this.resizeSensor = null;
117
117
 
118
118
  this.uid = slugid.nice();
119
+ /** @type {Record<string, import('./TiledPlot').TiledPlot> */
119
120
  this.tiledPlots = {};
120
121
  this.genomePositionSearchBoxes = {};
121
122
 
@@ -160,7 +161,7 @@ class HiGlassComponent extends React.Component {
160
161
 
161
162
  // allow a different PIXI to be passed in case the
162
163
  // caller wants to use a different version
163
- GLOBALS.PIXI = (props.options && props.options.PIXI) || PIXI;
164
+ GLOBALS.PIXI = props.options?.PIXI || PIXI;
164
165
 
165
166
  this.viewMarginTop =
166
167
  +props.options.viewMarginTop >= 0
@@ -292,7 +293,7 @@ class HiGlassComponent extends React.Component {
292
293
  mouseOverOverlayUid: null,
293
294
  mouseTool,
294
295
  isDarkTheme: false,
295
- rangeSelection1dSize: [0, Infinity],
296
+ rangeSelection1dSize: [0, Number.POSITIVE_INFINITY],
296
297
  rangeSelectionToInt: false,
297
298
  modal: null,
298
299
  };
@@ -370,7 +371,6 @@ class HiGlassComponent extends React.Component {
370
371
  );
371
372
  }
372
373
 
373
- // eslint-disable-next-line camelcase
374
374
  UNSAFE_componentWillMount() {
375
375
  this.domEvent.register('keydown', document);
376
376
  this.domEvent.register('keyup', document);
@@ -422,7 +422,6 @@ class HiGlassComponent extends React.Component {
422
422
  }
423
423
 
424
424
  get sizeMode() {
425
- // eslint-disable-next-line no-nested-ternary
426
425
  return typeof this.props.options.sizeMode === 'undefined'
427
426
  ? this.props.options.bounded
428
427
  ? 'bounded'
@@ -514,7 +513,7 @@ class HiGlassComponent extends React.Component {
514
513
  autoResize: true,
515
514
  };
516
515
 
517
- const versionNumber = parseInt(PIXI.VERSION[0], 10);
516
+ const versionNumber = Number.parseInt(PIXI.VERSION[0], 10);
518
517
 
519
518
  if (versionNumber === 4) {
520
519
  console.warn(
@@ -545,7 +544,7 @@ class HiGlassComponent extends React.Component {
545
544
 
546
545
  // keep track of the width and height of this element, because it
547
546
  // needs to be reflected in the size of our drawing surface
548
- // eslint-disable-next-line react/no-did-mount-set-state
547
+
549
548
  this.setState({
550
549
  svgElement: this.svgElement,
551
550
  canvasElement: this.canvasElement,
@@ -623,7 +622,6 @@ class HiGlassComponent extends React.Component {
623
622
  return views;
624
623
  }
625
624
 
626
- // eslint-disable-next-line camelcase
627
625
  UNSAFE_componentWillReceiveProps(newProps) {
628
626
  const viewsByUid = this.loadIfRemoteViewConfig(newProps.viewConfig);
629
627
 
@@ -655,7 +653,6 @@ class HiGlassComponent extends React.Component {
655
653
  });
656
654
  }
657
655
 
658
- // eslint-disable-next-line camelcase
659
656
  UNSAFE_componentWillUpdate() {
660
657
  // let width = this.element.clientWidth;
661
658
  // let height = this.element.clientHeight;
@@ -804,10 +801,7 @@ class HiGlassComponent extends React.Component {
804
801
  const trackOptions = track.options ? track.options : {};
805
802
 
806
803
  if (this.props.options.defaultTrackOptions) {
807
- if (
808
- this.props.options.defaultTrackOptions.trackSpecific &&
809
- this.props.options.defaultTrackOptions.trackSpecific[track.type]
810
- ) {
804
+ if (this.props.options.defaultTrackOptions.trackSpecific?.[track.type]) {
811
805
  // track specific options take precedence over all options
812
806
 
813
807
  const options =
@@ -834,11 +828,9 @@ class HiGlassComponent extends React.Component {
834
828
  }
835
829
 
836
830
  if (trackInfo.defaultOptions) {
837
- const defaultThemeOptions =
838
- trackInfo.defaultOptionsByTheme &&
839
- trackInfo.defaultOptionsByTheme[this.theme]
840
- ? trackInfo.defaultOptionsByTheme[this.theme]
841
- : {};
831
+ const defaultThemeOptions = trackInfo.defaultOptionsByTheme?.[this.theme]
832
+ ? trackInfo.defaultOptionsByTheme[this.theme]
833
+ : {};
842
834
 
843
835
  const defaultOptions = {
844
836
  ...trackInfo.defaultOptions,
@@ -1209,6 +1201,9 @@ class HiGlassComponent extends React.Component {
1209
1201
  )
1210
1202
  // filter out stale locks with non-existant tracks
1211
1203
  .filter((track) => track)
1204
+ // Filter out tracks that don't have values scales (e.g. chromosome tracks).
1205
+ // The .originalTrack check covers LeftTrackModifier style tracks.
1206
+ .filter((track) => track.valueScale || track.originalTrack?.valueScale)
1212
1207
  // if the track is a LeftTrackModifier we want the originalTrack
1213
1208
  .map((track) =>
1214
1209
  track.originalTrack === undefined ? track : track.originalTrack,
@@ -1234,14 +1229,16 @@ class HiGlassComponent extends React.Component {
1234
1229
 
1235
1230
  if (
1236
1231
  minValues.length === 0 ||
1237
- minValues.filter((x) => x === null || x === Infinity).length > 0
1232
+ minValues.filter((x) => x === null || x === Number.POSITIVE_INFINITY)
1233
+ .length > 0
1238
1234
  ) {
1239
1235
  return null; // Data hasn't loaded completely
1240
1236
  }
1241
1237
 
1242
1238
  if (
1243
1239
  maxValues.length === 0 ||
1244
- maxValues.filter((x) => x === null || x === -Infinity).length > 0
1240
+ maxValues.filter((x) => x === null || x === Number.NEGATIVE_INFINITY)
1241
+ .length > 0
1245
1242
  ) {
1246
1243
  return null; // Data hasn't loaded completely
1247
1244
  }
@@ -1395,7 +1392,7 @@ class HiGlassComponent extends React.Component {
1395
1392
  * Event handler is called with parameters (xScale, yScale)
1396
1393
  */
1397
1394
  addDraggingChangedListener(viewUid, listenerUid, eventHandler) {
1398
- if (!this.draggingChangedListeners.hasOwnProperty(viewUid)) {
1395
+ if (!(viewUid in this.draggingChangedListeners)) {
1399
1396
  this.draggingChangedListeners[viewUid] = {};
1400
1397
  }
1401
1398
 
@@ -1412,10 +1409,10 @@ class HiGlassComponent extends React.Component {
1412
1409
  * @param listenerUid: The uid of the listener itself.
1413
1410
  */
1414
1411
  removeDraggingChangedListener(viewUid, listenerUid) {
1415
- if (this.draggingChangedListeners.hasOwnProperty(viewUid)) {
1412
+ if (viewUid in this.draggingChangedListeners) {
1416
1413
  const listeners = this.draggingChangedListeners[viewUid];
1417
1414
 
1418
- if (listeners.hasOwnProperty(listenerUid)) {
1415
+ if (listenerUid in listeners) {
1419
1416
  // make sure the listener doesn't think we're still
1420
1417
  // dragging
1421
1418
  listeners[listenerUid](false);
@@ -1605,7 +1602,6 @@ class HiGlassComponent extends React.Component {
1605
1602
  const lockGroup = this.zoomLocks[uid];
1606
1603
  const lockGroupItems = dictItems(lockGroup);
1607
1604
 
1608
- // eslint-disable-next-line no-unused-vars
1609
1605
  const [centerX, centerY, k] = scalesCenterAndK(
1610
1606
  this.xScales[uid],
1611
1607
  this.yScales[uid],
@@ -1624,7 +1620,6 @@ class HiGlassComponent extends React.Component {
1624
1620
  continue;
1625
1621
  }
1626
1622
 
1627
- // eslint-disable-next-line no-unused-vars
1628
1623
  const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
1629
1624
  this.xScales[key],
1630
1625
  this.yScales[key],
@@ -1656,7 +1651,7 @@ class HiGlassComponent extends React.Component {
1656
1651
 
1657
1652
  // notify the listeners of all locked views that the scales of
1658
1653
  // this view have changed
1659
- if (this.scalesChangedListeners.hasOwnProperty(key)) {
1654
+ if (key in this.scalesChangedListeners) {
1660
1655
  dictValues(this.scalesChangedListeners[key]).forEach((x) => {
1661
1656
  x(newXScale, newYScale);
1662
1657
  });
@@ -1669,7 +1664,6 @@ class HiGlassComponent extends React.Component {
1669
1664
  const lockGroup = this.locationLocks[uid];
1670
1665
  const lockGroupItems = dictItems(lockGroup);
1671
1666
 
1672
- // eslint-disable-next-line no-unused-vars
1673
1667
  const [centerX, centerY, k] = scalesCenterAndK(
1674
1668
  this.xScales[uid],
1675
1669
  this.yScales[uid],
@@ -1683,7 +1677,6 @@ class HiGlassComponent extends React.Component {
1683
1677
  continue;
1684
1678
  }
1685
1679
 
1686
- // eslint-disable-next-line no-unused-vars
1687
1680
  const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
1688
1681
  this.xScales[key],
1689
1682
  this.yScales[key],
@@ -1718,7 +1711,7 @@ class HiGlassComponent extends React.Component {
1718
1711
 
1719
1712
  // notify the listeners of all locked views that the scales of
1720
1713
  // this view have changed
1721
- if (this.scalesChangedListeners.hasOwnProperty(key)) {
1714
+ if (key in this.scalesChangedListeners) {
1722
1715
  dictValues(this.scalesChangedListeners[key]).forEach((x) => {
1723
1716
  x(newXScale, newYScale);
1724
1717
  });
@@ -1734,7 +1727,6 @@ class HiGlassComponent extends React.Component {
1734
1727
  // this means the x axis of this view (uid) is locked to the y axis of another view
1735
1728
  const lockCrossAxis = this.locationLocksAxisWise.x[uid].axis !== 'x';
1736
1729
 
1737
- // eslint-disable-next-line no-unused-vars
1738
1730
  const [centerX, centerY, k] = scalesCenterAndK(
1739
1731
  this.xScales[uid],
1740
1732
  this.yScales[uid],
@@ -1748,7 +1740,6 @@ class HiGlassComponent extends React.Component {
1748
1740
  continue;
1749
1741
  }
1750
1742
 
1751
- // eslint-disable-next-line no-unused-vars
1752
1743
  const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
1753
1744
  this.xScales[key],
1754
1745
  this.yScales[key],
@@ -1781,7 +1772,7 @@ class HiGlassComponent extends React.Component {
1781
1772
 
1782
1773
  // notify the listeners of all locked views that the scales of
1783
1774
  // this view have changed
1784
- if (this.scalesChangedListeners.hasOwnProperty(key)) {
1775
+ if (key in this.scalesChangedListeners) {
1785
1776
  dictValues(this.scalesChangedListeners[key]).forEach((x) => {
1786
1777
  x(newXScale, newYScale);
1787
1778
  });
@@ -1797,7 +1788,6 @@ class HiGlassComponent extends React.Component {
1797
1788
  // this means the y axis of this view (uid) is locked to the x axis of another view
1798
1789
  const lockCrossAxis = this.locationLocksAxisWise.y[uid].axis !== 'y';
1799
1790
 
1800
- // eslint-disable-next-line no-unused-vars
1801
1791
  const [centerX, centerY, k] = scalesCenterAndK(
1802
1792
  this.xScales[uid],
1803
1793
  this.yScales[uid],
@@ -1811,7 +1801,6 @@ class HiGlassComponent extends React.Component {
1811
1801
  continue;
1812
1802
  }
1813
1803
 
1814
- // eslint-disable-next-line no-unused-vars
1815
1804
  const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
1816
1805
  this.xScales[key],
1817
1806
  this.yScales[key],
@@ -1844,7 +1833,7 @@ class HiGlassComponent extends React.Component {
1844
1833
 
1845
1834
  // notify the listeners of all locked views that the scales of
1846
1835
  // this view have changed
1847
- if (this.scalesChangedListeners.hasOwnProperty(key)) {
1836
+ if (key in this.scalesChangedListeners) {
1848
1837
  dictValues(this.scalesChangedListeners[key]).forEach((x) => {
1849
1838
  x(newXScale, newYScale);
1850
1839
  });
@@ -2125,12 +2114,11 @@ class HiGlassComponent extends React.Component {
2125
2114
  const targetXScale = this.xScales[uid1];
2126
2115
  const targetYScale = this.yScales[uid1];
2127
2116
 
2128
- // eslint-disable-next-line no-unused-vars
2129
2117
  const [targetCenterX, targetCenterY, targetK] = scalesCenterAndK(
2130
2118
  targetXScale,
2131
2119
  targetYScale,
2132
2120
  );
2133
- // eslint-disable-next-line no-unused-vars
2121
+
2134
2122
  const [sourceCenterX, sourceCenterY, sourceK] = scalesCenterAndK(
2135
2123
  sourceXScale,
2136
2124
  sourceYScale,
@@ -2155,12 +2143,11 @@ class HiGlassComponent extends React.Component {
2155
2143
  const targetXScale = this.xScales[uid1];
2156
2144
  const targetYScale = this.yScales[uid1];
2157
2145
 
2158
- // eslint-disable-next-line no-unused-vars
2159
2146
  const [targetCenterX, targetCenterY, targetK] = scalesCenterAndK(
2160
2147
  targetXScale,
2161
2148
  targetYScale,
2162
2149
  );
2163
- // eslint-disable-next-line no-unused-vars
2150
+
2164
2151
  const [sourceCenterX, sourceCenterY, sourceK] = scalesCenterAndK(
2165
2152
  sourceXScale,
2166
2153
  sourceYScale,
@@ -2299,11 +2286,11 @@ class HiGlassComponent extends React.Component {
2299
2286
  return TRACKS_INFO_BY_TYPE[trackType];
2300
2287
  }
2301
2288
 
2302
- if (this.pluginTracks && this.pluginTracks[trackType]) {
2289
+ if (this.pluginTracks?.[trackType]) {
2303
2290
  return this.pluginTracks[trackType].config;
2304
2291
  }
2305
2292
 
2306
- if (window.higlassTracksByType && window.higlassTracksByType[trackType]) {
2293
+ if (window.higlassTracksByType?.[trackType]) {
2307
2294
  return window.higlassTracksByType[trackType].config;
2308
2295
  }
2309
2296
 
@@ -2317,7 +2304,7 @@ class HiGlassComponent extends React.Component {
2317
2304
 
2318
2305
  forceRefreshView() {
2319
2306
  // force everything to rerender
2320
- this.setState(this.state); // eslint-disable-line react/no-access-state-in-setstate
2307
+ this.setState(this.state);
2321
2308
  }
2322
2309
 
2323
2310
  refreshView(timeout = SHORT_DRAG_TIMEOUT) {
@@ -2535,7 +2522,7 @@ class HiGlassComponent extends React.Component {
2535
2522
  }
2536
2523
 
2537
2524
  calculateZoomLimits(view, initialXDomain) {
2538
- const limits = [0, Infinity];
2525
+ const limits = [0, Number.POSITIVE_INFINITY];
2539
2526
 
2540
2527
  // By default, highest zoom resolution is 1bp
2541
2528
  const viewConfLimit = view.zoomLimits || [1, null];
@@ -2840,11 +2827,11 @@ class HiGlassComponent extends React.Component {
2840
2827
 
2841
2828
  newTrack.width =
2842
2829
  trackInfo.defaultWidth ||
2843
- (trackInfo.defaultOptions && trackInfo.defaultOptions.minWidth) ||
2830
+ trackInfo.defaultOptions?.minWidth ||
2844
2831
  this.minVerticalWidth;
2845
2832
  newTrack.height =
2846
2833
  trackInfo.defaultHeight ||
2847
- (trackInfo.defaultOptions && trackInfo.defaultOptions.minHeight) ||
2834
+ trackInfo.defaultOptions?.minHeight ||
2848
2835
  this.minHorizontalHeight;
2849
2836
 
2850
2837
  const { tracks } = this.state.views[viewId];
@@ -3203,7 +3190,7 @@ class HiGlassComponent extends React.Component {
3203
3190
  track.type === 'viewport-projection-center' ||
3204
3191
  track.type === 'viewport-projection-horizontal' ||
3205
3192
  track.type === 'viewport-projection-vertical' ||
3206
- (trackInfo && trackInfo.projection)
3193
+ trackInfo?.projection
3207
3194
  ) {
3208
3195
  const fromView = track.fromViewUid;
3209
3196
 
@@ -3399,7 +3386,7 @@ class HiGlassComponent extends React.Component {
3399
3386
  const locksByViewUid = {};
3400
3387
 
3401
3388
  for (const viewUid of dictKeys(locks)) {
3402
- let lockUid = locks[viewUid] && locks[viewUid].uid;
3389
+ let lockUid = locks[viewUid]?.uid;
3403
3390
 
3404
3391
  if (!lockUid) {
3405
3392
  // otherwise, assign this locationLock its own uid
@@ -3697,7 +3684,6 @@ class HiGlassComponent extends React.Component {
3697
3684
  });
3698
3685
 
3699
3686
  this.setState((prevState) => {
3700
- // eslint-disable-next-line no-shadow
3701
3687
  const views = JSON.parse(JSON.stringify(prevState.views));
3702
3688
  views[newView.uid] = newView;
3703
3689
  return { views };
@@ -4025,7 +4011,7 @@ class HiGlassComponent extends React.Component {
4025
4011
  'right',
4026
4012
  'bottom',
4027
4013
  ]) {
4028
- if (v.tracks && v.tracks.hasOwnProperty(trackOrientation)) {
4014
+ if (trackOrientation in (v.tracks ?? {})) {
4029
4015
  // filter out invalid tracks
4030
4016
  v.tracks[trackOrientation] = v.tracks[trackOrientation].filter((t) =>
4031
4017
  this.isTrackValid(t, viewUidsSet),
@@ -4355,7 +4341,10 @@ class HiGlassComponent extends React.Component {
4355
4341
  (listenerId) => listenerId.indexOf(LOCATION_LISTENER_PREFIX) === 0,
4356
4342
  )
4357
4343
  .map((listenerId) =>
4358
- parseInt(listenerId.slice(LOCATION_LISTENER_PREFIX.length + 1), 10),
4344
+ Number.parseInt(
4345
+ listenerId.slice(LOCATION_LISTENER_PREFIX.length + 1),
4346
+ 10,
4347
+ ),
4359
4348
  )
4360
4349
  .reduce((max, value) => Math.max(max, value), 0) + 1;
4361
4350
  }
@@ -4450,15 +4439,13 @@ class HiGlassComponent extends React.Component {
4450
4439
  const evt = {
4451
4440
  x: relPos[0],
4452
4441
  y: relPos[1],
4453
- relTrackX:
4454
- hoveredTrack && hoveredTrack.flipText ? relTrackPos[1] : relTrackPos[0],
4455
- relTrackY:
4456
- hoveredTrack && hoveredTrack.flipText ? relTrackPos[0] : relTrackPos[1],
4442
+ relTrackX: hoveredTrack?.flipText ? relTrackPos[1] : relTrackPos[0],
4443
+ relTrackY: hoveredTrack?.flipText ? relTrackPos[0] : relTrackPos[1],
4457
4444
  dataX,
4458
4445
  dataY,
4459
4446
  // See below why we need these derived boolean values
4460
- isFrom2dTrack: !!(hoveredTrack && hoveredTrack.is2d),
4461
- isFromVerticalTrack: !!(hoveredTrack && hoveredTrack.flipText),
4447
+ isFrom2dTrack: !!hoveredTrack?.is2d,
4448
+ isFromVerticalTrack: !!hoveredTrack?.flipText,
4462
4449
  track: hoveredTrack,
4463
4450
  origEvt: e,
4464
4451
  sourceUid: this.uid,
@@ -4536,13 +4523,12 @@ class HiGlassComponent extends React.Component {
4536
4523
  showHoverMenu(evt) {
4537
4524
  // each track should have a function that returns an HTML representation
4538
4525
  // of the data at a give position
4539
- const mouseOverHtml =
4540
- evt.track && evt.track.getMouseOverHtml
4541
- ? evt.track.getMouseOverHtml(evt.relTrackX, evt.relTrackY)
4542
- : '';
4526
+ const mouseOverHtml = evt.track?.getMouseOverHtml
4527
+ ? evt.track.getMouseOverHtml(evt.relTrackX, evt.relTrackY)
4528
+ : '';
4543
4529
 
4544
4530
  if (evt.track !== this.prevMouseHoverTrack) {
4545
- if (this.prevMouseHoverTrack && this.prevMouseHoverTrack.stopHover) {
4531
+ if (this.prevMouseHoverTrack?.stopHover) {
4546
4532
  this.prevMouseHoverTrack.stopHover();
4547
4533
  }
4548
4534
  }
@@ -4551,7 +4537,7 @@ class HiGlassComponent extends React.Component {
4551
4537
 
4552
4538
  if (this.zooming) return;
4553
4539
 
4554
- const data = mouseOverHtml && mouseOverHtml.length ? [1] : [];
4540
+ const data = mouseOverHtml?.length ? [1] : [];
4555
4541
 
4556
4542
  // try to select the mouseover div
4557
4543
  let mouseOverDiv = select('body')
@@ -4663,10 +4649,8 @@ class HiGlassComponent extends React.Component {
4663
4649
  ]
4664
4650
  : relPos;
4665
4651
 
4666
- const relTrackX =
4667
- hoveredTrack && hoveredTrack.flipText ? relTrackPos[1] : relTrackPos[0];
4668
- const relTrackY =
4669
- hoveredTrack && hoveredTrack.flipText ? relTrackPos[0] : relTrackPos[1];
4652
+ const relTrackX = hoveredTrack?.flipText ? relTrackPos[1] : relTrackPos[0];
4653
+ const relTrackY = hoveredTrack?.flipText ? relTrackPos[0] : relTrackPos[1];
4670
4654
 
4671
4655
  for (const track of this.iterateOverTracks()) {
4672
4656
  const trackObj = getTrackObjById(
@@ -4818,7 +4802,7 @@ class HiGlassComponent extends React.Component {
4818
4802
  this.props.options.zoomFixed ||
4819
4803
  this.state.viewConfig.zoomFixed ||
4820
4804
  this.props.options.sizeMode === SIZE_MODE_SCROLL ||
4821
- (view && view.zoomFixed)
4805
+ view?.zoomFixed
4822
4806
  );
4823
4807
  }
4824
4808
 
@@ -4900,14 +4884,8 @@ class HiGlassComponent extends React.Component {
4900
4884
  const evtToPublish = {
4901
4885
  x: relPos[0],
4902
4886
  y: relPos[1],
4903
- relTrackX:
4904
- hoveredTrack && hoveredTrack.flipText
4905
- ? relTrackPos[1]
4906
- : relTrackPos[0],
4907
- relTrackY:
4908
- hoveredTrack && hoveredTrack.flipText
4909
- ? relTrackPos[0]
4910
- : relTrackPos[1],
4887
+ relTrackX: hoveredTrack?.flipText ? relTrackPos[1] : relTrackPos[0],
4888
+ relTrackY: hoveredTrack?.flipText ? relTrackPos[0] : relTrackPos[1],
4911
4889
  track: hoveredTrack,
4912
4890
  origEvt: nativeEvent,
4913
4891
  sourceUid: this.uid,
@@ -5152,8 +5130,7 @@ class HiGlassComponent extends React.Component {
5152
5130
  }}
5153
5131
  getGenomePositionSearchBox={getGenomePositionSearchBox}
5154
5132
  isGenomePositionSearchBoxVisible={
5155
- view.genomePositionSearchBox &&
5156
- view.genomePositionSearchBox.visible
5133
+ view.genomePositionSearchBox?.visible
5157
5134
  }
5158
5135
  mouseTool={this.state.mouseTool}
5159
5136
  onAddView={() => this.handleAddView(view)}
@@ -28,7 +28,7 @@ class Horizontal1dHeatmapTrack extends HorizontalLine1DPixiTrack {
28
28
  }
29
29
 
30
30
  rerender(options) {
31
- if (options && options.colorRange) {
31
+ if (options?.colorRange) {
32
32
  this.setColorScale(options.colorRange);
33
33
  }
34
34
 
@@ -50,7 +50,7 @@ class Horizontal2DDomainsTrack extends TiledPixiTrack {
50
50
  let zoomLevel = Math.max(xZoomLevel, yZoomLevel);
51
51
  zoomLevel = Math.min(zoomLevel, this.maxZoom);
52
52
 
53
- if (this.options && this.options.maxZoom) {
53
+ if (this.options?.maxZoom) {
54
54
  if (this.options.maxZoom >= 0) {
55
55
  zoomLevel = Math.min(this.options.maxZoom, zoomLevel);
56
56
  } else {
@@ -1,11 +1,10 @@
1
1
  // @ts-nocheck
2
2
  import boxIntersect from 'box-intersect';
3
+ import { format, formatPrefix, precisionPrefix } from 'd3-format';
3
4
  import { scaleLinear } from 'd3-scale';
4
- import { format, precisionPrefix, formatPrefix } from 'd3-format';
5
5
 
6
- import PixiTrack from './PixiTrack';
7
6
  import ChromosomeInfo from './ChromosomeInfo';
8
- import SearchField from './SearchField';
7
+ import TiledPixiTrack from './TiledPixiTrack';
9
8
 
10
9
  import {
11
10
  absToChr,
@@ -22,13 +21,12 @@ const TICK_HEIGHT = 6;
22
21
  const TICK_TEXT_SEPARATION = 2;
23
22
  const TICK_COLOR = 0x777777;
24
23
 
25
- class HorizontalChromosomeLabels extends PixiTrack {
24
+ class HorizontalChromosomeLabels extends TiledPixiTrack {
26
25
  constructor(context, options) {
27
26
  super(context, options);
28
27
  const { dataConfig, animate, chromInfoPath, isShowGlobalMousePosition } =
29
28
  context;
30
29
 
31
- this.searchField = null;
32
30
  this.chromInfo = null;
33
31
  this.dataConfig = dataConfig;
34
32
 
@@ -80,25 +78,33 @@ class HorizontalChromosomeLabels extends PixiTrack {
80
78
  );
81
79
  }
82
80
 
83
- let chromSizesPath = chromInfoPath;
84
-
85
- if (!chromSizesPath) {
86
- chromSizesPath = `${dataConfig.server}/chrom-sizes/?id=${dataConfig.tilesetUid}`;
81
+ /** The previous chromInfoPath approach to loading chromosome size.
82
+ *
83
+ * This is superseded by loading chromosome sizes directly from the
84
+ * tileset info object
85
+ */
86
+ if (chromInfoPath) {
87
+ ChromosomeInfo(
88
+ chromInfoPath,
89
+ (newChromInfo) => {
90
+ this.chromInfo = newChromInfo;
91
+
92
+ this.tilesetInfoReceived();
93
+ },
94
+ this.pubSub,
95
+ );
87
96
  }
97
+ }
88
98
 
89
- ChromosomeInfo(
90
- chromSizesPath,
91
- (newChromInfo) => {
92
- this.chromInfo = newChromInfo;
93
-
94
- this.searchField = new SearchField(this.chromInfo);
99
+ tilesetInfoReceived() {
100
+ this.rerender(this.options, true);
101
+ this.draw();
102
+ this.animate();
103
+ }
95
104
 
96
- this.rerender(this.options, true);
97
- this.draw();
98
- this.animate();
99
- },
100
- this.pubSub,
101
- );
105
+ calculateVisibleTiles() {
106
+ /** This track does not use tiles so return an empty set */
107
+ return [];
102
108
  }
103
109
 
104
110
  initBoundsTicks() {
@@ -432,7 +438,7 @@ class HorizontalChromosomeLabels extends PixiTrack {
432
438
  draw() {
433
439
  this.allTexts = [];
434
440
 
435
- if (!this.texts || !this.searchField) return;
441
+ if (!this.texts) return;
436
442
 
437
443
  const x1 = absToChr(this._xScale.domain()[0], this.chromInfo);
438
444
  const x2 = absToChr(this._xScale.domain()[1], this.chromInfo);
@@ -11,9 +11,9 @@ import HorizontalTiled1DPixiTrack from './HorizontalTiled1DPixiTrack';
11
11
  // Services
12
12
  import { tileProxy } from './services';
13
13
 
14
+ import trackUtils from './track-utils';
14
15
  // Utils
15
16
  import { colorToHex } from './utils';
16
- import trackUtils from './track-utils';
17
17
 
18
18
  // these are default values that are overwritten by the track's options
19
19
  const FONT_SIZE = 11;
@@ -30,7 +30,7 @@ class HorizontalHeatmapTrack extends HeatmapTiledPixiTrack {
30
30
  // Continuous scaling is currently not supported
31
31
  this.continuousScaling = false;
32
32
 
33
- if (options && options.colorRange) {
33
+ if (options?.colorRange) {
34
34
  this.colorScale = colorDomainToRgbaArray(options.colorRange);
35
35
  }
36
36
 
@@ -89,7 +89,7 @@ class HorizontalHeatmapTrack extends HeatmapTiledPixiTrack {
89
89
  zoomLevel = Math.min(zoomLevel, this.maxZoom);
90
90
  }
91
91
 
92
- if (this.options && this.options.maxZoom) {
92
+ if (this.options?.maxZoom) {
93
93
  if (this.options.maxZoom >= 0) {
94
94
  zoomLevel = Math.min(this.options.maxZoom, zoomLevel);
95
95
  } else {