higlass 1.12.3 → 1.13.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 (90) hide show
  1. package/README.md +3 -3
  2. package/app/globals.d.ts +11 -0
  3. package/app/missing-types.d.ts +21 -0
  4. package/app/scripts/CenterTrack.jsx +0 -1
  5. package/app/scripts/DraggableDiv.jsx +0 -1
  6. package/app/scripts/GenomePositionSearchBox.jsx +0 -1
  7. package/app/scripts/SearchField.js +1 -1
  8. package/app/scripts/TrackRenderer.jsx +405 -89
  9. package/app/scripts/VerticalTiledPlot.jsx +0 -1
  10. package/app/scripts/configs/default-tracks-for-datatype.js +3 -2
  11. package/app/scripts/configs/primitives.js +3 -2
  12. package/app/scripts/configs/tracks-info-by-type.js +4 -1
  13. package/app/scripts/configs/tracks-info.js +25 -1
  14. package/app/scripts/plugins/available-for-plugins.js +14 -6
  15. package/app/scripts/types.ts +79 -0
  16. package/app/scripts/utils/abs-to-chr.js +16 -1
  17. package/app/scripts/utils/accessor-transposition.js +5 -4
  18. package/app/scripts/utils/add-arrays.js +9 -7
  19. package/app/scripts/utils/add-class.js +4 -2
  20. package/app/scripts/utils/add-event-listener-once.js +9 -3
  21. package/app/scripts/utils/background-task-scheduler.js +58 -2
  22. package/app/scripts/utils/base64-to-canvas.js +12 -5
  23. package/app/scripts/utils/chr-to-abs.js +10 -0
  24. package/app/scripts/utils/chrom-info-bisector.js +4 -1
  25. package/app/scripts/utils/clone-event.js +11 -4
  26. package/app/scripts/utils/color-to-hex.js +8 -0
  27. package/app/scripts/utils/color-to-rgba.js +8 -0
  28. package/app/scripts/utils/data-to-genomic-loci.js +13 -1
  29. package/app/scripts/utils/debounce.js +16 -11
  30. package/app/scripts/utils/dec-to-hex-str.js +7 -0
  31. package/app/scripts/utils/dict-from-tuples.js +11 -3
  32. package/app/scripts/utils/dict-items.js +15 -0
  33. package/app/scripts/utils/dict-keys.js +11 -1
  34. package/app/scripts/utils/dict-values.js +7 -0
  35. package/app/scripts/utils/download.js +14 -11
  36. package/app/scripts/utils/flatten.js +5 -2
  37. package/app/scripts/utils/for-each.js +7 -5
  38. package/app/scripts/utils/forward-event.js +3 -2
  39. package/app/scripts/utils/genome-loci-to-pixels.js +8 -0
  40. package/app/scripts/utils/genomic-range-to-chromosome-chunks.js +13 -6
  41. package/app/scripts/utils/get-aggregation-function.js +10 -2
  42. package/app/scripts/utils/get-element-dim.js +6 -0
  43. package/app/scripts/utils/gradient.js +14 -0
  44. package/app/scripts/utils/has-class.js +6 -4
  45. package/app/scripts/utils/hex-string-to-int.js +11 -4
  46. package/app/scripts/utils/index.js +14 -0
  47. package/app/scripts/utils/into-the-void.js +2 -1
  48. package/app/scripts/utils/is-track-or-child-track.js +6 -0
  49. package/app/scripts/utils/is-track-range-selectable.js +10 -1
  50. package/app/scripts/utils/is-within.js +9 -7
  51. package/app/scripts/utils/lat-to-y.js +6 -3
  52. package/app/scripts/utils/lng-to-x.js +4 -3
  53. package/app/scripts/utils/map.js +5 -2
  54. package/app/scripts/utils/max-non-zero.js +6 -0
  55. package/app/scripts/utils/max.js +4 -3
  56. package/app/scripts/utils/min-non-zero.js +6 -0
  57. package/app/scripts/utils/min.js +4 -3
  58. package/app/scripts/utils/mod.js +4 -3
  59. package/app/scripts/utils/numericify-version.js +5 -0
  60. package/app/scripts/utils/obj-vals.js +3 -2
  61. package/app/scripts/utils/or.js +4 -3
  62. package/app/scripts/utils/parse-chromsizes-rows.js +26 -5
  63. package/app/scripts/utils/q.js +3 -2
  64. package/app/scripts/utils/rad-to-deg.js +3 -2
  65. package/app/scripts/utils/reduce.js +2 -2
  66. package/app/scripts/utils/rel-to-abs-chrom-pos.js +10 -0
  67. package/app/scripts/utils/remove-class.js +3 -2
  68. package/app/scripts/utils/reset-d3-brush-style.js +7 -2
  69. package/app/scripts/utils/rgb-to-hex.js +9 -0
  70. package/app/scripts/utils/scales-center-and-k.js +5 -3
  71. package/app/scripts/utils/scales-to-genome-loci.js +10 -0
  72. package/app/scripts/utils/selected-items-to-cum-weights.js +12 -4
  73. package/app/scripts/utils/selected-items-to-size.js +5 -2
  74. package/app/scripts/utils/show-mouse-position.js +62 -19
  75. package/app/scripts/utils/some.js +6 -4
  76. package/app/scripts/utils/sum.js +4 -3
  77. package/app/scripts/utils/throttle-and-debounce.js +15 -6
  78. package/app/scripts/utils/tile-to-canvas.js +8 -4
  79. package/app/scripts/utils/timeout.js +2 -0
  80. package/app/scripts/utils/to-void.js +2 -0
  81. package/app/scripts/utils/total-track-pixel-height.js +11 -12
  82. package/app/scripts/utils/trim-trailing-slash.js +3 -2
  83. package/app/scripts/utils/type-guards.js +17 -0
  84. package/app/scripts/utils/value-to-color.js +7 -6
  85. package/app/scripts/utils/visit-positioned-tracks.js +16 -11
  86. package/app/scripts/utils/visit-tracks.js +12 -13
  87. package/dist/hglib.css +54 -54
  88. package/dist/hglib.js +62191 -62096
  89. package/dist/hglib.min.js +127 -127
  90. package/package.json +16 -5
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Pure functional reducer. Can be used for currying stuff. Check out
3
- * `flatten.js`.
2
+ * Pure functional reducer. Can be used for currying stuff. Check out `flatten.js`.
4
3
  * @param {function} f Reducer function.
