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.
- package/README.md +3 -3
- package/app/globals.d.ts +11 -0
- package/app/missing-types.d.ts +21 -0
- package/app/scripts/CenterTrack.jsx +0 -1
- package/app/scripts/DraggableDiv.jsx +0 -1
- package/app/scripts/GenomePositionSearchBox.jsx +0 -1
- package/app/scripts/SearchField.js +1 -1
- package/app/scripts/TrackRenderer.jsx +405 -89
- package/app/scripts/VerticalTiledPlot.jsx +0 -1
- package/app/scripts/configs/default-tracks-for-datatype.js +3 -2
- package/app/scripts/configs/primitives.js +3 -2
- package/app/scripts/configs/tracks-info-by-type.js +4 -1
- package/app/scripts/configs/tracks-info.js +25 -1
- package/app/scripts/plugins/available-for-plugins.js +14 -6
- package/app/scripts/types.ts +79 -0
- package/app/scripts/utils/abs-to-chr.js +16 -1
- package/app/scripts/utils/accessor-transposition.js +5 -4
- package/app/scripts/utils/add-arrays.js +9 -7
- package/app/scripts/utils/add-class.js +4 -2
- package/app/scripts/utils/add-event-listener-once.js +9 -3
- package/app/scripts/utils/background-task-scheduler.js +58 -2
- package/app/scripts/utils/base64-to-canvas.js +12 -5
- package/app/scripts/utils/chr-to-abs.js +10 -0
- package/app/scripts/utils/chrom-info-bisector.js +4 -1
- package/app/scripts/utils/clone-event.js +11 -4
- package/app/scripts/utils/color-to-hex.js +8 -0
- package/app/scripts/utils/color-to-rgba.js +8 -0
- package/app/scripts/utils/data-to-genomic-loci.js +13 -1
- package/app/scripts/utils/debounce.js +16 -11
- package/app/scripts/utils/dec-to-hex-str.js +7 -0
- package/app/scripts/utils/dict-from-tuples.js +11 -3
- package/app/scripts/utils/dict-items.js +15 -0
- package/app/scripts/utils/dict-keys.js +11 -1
- package/app/scripts/utils/dict-values.js +7 -0
- package/app/scripts/utils/download.js +14 -11
- package/app/scripts/utils/flatten.js +5 -2
- package/app/scripts/utils/for-each.js +7 -5
- package/app/scripts/utils/forward-event.js +3 -2
- package/app/scripts/utils/genome-loci-to-pixels.js +8 -0
- package/app/scripts/utils/genomic-range-to-chromosome-chunks.js +13 -6
- package/app/scripts/utils/get-aggregation-function.js +10 -2
- package/app/scripts/utils/get-element-dim.js +6 -0
- package/app/scripts/utils/gradient.js +14 -0
- package/app/scripts/utils/has-class.js +6 -4
- package/app/scripts/utils/hex-string-to-int.js +11 -4
- package/app/scripts/utils/index.js +14 -0
- package/app/scripts/utils/into-the-void.js +2 -1
- package/app/scripts/utils/is-track-or-child-track.js +6 -0
- package/app/scripts/utils/is-track-range-selectable.js +10 -1
- package/app/scripts/utils/is-within.js +9 -7
- package/app/scripts/utils/lat-to-y.js +6 -3
- package/app/scripts/utils/lng-to-x.js +4 -3
- package/app/scripts/utils/map.js +5 -2
- package/app/scripts/utils/max-non-zero.js +6 -0
- package/app/scripts/utils/max.js +4 -3
- package/app/scripts/utils/min-non-zero.js +6 -0
- package/app/scripts/utils/min.js +4 -3
- package/app/scripts/utils/mod.js +4 -3
- package/app/scripts/utils/numericify-version.js +5 -0
- package/app/scripts/utils/obj-vals.js +3 -2
- package/app/scripts/utils/or.js +4 -3
- package/app/scripts/utils/parse-chromsizes-rows.js +26 -5
- package/app/scripts/utils/q.js +3 -2
- package/app/scripts/utils/rad-to-deg.js +3 -2
- package/app/scripts/utils/reduce.js +2 -2
- package/app/scripts/utils/rel-to-abs-chrom-pos.js +10 -0
- package/app/scripts/utils/remove-class.js +3 -2
- package/app/scripts/utils/reset-d3-brush-style.js +7 -2
- package/app/scripts/utils/rgb-to-hex.js +9 -0
- package/app/scripts/utils/scales-center-and-k.js +5 -3
- package/app/scripts/utils/scales-to-genome-loci.js +10 -0
- package/app/scripts/utils/selected-items-to-cum-weights.js +12 -4
- package/app/scripts/utils/selected-items-to-size.js +5 -2
- package/app/scripts/utils/show-mouse-position.js +62 -19
- package/app/scripts/utils/some.js +6 -4
- package/app/scripts/utils/sum.js +4 -3
- package/app/scripts/utils/throttle-and-debounce.js +15 -6
- package/app/scripts/utils/tile-to-canvas.js +8 -4
- package/app/scripts/utils/timeout.js +2 -0
- package/app/scripts/utils/to-void.js +2 -0
- package/app/scripts/utils/total-track-pixel-height.js +11 -12
- package/app/scripts/utils/trim-trailing-slash.js +3 -2
- package/app/scripts/utils/type-guards.js +17 -0
- package/app/scripts/utils/value-to-color.js +7 -6
- package/app/scripts/utils/visit-positioned-tracks.js +16 -11
- package/app/scripts/utils/visit-tracks.js +12 -13
- package/dist/hglib.css +54 -54
- package/dist/hglib.js +62191 -62096
- package/dist/hglib.min.js +127 -127
- 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
|
|
8
|
-
* @param
|
|
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
|
-
* @
|
|
4
|
-
* @param
|
|
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
|
|
8
|
-
* @param yScale
|
|
9
|
-
* @return:
|
|
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
|
-
*
|
|
17
|
-
* @param {
|
|
18
|
-
* or is its size relative to the group size?
|
|
19
|
-
* @returns {
|
|
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
|
-
*
|
|
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
|
-
(
|
|
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
|
|
15
|
-
* @param
|
|
16
|
-
* @param
|
|
17
|
-
* @param
|
|
18
|
-
* @param
|
|
19
|
-
* @param
|
|
20
|
-
* @param
|
|
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
|
|
23
|
-
*
|
|
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
|
|
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
|
|
60
|
-
* @param
|
|
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 {
|
|
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
|
|
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
|
|
139
|
-
* @param
|
|
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
|
|
178
|
+
* @param {Boolean} isGlobal - If `true` local and global events will trigger
|
|
142
179
|
* the mouse position drawing.
|
|
143
|
-
* @return
|
|
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
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* @
|
|
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
|
|
package/app/scripts/utils/sum.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/**
|
|
2
3
|
* Convenience function for a reducer to sum up a numerical array.
|
|
3
|
-
* @param
|
|
4
|
-
* @param
|
|
5
|
-
* @return
|
|
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
|
-
* @
|
|
27
|
-
* @param
|
|
28
|
-
* @param
|
|
29
|
-
* @
|
|
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 =
|
|
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
|
-
|
|
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
|
|
4
|
-
* @param
|
|
5
|
-
* @param
|
|
6
|
-
* @return
|
|
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,17 +1,16 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
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
|
-
*
|
|
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
|
|
4
|
-
* @return
|
|
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
|
-
* @
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
7
|
-
*
|
|
8
|
-
* @param
|
|
9
|
-
* @return
|
|
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
|
|
6
|
-
* @param
|
|
7
|
-
* @param
|
|
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.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
4
|
-
* @param
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
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
|
-
|
|
11
|
-
|
|
13
|
+
visit,
|
|
14
|
+
includeCombinedTracks = true,
|
|
12
15
|
position = null,
|
|
13
16
|
) =>
|
|
14
17
|
tracks.forEach((track) => {
|
|
15
|
-
if (
|
|
16
|
-
|
|
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;
|