5
4
  * @return {array} Curried function that accepts an array to be reduced.
6
5
  */
7
6
  const reduce = (f) => (x) => Array.prototype.reduce.call(x, f);
8
7
 
8
+ // TODO(Trevor): Not referenced anywhere. Remove?
9
9
  export default reduce;
@@ -1,3 +1,13 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @template {string} Name
5
+ * @param {Name} chrom
6
+ * @param {number} x
7
+ * @param {number} y
8
+ * @param {import('../types').ChromInfo<Name>} chromInfo
9
+ * @returns {[number, number]}
10
+ */
1
11
  const relToAbsChromPos = (chrom, x, y, chromInfo) => [
2
12
  chromInfo.chrPositions[chrom].pos + +x,
3
13
  chromInfo.chrPositions[chrom].pos + +y,
@@ -1,11 +1,12 @@
1
+ // @ts-check
1
2
  import hasClass from './has-class';
2
3
 
3
4
  const XMLNS = 'http://www.w3.org/2000/svg';
4
5
 
5
6
  /**
6
7
  * Remove a class from an HTML or SVG element.
7
- * @param {object} el HTML or SVG element.
8
- * @param {string} className Class name to be removed.
8
+ * @param {Element} el - HTML or SVG element.
9
+ * @param {string} className Class name to be removed.
9
10
  */
10
11
  const removeClass = (el, className) => {
11
12
  const reg = new RegExp(`(\\s|^)${className}(\\s|$)`);
@@ -1,7 +1,12 @@
1
+ // @ts-check
2
+
3
+ /** @typedef {import('d3-selection').BaseType} BaseType */
4
+
1
5
  /**
2
6
  * Unsets the automatically set brush style of D3.
3
- * @param {object} el Element which is brushed on.
4
- * @param {string} className New class name to be set.
7
+ * @template {import('d3-selection').Selection<BaseType, unknown, BaseType, unknown>} Sel
8
+ * @param {Sel} el - Element which is brushed on.
9
+ * @param {string} className New class name to be set.
5
10
  */
6
11
  const resetD3BrushStyle = (el, className) => {
7
12
  el.select('.selection')
@@ -1,8 +1,17 @@
1
+ // @ts-check
2
+
3
+ /** @param {number} c */
1
4
  const componentToHex = (c) => {
2
5
  const hex = c.toString(16);
3
6
  return hex.length === 1 ? `0${hex}` : hex;
4
7
  };
5
8
 
9
+ /**
10
+ * @param {number} r
11
+ * @param {number} g
12
+ * @param {number} b
13
+ * @returns {string}
14
+ */
6
15
  const rgbToHex = (r, g, b) =>
7
16
  `#${componentToHex(r)}${componentToHex(g)}${componentToHex(b)}`;
8
17
 
@@ -1,12 +1,14 @@
1
+ // @ts-check
2
+
1
3
  /**
2
4
  * Calculate the center of the scale as well as its scale
3
5
  * factor
4
6
  *
5
7
  * Assumes the two scales have the same k
6
8
  *
7
- * @param xScale: A d3 scale.
8
- * @param yScale: A d3 scale.
9
- * @return: [domainCenter, k]
9
+ * @param {import('../types').Scale} xScale - A d3 scale.
10
+ * @param {import('../types').Scale} yScale - A d3 scale.
11
+ * @return {[xCenter: number, yCenter: number, k: number]}
10
12
  */
11
13
  const scalesCenterAndK = (xScale, yScale) => {
12
14
  const xCenter = xScale.invert((xScale.range()[0] + xScale.range()[1]) / 2);
@@ -1,5 +1,15 @@
1
+ // @ts-check
1
2
  import dataToGenomicLoci from './data-to-genomic-loci';
2
3
 
4
+ /** @typedef {import('./data-to-genomic-loci').GenomicLoci} GenomicLoci */
5
+
6
+ /**
7
+ * Convert a pair of scales to genomic coordinates.
8
+ * @param {import('../types').Scale} xScale
9
+ * @param {import('../types').Scale} yScale
10
+ * @param {import('../types').ChromInfo} chromInfo
11
+ * @returns {[...GenomicLoci, ...GenomicLoci] | undefined} The genomic coordinates.
12
+ */
3
13
  export const scalesToGenomeLoci = (xScale, yScale, chromInfo) => {
4
14
  if (chromInfo === null || !xScale || !yScale) return undefined;
5
15
 
@@ -1,7 +1,14 @@
1
+ // @ts-check
1
2
  import selectedItemsToSize from './selected-items-to-size';
2
3
 
4
+ /**
5
+ * Compute the cumulative sum of an array of numbers.
6
+ * @param {Array<number>} values - The array of numbers to sum.
7
+ * @returns {Float64Array} The array of cumulative sums.
8
+ */
3
9
  function cumsum(values) {
4
10
  let sum = 0;
11
+ /** @type {number[]} */
5
12
  const result = [];
6
13
  values.forEach((v) => {
7
14
  sum += +v || 0;
@@ -13,10 +20,11 @@ function cumsum(values) {
13
20
  /**
14
21
  * Compute the cumulative normalized weights associated with a
15
22
  * potentially 2d array of selected item indices.
16
- * @param {array} selectedItems The 1d or 2d array of items or groups of items.
17
- * @param {boolean} withRelativeSize Does a group of indices count as 1 unit size
18
- * or is its size relative to the group size?
19
- * @returns {number[]} The array of cumulative weights, one for each item.
23
+ *
24
+ * @param {Array<unknown>} selectedItems - The 1d or 2d array of items or groups of items.
25
+ * @param {boolean} withRelativeSize - Does a group of indices count as 1 unit size or is its size relative to the group size?
26
+ * @returns {Float64Array} The array of cumulative weights, one for each item.
27
+ *
20
28
  * Sums to 1 before the cumulative sum step (i.e. the final array element will be 1).
21
29
  */
22
30
  const selectedItemsToCumWeights = (selectedItems, withRelativeSize) => {
@@ -1,8 +1,10 @@
1
+ // @ts-check
1
2
  /**
2
3
  * Compute the size associated with a potentially 2d array of selected item indices.
3
4
  * For example, this can be used to compute the total height of a `horizontal-multivec` track
4
5
  * where rows are selected individually or in aggregation groups.
5
- * @param {array} selectedItems The 1d or 2d array of items or groups of items.
6
+ *
7
+ * @param {Array<unknown>} selectedItems The 1d or 2d array of items or groups of items.
6
8
  * @param {boolean} withRelativeSize Does a group of indices count as 1 unit size
7
9
  * or is its size relative to the group size?
8
10
  * @returns {number} The computed size value.
@@ -10,7 +12,8 @@
10
12
  */
11
13
  const selectedItemsToSize = (selectedItems, withRelativeSize) =>
12
14
  selectedItems.reduce(
13
- (a, h) => a + (Array.isArray(h) && withRelativeSize ? h.length : 1),
15
+ (/** @type {number} */ a, h) =>
16
+ a + (Array.isArray(h) && withRelativeSize ? h.length : 1),
14
17
  0,
15
18
  );
16
19
 
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  import { globalPubSub } from 'pub-sub-es';
2
3
 
3
4
  import hexStrToInt from './hex-string-to-int';
@@ -8,22 +9,27 @@ import { GLOBALS } from '../configs';
8
9
  const COLOR = 0xaaaaaa;
9
10
  const ALPHA = 1.0;
10
11
 
12
+ /**
13
+ * @typedef MouseTrackOptions
14
+ * @property {string=} mousePositionColor - Color of the mouse position.
15
+ * @property {number=} mousePositionAlpha - Alpha of the mouse position.
16
+ */
17
+
11
18
  /**
12
19
  * Actual interface for initializing to show the mouse location
13
20
  *
14
- * @param {Object} pubSubs PubSub service.
15
- * @param {Object} pubSubs Subscribed PubSub events.
16
- * @param {Object} options Track options.
17
- * @param {Function} getScales Getter for the track's X and Y scales.
18
- * @param {Function} getPosition Getter for the track's position.
19
- * @param {Function} getDimensions Getter for the track's dimensions.
20
- * @param {Function} getIsFlipped Getter determining if a track has been
21
+ * @param {import('pub-sub-es').PubSub} pubSub - PubSub service.
22
+ * @param {Array<import('pub-sub-es').Subscription>} pubSubs - Subscribed PubSub events.
23
+ * @param {MouseTrackOptions} options - Track options.
24
+ * @param {() => [import('../types').Scale, import('../types').Scale]} getScales - Getter for the track's X and Y scales.
25
+ * @param {() => [number, number]} getPosition - Getter for the track's position.
26
+ * @param {() => [number, number]} getDimensions - Getter for the track's dimensions.
27
+ * @param {() => boolean} getIsFlipped - Getter determining if a track has been
21
28
  * flipped from horizontal to vertical.
22
- * @param {Boolean} is2d If `true` draw both dimensions of the mouse
23
- * location.
24
- * @param {Boolean} isGlobal If `true` local and global events will trigger
29
+ * @param {boolean} is2d - If `true` draw both dimensions of the mouse location.
30
+ * @param {boolean} isGlobal - If `true` local and global events will trigger
25
31
  * the mouse position drawing.
26
- * @return {Object} PIXI graphics the mouse location is drawn on.
32
+ * @return {import('pixi.js').Graphics} - PIXI graphics the mouse location is drawn on.
27
33
  */
28
34
  const showMousePosition = (
29
35
  pubSub,
@@ -56,10 +62,11 @@ const showMousePosition = (
56
62
  /**
57
63
  * Draw 1D mouse location (cross) hair onto the PIXI graphics.
58
64
  *
59
- * @param {Integer} mousePos One dimension of the mouse location
60
- * @param {Boolean} isHorizontal If `true` the dimension to be drawn is
65
+ * @param {number} mousePos - One dimension of the mouse location (integer).
66
+ * @param {boolean=} isHorizontal - If `true` the dimension to be drawn is
61
67
  * horizontal.
62
- * @param {Boolean} isNoClear If `true` do not clear the graphics.
68
+ * @param {boolean=} isNoClear If `true` do not clear the graphics.
69
+ * @return {void}
63
70
  */
64
71
  const drawMousePosition = (mousePos, isHorizontal, isNoClear) => {
65
72
  if (!isNoClear) clearGraphics();
@@ -77,10 +84,25 @@ const showMousePosition = (
77
84
  }
78
85
  };
79
86
 
87
+ /**
88
+ * @typedef NoHoveredTracksEvent
89
+ * @property {true} noHoveredTracks - If `true` no tracks are hovered.
90
+ * @property {false=} isFromVerticalTrack - If `true` the event is from a vertical track.
91
+ */
92
+
93
+ /**
94
+ * @typedef TrackEvent
95
+ * @property {false=} noHoveredTracks - If `true` no tracks are hovered.
96
+ * @property {boolean} isFromVerticalTrack - If `true` the event is from a vertical track.
97
+ * @property {boolean} isFrom2dTrack - If `true` the event is from a 2D track.
98
+ * @property {number} dataY - Y position of the mouse.
99
+ * @property {number} dataX - X position of the mouse.
100
+ */
101
+
80
102
  /**
81
103
  * Mouse move handler
82
104
  *
83
- * @param {Object} e Event object.
105
+ * @param {Event & (NoHoveredTracksEvent | TrackEvent)} event - Event object.
84
106
  */
85
107
  const mouseMoveHandler = (event) => {
86
108
  if (event.noHoveredTracks) {
@@ -127,6 +149,21 @@ const showMousePosition = (
127
149
  return graphics;
128
150
  };
129
151
 
152
+ /**
153
+ * @typedef ClassContext
154
+ * @property {import('pixi.js').Container=} pForeground
155
+ * @property {import('pixi.js').Container=} pMasked
156
+ * @property {import('pixi.js').Container=} pMain
157
+ * @property {() => import('../types').Scale} xScale
158
+ * @property {() => import('../types').Scale} yScale
159
+ * @property {() => [number, number]} getPosition
160
+ * @property {() => [number, number]} getDimensions
161
+ * @property {import('pub-sub-es').PubSub} pubSub
162
+ * @property {Array<import('pub-sub-es').Subscription>} pubSubs
163
+ * @property {(prop: 'flipText') => () => boolean} getProp
164
+ * @property {{}} options
165
+ */
166
+
130
167
  /**
131
168
  * Public API for showing the mouse location.
132
169
  *
@@ -135,15 +172,21 @@ const showMousePosition = (
135
172
  * `showMousePosition` is the actual function and could be called from within
136
173
  * each class as well.
137
174
  *
138
- * @param {Object} context Class context, i.e., `this`.
139
- * @param {Boolean} is2d If `true` both dimensions of the mouse location
175
+ * @param {ClassContext} context - Class context, i.e., `this`.
176
+ * @param {Boolean} is2d - If `true` both dimensions of the mouse location
140
177
  * should be shown. E.g., on a central track.
141
- * @param {Boolean} isGlobal If `true` local and global events will trigger
178
+ * @param {Boolean} isGlobal - If `true` local and global events will trigger
142
179
  * the mouse position drawing.
143
- * @return {Function} Method to remove graphics showing the mouse location.
180
+ * @return {Function} - Method to remove graphics showing the mouse location.
144
181
  */
145
182
  const setupShowMousePosition = (context, is2d = false, isGlobal = false) => {
146
183
  const scene = is2d ? context.pMasked : context.pForeground || context.pMain;
184
+ if (!scene) {
185
+ throw new Error(
186
+ 'setupShowMousePosition: No scene found. Please make sure to call this method after the scene has been initialized.',
187
+ );
188
+ }
189
+ /** @type {() => [import('../types').Scale, import('../types').Scale]} */
147
190
  const getScales = () => [context.xScale(), context.yScale()];
148
191
 
149
192
  const graphics = showMousePosition(
@@ -1,9 +1,11 @@
1
+ // @ts-check
1
2
  /**
2
3
  * Functional version of `Array.forEach`. More flexible and applicable to
3
- * other array-like data types like `NodeList`.
4
- * @param {function} f Modifier function applied on every item of the
5
- * array.
6
- * @return {*} Modified array-like variable.
4
+ * other array-like data types like `NodeList`.
5
+ *
6
+ * @template T
7
+ * @param {(item: T, i: number) => boolean} f - Modifier function applied on every item of the array.
8
+ * @return {(arr: Array<T>) => boolean} Modified array-like variable.
7
9
  */
8
10
  const some = (f) => (x) => Array.prototype.some.call(x, f);
9
11
 
@@ -1,8 +1,9 @@
1
+ // @ts-check
1
2
  /**
2
3
  * Convenience function for a reducer to sum up a numerical array.
3
- * @param {number} a Value A
4
- * @param {number} b Value B
5
- * @return {number} Sum of A + B
4
+ * @param {number} a - Value A
5
+ * @param {number} b - Value B
6
+ * @return {number} Sum of A + B
6
7
  */
7
8
  const sum = (a, b) => a + b;
8
9
 
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  /**
2
3
  * Throttle and debounce a function call
3
4
  *
@@ -23,19 +24,22 @@
23
24
  * 09. nothing
24
25
  * 10. y(f, 2, 2)(args_10) => f(args_10) call from debouncing
25
26
  *
26
- * @param {functon} func - Function to be throttled and debounced
27
- * @param {number} interval - Throttle intevals in milliseconds
28
- * @param {number} finalWait - Debounce wait time in milliseconds
29
- * @return {function} - Throttled and debounced function
27
+ * @template {any[]} Args
28
+ * @param {(...args: Args) => void} func - Function to be throttled and debounced
29
+ * @param {number} interval - Throttle intevals in milliseconds
30
+ * @param {number} finalWait - Debounce wait time in milliseconds
31
+ * @return {(request: unknown, ...args: Args) => void} - Throttled and debounced function
30
32
  */
31
33
  const throttleAndDebounce = (func, interval, finalWait) => {
34
+ /** @type {ReturnType<typeof setTimeout> | undefined} */
32
35
  let timeout;
33
36
  let blockedCalls = 0;
34
37
 
35
38
  const reset = () => {
36
- timeout = null;
39
+ timeout = undefined;
37
40
  };
38
41
 
42
+ /** @param {Args} args */
39
43
  const debounced = (...args) => {
40
44
  const later = () => {
41
45
  // Since we throttle and debounce we should check whether there were
@@ -57,12 +61,17 @@ const throttleAndDebounce = (func, interval, finalWait) => {
57
61
  reset();
58
62
  };
59
63
 
64
+ /** @param {Args} args */
60
65
  debounced.immediate = (...args) => {
61
66
  func(...args);
62
67
  };
63
68
 
64
69
  let wait = false;
65
- const throttled = (request, ...args) => {
70
+ /**
71
+ * @param {unknown} _request
72
+ * @param {Args} args
73
+ */
74
+ const throttled = (_request, ...args) => {
66
75
  if (!wait) {
67
76
  func(...args);
68
77
  debounced(...args);
@@ -1,9 +1,10 @@
1
+ // @ts-check
1
2
  /**
2
3
  * Convert a 1D numerical array into a canvas image
3
- * @param {Float32Array} pixData 1D data array
4
- * @param {number} w Width
5
- * @param {number} h Height
6
- * @return {object} Canvas object
4
+ * @param {Uint8ClampedArray} pixData - 1D data array
5
+ * @param {number} w - Width
6
+ * @param {number} h - Height
7
+ * @return {object} Canvas object
7
8
  */
8
9
  const tileToCanvas = (pixData, w = 256, h = 256) => {
9
10
  const canvas = document.createElement('canvas');
@@ -12,6 +13,9 @@ const tileToCanvas = (pixData, w = 256, h = 256) => {
12
13
  canvas.height = h;
13
14
 
14
15
  const ctx = canvas.getContext('2d');
16
+ if (!ctx) {
17
+ throw new Error('Could not get canvas context');
18
+ }
15
19
 
16
20
  ctx.fillStyle = 'transparent';
17
21
  ctx.fillRect(0, 0, canvas.width, canvas.height);
@@ -1,3 +1,5 @@
1
+ // @ts-check
2
+ /** @param {number} ms */
1
3
  const timeout = (ms) =>
2
4
  new Promise((resolve) => {
3
5
  setTimeout(resolve, ms);
@@ -1,3 +1,5 @@
1
+ // @ts-check
2
+ /** @type {(...args: any[]) => void} */
1
3
  const toVoid = () => {};
2
4
 
3
5
  export default toVoid;
@@ -1,17 +1,16 @@
1
+ // @ts-check
1
2
  /**
2
- * Calculate the total height of the horizontal and center
3
- * tracks in pixels
4
- *
5
- * Parameters
6
- * -----------
7
- *
8
- * view : view config object
9
- * A typical view configuration containing a list of tracks
3
+ * @typedef Tracks
4
+ * @prop {{ height: number }[]=} top
5
+ * @prop {{ height: number }[]=} center
6
+ * @prop {{ height: number }[]=} bottom
7
+ */
8
+
9
+ /**
10
+ * Calculate the total height of the horizontal and center tracks in pixels
10
11
  *
11
- * Returns
12
- * -------
13
- * int
14
- * The total height of the top, center and bottom tracks
12
+ * @param {{ tracks?: Tracks }} view - A typical view configuration containing a list of tracks
13
+ * @returns {number} - The total height of the top, center and bottom tracks
15
14
  */
16
15
  const totalTrackPixelHeight = (view) => {
17
16
  // no tracks means no height
@@ -1,7 +1,8 @@
1
+ // @ts-check
1
2
  /**
2
3
  * Trim trailing slash of an URL.
3
- * @param {string} url URL to be trimmed.
4
- * @return {string} Trimmed URL.
4
+ * @param {string} url - URL to be trimmed.
5
+ * @return {string} Trimmed URL.
5
6
  */
6
7
  const trimTrailingSlash = (url) => (url || '').replace(/\/$/, '');
7
8
 
@@ -0,0 +1,17 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @param {import('../types').TrackConfig} trackConfig
5
+ * @return {trackConfig is import('../types').CombinedTrackConfig}
6
+ */
7
+ export function isCombinedTrackConfig(trackConfig) {
8
+ return trackConfig.type === 'combined';
9
+ }
10
+
11
+ /**
12
+ * @param {Event} event
13
+ * @returns {event is WheelEvent}
14
+ */
15
+ export function isWheelEvent(event) {
16
+ return 'deltaY' in event && 'deltaMode' in event;
17
+ }
@@ -1,12 +1,13 @@
1
+ // @ts-check
1
2
  /**
2
3
  * Factory function for a value to RGB color converter
3
4
  *
4
- * @param {Function} valueScale Value scaling function.
5
- * @param {Array} colorScale Color scale array.
6
- * @param {Number} pseudoCounts Pseudo counts used as a pseudocount to
7
- * prevent taking the log of 0.
8
- * @param {Number} eps Epsilon.
9
- * @return {Array} RGB color array.
5
+ * @template T
6
+ * @param {(value: number) => number} valueScale - Value scaling function.
7
+ * @param {Array<T>} colorScale - Color scale array.
8
+ * @param {number} pseudoCounts - Pseudo counts used as a pseudocount to prevent taking the log of 0.
9
+ * @param {number} eps - Epsilon.
10
+ * @return {(value: number) => T} RGB color array.
10
11
  */
11
12
  const valueToColor =
12
13
  (valueScale, colorScale, pseudoCounts = 0, eps = 0.000001) =>
@@ -1,26 +1,31 @@
1
+ // @ts-check
1
2
  import visitTracks from './visit-tracks';
2
3
 
4
+ /** @typedef {{ [Key in import('../types').TrackPosition]: import('../types').TrackConfig[] }} PositionedTracks
5
+ */
6
+
3
7
  /**
4
8
  * Track visitor for positioned tracks, i.e., tracks with a position.
5
- * @param {array} tracks List of all positioned tracks from the view definition.
6
- * @param {function} visitor Callback function receiving individual tracks.
7
- * @param {boolean} inclCombinedTracks If `true` recursively visit combined tracks.
9
+ * @param {PositionedTracks} positionedTracks - List of all positioned tracks from the view definition.
10
+ * @param {import('../types').TrackVisitor} visitor - Callback function receiving individual tracks.
11
+ * @param {boolean} inclCombinedTracks - If `true` recursively visit combined tracks.
8
12
  */
9
13
  const visitPositionedTracks = (
10
14
  positionedTracks,
11
15
  visitor,
12
16
  inclCombinedTracks = true,
13
17
  ) => {
18
+ /** @type {import('../types').TrackConfig[]} */
14
19
  const allTracks = [];
15
20
 
16
- Object.keys(positionedTracks).forEach((position) => {
17
- visitTracks(
18
- positionedTracks[position],
19
- visitor,
20
- inclCombinedTracks,
21
- position,
22
- );
23
- });
21
+ for (const [stringPosition, tracks] of Object.entries(positionedTracks)) {
22
+ /** @type {import('../types').TrackPosition} */
23
+ // @ts-expect-error - Typings for Object#entries don't have strong inference,
24
+ // might change in the future.
25
+ const position = stringPosition;
26
+ visitTracks(tracks, visitor, inclCombinedTracks, position);
27
+ allTracks.push(...tracks);
28
+ }
24
29
 
25
30
  return allTracks;
26
31
  };
@@ -1,25 +1,24 @@
1
+ // @ts-check
2
+ import { isCombinedTrackConfig } from './type-guards';
3
+
1
4
  /**
2
5
  * Track visitor to run code on individual tracks.
3
- * @param {array} tracks List of all tracks from the view definition.
4
- * @param {function} visitor Callback function receiving individual tracks.
5
- * @param {boolean} inclCombinedTracks If `true` recursively visit combined tracks.
6
- * @param {function} position Can be used to limit the tracks to be visit to a certain position.
6
+ * @param {import('../types').TrackConfig[]} tracks - List of all tracks from the view definition.
7
+ * @param {import('../types').TrackVisitor} visit - Callback function receiving individual tracks.
8
+ * @param {boolean} includeCombinedTracks - If `true` recursively visit combined tracks.
9
+ * @param {import('../types').TrackPosition | null} position - Can be used to limit the tracks to be visit to a certain position.
7
10
  */
8
11
  const visitTracks = (
9
12
  tracks,
10
- visitor,
11
- inclCombinedTracks = true,
13
+ visit,
14
+ includeCombinedTracks = true,
12
15
  position = null,
13
16
  ) =>
14
17
  tracks.forEach((track) => {
15
- if (track.type === 'combined') {
16
- if (inclCombinedTracks) {
17
- visitTracks(track.contents, visitor, inclCombinedTracks, position);
18
- visitor(track, position);
19
- }
20
- } else {
21
- visitor(track, position);
18
+ if (includeCombinedTracks && isCombinedTrackConfig(track)) {
19
+ visitTracks(track.contents, visit, includeCombinedTracks, position);
22
20
  }
21
+ visit(track, position);
23
22
  });
24
23
 
25
24
  export default visitTracks;