@genome-spy/core 0.30.0 → 0.30.3
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/dist/index.es.js +16379 -0
- package/dist/index.js +43 -43
- package/package.json +10 -7
- package/src/data/collector.js +0 -183
- package/src/data/collector.test.js +0 -84
- package/src/data/dataFlow.js +0 -148
- package/src/data/dataFlow.test.js +0 -5
- package/src/data/facetNode.js +0 -17
- package/src/data/flow.test.js +0 -72
- package/src/data/flowBatch.d.ts +0 -40
- package/src/data/flowNode.js +0 -283
- package/src/data/flowNode.test.js +0 -50
- package/src/data/flowOptimizer.js +0 -123
- package/src/data/flowOptimizer.test.js +0 -193
- package/src/data/flowTestUtils.js +0 -63
- package/src/data/formats/fasta.js +0 -32
- package/src/data/formats/fasta.test.js +0 -27
- package/src/data/sources/dataSource.js +0 -22
- package/src/data/sources/dataSourceFactory.js +0 -24
- package/src/data/sources/dataUtils.js +0 -78
- package/src/data/sources/dynamicCallbackSource.js +0 -57
- package/src/data/sources/dynamicSource.js +0 -37
- package/src/data/sources/inlineSource.js +0 -67
- package/src/data/sources/inlineSource.test.js +0 -56
- package/src/data/sources/namedSource.js +0 -79
- package/src/data/sources/sequenceSource.js +0 -46
- package/src/data/sources/sequenceSource.test.js +0 -46
- package/src/data/sources/urlSource.js +0 -74
- package/src/data/transforms/aggregate.js +0 -70
- package/src/data/transforms/clone.js +0 -40
- package/src/data/transforms/clone.test.js +0 -11
- package/src/data/transforms/coverage.js +0 -187
- package/src/data/transforms/coverage.test.js +0 -123
- package/src/data/transforms/filter.js +0 -37
- package/src/data/transforms/filter.test.js +0 -18
- package/src/data/transforms/filterScoredLabels.js +0 -134
- package/src/data/transforms/flattenCompressedExons.js +0 -57
- package/src/data/transforms/flattenDelimited.js +0 -74
- package/src/data/transforms/flattenDelimited.test.js +0 -87
- package/src/data/transforms/flattenSequence.js +0 -39
- package/src/data/transforms/flattenSequence.test.js +0 -34
- package/src/data/transforms/formula.js +0 -39
- package/src/data/transforms/formula.test.js +0 -19
- package/src/data/transforms/identifier.js +0 -108
- package/src/data/transforms/identifier.test.js +0 -83
- package/src/data/transforms/linearizeGenomicCoordinate.js +0 -101
- package/src/data/transforms/measureText.js +0 -44
- package/src/data/transforms/pileup.js +0 -128
- package/src/data/transforms/pileup.test.js +0 -70
- package/src/data/transforms/project.js +0 -41
- package/src/data/transforms/project.test.js +0 -32
- package/src/data/transforms/regexExtract.js +0 -61
- package/src/data/transforms/regexExtract.test.js +0 -67
- package/src/data/transforms/regexFold.js +0 -141
- package/src/data/transforms/regexFold.test.js +0 -160
- package/src/data/transforms/sample.js +0 -101
- package/src/data/transforms/sample.test.js +0 -38
- package/src/data/transforms/stack.js +0 -137
- package/src/data/transforms/stack.test.js +0 -91
- package/src/data/transforms/transformFactory.js +0 -60
- package/src/embedApi.d.ts +0 -67
- package/src/encoder/accessor.js +0 -82
- package/src/encoder/accessor.test.js +0 -47
- package/src/encoder/encoder.js +0 -394
- package/src/encoder/encoder.test.js +0 -98
- package/src/fonts/Lato-Regular.json +0 -1267
- package/src/fonts/Lato-Regular.png +0 -0
- package/src/fonts/OFL.txt +0 -93
- package/src/fonts/README.md +0 -3
- package/src/fonts/bmFont.d.ts +0 -58
- package/src/fonts/bmFontManager.js +0 -357
- package/src/fonts/bmFontMetrics.js +0 -108
- package/src/genome/genome.js +0 -317
- package/src/genome/genome.test.js +0 -188
- package/src/genome/genomeStore.js +0 -54
- package/src/genome/locusFormat.js +0 -31
- package/src/genome/scaleIndex.d.ts +0 -38
- package/src/genome/scaleIndex.js +0 -166
- package/src/genome/scaleIndex.test.js +0 -78
- package/src/genome/scaleLocus.d.ts +0 -11
- package/src/genome/scaleLocus.js +0 -108
- package/src/genome/scaleLocus.test.js +0 -4
- package/src/genomeSpy.js +0 -785
- package/src/gl/arrayBuilder.js +0 -199
- package/src/gl/dataToVertices.js +0 -636
- package/src/gl/includes/common.glsl +0 -63
- package/src/gl/includes/picking.fragment.glsl +0 -1
- package/src/gl/includes/picking.vertex.glsl +0 -27
- package/src/gl/includes/sampleFacet.glsl +0 -107
- package/src/gl/includes/scales.glsl +0 -112
- package/src/gl/link.fragment.glsl +0 -18
- package/src/gl/link.vertex.glsl +0 -111
- package/src/gl/point.fragment.glsl +0 -123
- package/src/gl/point.vertex.glsl +0 -129
- package/src/gl/rect.fragment.glsl +0 -51
- package/src/gl/rect.vertex.glsl +0 -114
- package/src/gl/rule.fragment.glsl +0 -52
- package/src/gl/rule.vertex.glsl +0 -89
- package/src/gl/text.fragment.glsl +0 -31
- package/src/gl/text.vertex.glsl +0 -246
- package/src/gl/webGLHelper.js +0 -504
- package/src/img/bowtie.svg +0 -1
- package/src/img/genomespy-favicon.svg +0 -34
- package/src/index.html +0 -11
- package/src/index.js +0 -128
- package/src/marks/link.js +0 -175
- package/src/marks/mark.js +0 -975
- package/src/marks/markUtils.js +0 -125
- package/src/marks/pointMark.js +0 -251
- package/src/marks/rectMark.js +0 -241
- package/src/marks/rule.js +0 -250
- package/src/marks/text.js +0 -278
- package/src/node_modules/.vitest/results.json +0 -1
- package/src/scale/colorUtils.js +0 -184
- package/src/scale/glslScaleGenerator.js +0 -502
- package/src/scale/scale.js +0 -451
- package/src/scale/scale.test.js +0 -324
- package/src/scale/ticks.js +0 -203
- package/src/scale/ticks.test.js +0 -40
- package/src/singlePageApp.js +0 -13
- package/src/spec/axis.d.ts +0 -296
- package/src/spec/channel.d.ts +0 -430
- package/src/spec/data.d.ts +0 -196
- package/src/spec/font.d.ts +0 -15
- package/src/spec/genome.d.ts +0 -35
- package/src/spec/mark.d.ts +0 -429
- package/src/spec/root.d.ts +0 -17
- package/src/spec/sampleView.d.ts +0 -180
- package/src/spec/scale.d.ts +0 -273
- package/src/spec/title.d.ts +0 -102
- package/src/spec/tooltip.d.ts +0 -9
- package/src/spec/transform.d.ts +0 -479
- package/src/spec/view.d.ts +0 -201
- package/src/styles/genome-spy.scss +0 -153
- package/src/tooltip/dataTooltipHandler.js +0 -64
- package/src/tooltip/refseqGeneTooltipHandler.js +0 -78
- package/src/tooltip/tooltipHandler.ts +0 -12
- package/src/types/filetypes.d.ts +0 -14
- package/src/types/flatqueue.d.ts +0 -53
- package/src/types/glsl.d.ts +0 -4
- package/src/types/internmap.d.ts +0 -22
- package/src/types/object.d.ts +0 -21
- package/src/types/vega-loader.d.ts +0 -1
- package/src/types/vega-scale.d.ts +0 -60
- package/src/utils/addBaseUrl.js +0 -19
- package/src/utils/addBaseUrl.test.js +0 -22
- package/src/utils/animator.js +0 -83
- package/src/utils/arrayUtils.js +0 -61
- package/src/utils/binnedIndex.js +0 -167
- package/src/utils/binnedIndex.test.js +0 -155
- package/src/utils/clamp.js +0 -8
- package/src/utils/cloner.js +0 -34
- package/src/utils/cloner.test.js +0 -24
- package/src/utils/coalesce.js +0 -11
- package/src/utils/coalesce.test.js +0 -16
- package/src/utils/concatIterables.js +0 -26
- package/src/utils/concatIterables.test.js +0 -8
- package/src/utils/debounce.js +0 -37
- package/src/utils/domainArray.js +0 -216
- package/src/utils/domainArray.test.js +0 -130
- package/src/utils/eerp.js +0 -13
- package/src/utils/expression.js +0 -32
- package/src/utils/field.js +0 -28
- package/src/utils/formatObject.js +0 -31
- package/src/utils/indexer.js +0 -43
- package/src/utils/indexer.test.js +0 -47
- package/src/utils/inertia.js +0 -124
- package/src/utils/interactionEvent.js +0 -33
- package/src/utils/iterateNestedMaps.js +0 -21
- package/src/utils/iterateNestedMaps.test.js +0 -33
- package/src/utils/kWayMerge.js +0 -42
- package/src/utils/kWayMerge.test.js +0 -26
- package/src/utils/layout/flexLayout.js +0 -368
- package/src/utils/layout/flexLayout.test.js +0 -311
- package/src/utils/layout/grid.js +0 -95
- package/src/utils/layout/grid.test.js +0 -71
- package/src/utils/layout/padding.js +0 -120
- package/src/utils/layout/point.js +0 -23
- package/src/utils/layout/rectangle.js +0 -288
- package/src/utils/layout/rectangle.test.js +0 -172
- package/src/utils/mergeObjects.js +0 -99
- package/src/utils/mergeObjects.test.js +0 -42
- package/src/utils/numberExtractor.js +0 -24
- package/src/utils/numberExtractor.test.js +0 -6
- package/src/utils/point.js +0 -14
- package/src/utils/propertyCacher.js +0 -70
- package/src/utils/propertyCacher.test.js +0 -85
- package/src/utils/propertyCoalescer.js +0 -42
- package/src/utils/propertyCoalescer.test.js +0 -22
- package/src/utils/reservationMap.js +0 -103
- package/src/utils/reservationMap.test.js +0 -20
- package/src/utils/scaleNull.js +0 -19
- package/src/utils/setOperations.js +0 -75
- package/src/utils/smoothstep.js +0 -10
- package/src/utils/throttle.js +0 -34
- package/src/utils/topK.js +0 -76
- package/src/utils/topK.test.js +0 -64
- package/src/utils/transition.js +0 -74
- package/src/utils/ui/tooltip.js +0 -189
- package/src/utils/url.js +0 -22
- package/src/utils/variableTools.js +0 -24
- package/src/utils/variableTools.test.js +0 -13
- package/src/view/axisResolution.js +0 -140
- package/src/view/axisResolution.test.js +0 -201
- package/src/view/axisView.js +0 -747
- package/src/view/concatView.js +0 -45
- package/src/view/containerView.js +0 -159
- package/src/view/facetView.js +0 -491
- package/src/view/flowBuilder.js +0 -367
- package/src/view/flowBuilder.test.js +0 -125
- package/src/view/gridView.js +0 -786
- package/src/view/implicitRootView.js +0 -14
- package/src/view/importView.js +0 -19
- package/src/view/layerView.js +0 -74
- package/src/view/rendering.d.ts +0 -44
- package/src/view/renderingContext/compositeViewRenderingContext.js +0 -51
- package/src/view/renderingContext/deferredViewRenderingContext.js +0 -176
- package/src/view/renderingContext/layoutRecorderViewRenderingContext.js +0 -128
- package/src/view/renderingContext/simpleViewRenderingContext.js +0 -64
- package/src/view/renderingContext/svgViewRenderingContext.js +0 -125
- package/src/view/renderingContext/viewRenderingContext.js +0 -41
- package/src/view/scaleResolution.js +0 -797
- package/src/view/scaleResolution.test.js +0 -572
- package/src/view/scaleResolutionApi.d.ts +0 -40
- package/src/view/testUtils.js +0 -51
- package/src/view/title.js +0 -165
- package/src/view/unitView.js +0 -382
- package/src/view/view.js +0 -612
- package/src/view/view.test.js +0 -214
- package/src/view/viewContext.d.ts +0 -62
- package/src/view/viewFactory.js +0 -181
- package/src/view/viewFactory.test.js +0 -17
- package/src/view/viewUtils.js +0 -327
- package/src/view/zoom.js +0 -89
package/src/utils/domainArray.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {boolean | number | string} scalar
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export class DomainArray /** @type {Array<scalar>} */ extends Array {
|
|
6
|
-
constructor() {
|
|
7
|
-
super();
|
|
8
|
-
/** @type {string} */
|
|
9
|
-
this.type = undefined;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
*
|
|
14
|
-
* @param {scalar} value
|
|
15
|
-
* @returns {DomainArray}
|
|
16
|
-
*/
|
|
17
|
-
extend(value) {
|
|
18
|
-
return this;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
* @param {Iterable<scalar>} values
|
|
24
|
-
* @returns {DomainArray}
|
|
25
|
-
*/
|
|
26
|
-
extendAll(values) {
|
|
27
|
-
if (values instanceof DomainArray && values.type != this.type) {
|
|
28
|
-
throw new Error(
|
|
29
|
-
`Cannot combine different types of domains: ${this.type} and ${values.type}`
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
for (const value of values) {
|
|
34
|
-
this.extend(value);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return this;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @param {Iterable<T>} values
|
|
42
|
-
* @param {function(T):scalar} [accessor]
|
|
43
|
-
* @returns {DomainArray}
|
|
44
|
-
* @template T
|
|
45
|
-
*/
|
|
46
|
-
extendAllWithAccessor(values, accessor) {
|
|
47
|
-
for (const value of values) {
|
|
48
|
-
this.extend(accessor(value));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return this;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export class QuantitativeDomain extends DomainArray {
|
|
56
|
-
constructor() {
|
|
57
|
-
super();
|
|
58
|
-
this.type = "quantitative";
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
*
|
|
63
|
-
* @param {scalar} value
|
|
64
|
-
* @returns {DomainArray}
|
|
65
|
-
*/
|
|
66
|
-
extend(value) {
|
|
67
|
-
if (value === null || value === undefined || Number.isNaN(value)) {
|
|
68
|
-
return this;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
value = +value;
|
|
72
|
-
|
|
73
|
-
if (this.length) {
|
|
74
|
-
if (value < this[0]) {
|
|
75
|
-
this[0] = value;
|
|
76
|
-
} else if (value > this[1]) {
|
|
77
|
-
this[1] = value;
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
this.push(value);
|
|
81
|
-
this.push(value);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return this;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Builder that tries to preserve the order
|
|
90
|
-
*/
|
|
91
|
-
export class OrdinalDomain extends DomainArray {
|
|
92
|
-
constructor() {
|
|
93
|
-
super();
|
|
94
|
-
this.type = "ordinal";
|
|
95
|
-
|
|
96
|
-
/** @type {Set<scalar>} */
|
|
97
|
-
this.uniqueValues = new Set();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
*
|
|
102
|
-
* @param {scalar} value
|
|
103
|
-
* @returns {DomainArray}
|
|
104
|
-
*/
|
|
105
|
-
extend(value) {
|
|
106
|
-
if (value === null || value === undefined || Number.isNaN(value)) {
|
|
107
|
-
return this;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (!this.uniqueValues.has(value)) {
|
|
111
|
-
this.uniqueValues.add(value);
|
|
112
|
-
this.push(value);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return this;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export class NominalDomain extends OrdinalDomain {
|
|
120
|
-
constructor() {
|
|
121
|
-
super();
|
|
122
|
-
this.type = "nominal";
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export class PiecewiseDomain extends DomainArray {
|
|
127
|
-
/**
|
|
128
|
-
*
|
|
129
|
-
* @param {number[]} initialDomain
|
|
130
|
-
*/
|
|
131
|
-
constructor(initialDomain) {
|
|
132
|
-
super();
|
|
133
|
-
|
|
134
|
-
let sum = 0;
|
|
135
|
-
for (let i = 1; i < initialDomain.length; i++) {
|
|
136
|
-
sum += Math.sign(initialDomain[i] - initialDomain[i - 1]);
|
|
137
|
-
}
|
|
138
|
-
if (Math.abs(sum) != initialDomain.length - 1) {
|
|
139
|
-
throw new Error(
|
|
140
|
-
"Piecewise domain must be strictly increasing or decreasing: " +
|
|
141
|
-
JSON.stringify(initialDomain)
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
initialDomain.forEach((x) => this.push(x));
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
*
|
|
150
|
-
* @param {scalar} value
|
|
151
|
-
* @returns {DomainArray}
|
|
152
|
-
*/
|
|
153
|
-
extend(value) {
|
|
154
|
-
if (this.includes(value)) {
|
|
155
|
-
return this;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
throw new Error(
|
|
159
|
-
"Piecewise domains are immutable and cannot be unioned!"
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* @type Object.<string, typeof DomainArray>
|
|
166
|
-
*/
|
|
167
|
-
const domainTypes = {
|
|
168
|
-
quantitative: QuantitativeDomain,
|
|
169
|
-
index: QuantitativeDomain,
|
|
170
|
-
locus: QuantitativeDomain,
|
|
171
|
-
nominal: NominalDomain,
|
|
172
|
-
ordinal: OrdinalDomain,
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
*
|
|
177
|
-
* @param {string} type
|
|
178
|
-
* @param {scalar[]} [initialDomain]
|
|
179
|
-
*/
|
|
180
|
-
export default function createDomain(type, initialDomain) {
|
|
181
|
-
if (type == "quantitative" && isPiecewiseArray(initialDomain)) {
|
|
182
|
-
const b = new PiecewiseDomain(/** @type {number[]} */ (initialDomain));
|
|
183
|
-
b.type = type;
|
|
184
|
-
return b;
|
|
185
|
-
} else if (domainTypes[type]) {
|
|
186
|
-
const b = new domainTypes[type]();
|
|
187
|
-
b.type = type;
|
|
188
|
-
if (initialDomain) {
|
|
189
|
-
b.extendAll(initialDomain);
|
|
190
|
-
}
|
|
191
|
-
return b;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
throw new Error("Unknown type: " + type);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* For unit tests
|
|
199
|
-
*
|
|
200
|
-
* @param {DomainArray | any[]} domainArray
|
|
201
|
-
*/
|
|
202
|
-
export function toRegularArray(domainArray) {
|
|
203
|
-
return [...domainArray];
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* @param {scalar[]} array
|
|
208
|
-
*/
|
|
209
|
-
function isPiecewiseArray(array) {
|
|
210
|
-
return (
|
|
211
|
-
array &&
|
|
212
|
-
array.length > 0 &&
|
|
213
|
-
array.length != 2 &&
|
|
214
|
-
array.every((x) => typeof x === "number")
|
|
215
|
-
);
|
|
216
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
2
|
-
import createDomain, {
|
|
3
|
-
toRegularArray as r,
|
|
4
|
-
PiecewiseDomain,
|
|
5
|
-
} from "./domainArray";
|
|
6
|
-
|
|
7
|
-
describe("Build quantitative domains", () => {
|
|
8
|
-
test("Empty domain", () => {
|
|
9
|
-
const b = createDomain("quantitative");
|
|
10
|
-
expect(r(b)).toEqual([]);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test("Extends by one value at a time", () => {
|
|
14
|
-
const b = createDomain("quantitative");
|
|
15
|
-
b.extend(2);
|
|
16
|
-
b.extend(1);
|
|
17
|
-
b.extend(null);
|
|
18
|
-
b.extend(undefined);
|
|
19
|
-
b.extend(NaN);
|
|
20
|
-
b.extend(5);
|
|
21
|
-
b.extend(4);
|
|
22
|
-
expect(r(b)).toEqual([1, 5]);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test("Extends with an iterable", () => {
|
|
26
|
-
const b = createDomain("quantitative");
|
|
27
|
-
b.extendAll([2, 1, null, undefined, NaN, 5, 4]);
|
|
28
|
-
expect(r(b)).toEqual([1, 5]);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test("Extends with an iterable and an accessor", () => {
|
|
32
|
-
const b = createDomain("quantitative");
|
|
33
|
-
b.extendAllWithAccessor(
|
|
34
|
-
[
|
|
35
|
-
{ x: 2 },
|
|
36
|
-
{ x: 1 },
|
|
37
|
-
{ x: null },
|
|
38
|
-
{ x: undefined },
|
|
39
|
-
{ x: NaN },
|
|
40
|
-
{ x: 5 },
|
|
41
|
-
{ x: 4 },
|
|
42
|
-
],
|
|
43
|
-
(d) => d.x
|
|
44
|
-
);
|
|
45
|
-
expect(r(b)).toEqual([1, 5]);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test("Coerces to number", () => {
|
|
49
|
-
const b = createDomain("quantitative");
|
|
50
|
-
expect(r(b.extend("123"))).toEqual([123, 123]);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe("Build ordinal domains", () => {
|
|
55
|
-
// Note: nominal is an unordered abstraction of ordinal. Testing just ordinal is enough.
|
|
56
|
-
|
|
57
|
-
test("Empty domain", () => {
|
|
58
|
-
const b = createDomain("ordinal");
|
|
59
|
-
expect(r(b)).toEqual([]);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test("Extends by one value at a time, preserves order", () => {
|
|
63
|
-
const b = createDomain("ordinal");
|
|
64
|
-
b.extend("a");
|
|
65
|
-
b.extend("b");
|
|
66
|
-
b.extend("c");
|
|
67
|
-
b.extend("b");
|
|
68
|
-
b.extend(null);
|
|
69
|
-
b.extend(undefined);
|
|
70
|
-
b.extend(NaN);
|
|
71
|
-
b.extend("d");
|
|
72
|
-
expect(r(b)).toEqual(["a", "b", "c", "d"]);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe("Build piecewise domains", () => {
|
|
77
|
-
test("Creates a piecewise domain", () => {
|
|
78
|
-
expect(createDomain("quantitative", [1])).toBeInstanceOf(
|
|
79
|
-
PiecewiseDomain
|
|
80
|
-
);
|
|
81
|
-
expect(createDomain("quantitative", [1, 2, 3])).toBeInstanceOf(
|
|
82
|
-
PiecewiseDomain
|
|
83
|
-
);
|
|
84
|
-
expect(createDomain("quantitative", [1, 2, 3, 4])).toBeInstanceOf(
|
|
85
|
-
PiecewiseDomain
|
|
86
|
-
);
|
|
87
|
-
expect(createDomain("quantitative", [3, 2, 1])).toBeInstanceOf(
|
|
88
|
-
PiecewiseDomain
|
|
89
|
-
);
|
|
90
|
-
expect(r(createDomain("quantitative", [3, 2, 1]))).toEqual([3, 2, 1]);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
test("Throws on domain that is not stricly increasing or decreasing", () => {
|
|
94
|
-
expect(() => createDomain("quantitative", [2, 1, 3])).toThrow();
|
|
95
|
-
expect(() => createDomain("quantitative", [2, 3, 1])).toThrow();
|
|
96
|
-
expect(() => createDomain("quantitative", [3, 0, 2])).toThrow();
|
|
97
|
-
expect(() => createDomain("quantitative", [0, 3, 2])).toThrow();
|
|
98
|
-
expect(() => createDomain("quantitative", [1, 2, 2, 3])).toThrow();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
test("Throws on mutation attempts", () => {
|
|
102
|
-
expect(() =>
|
|
103
|
-
createDomain("quantitative", [1, 2, 3]).extend(4)
|
|
104
|
-
).toThrow();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
test("Does not throw when extending with existing value", () => {
|
|
108
|
-
expect(r(createDomain("quantitative", [1, 2, 3]).extend(2))).toEqual([
|
|
109
|
-
1, 2, 3,
|
|
110
|
-
]);
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
describe("Annotations", () => {
|
|
115
|
-
test("Quantitative domain is annotated", () =>
|
|
116
|
-
expect(createDomain("quantitative").type).toEqual("quantitative"));
|
|
117
|
-
|
|
118
|
-
test("Ordinal domain is annotated", () =>
|
|
119
|
-
expect(createDomain("ordinal").type).toEqual("ordinal"));
|
|
120
|
-
|
|
121
|
-
test("Nominal domain is annotated", () =>
|
|
122
|
-
expect(createDomain("nominal").type).toEqual("nominal"));
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
describe("Other stuff", () => {
|
|
126
|
-
test("Throws on extending by other type of domain array", () =>
|
|
127
|
-
expect(() =>
|
|
128
|
-
createDomain("quantitative").extendAll(createDomain("nominal"))
|
|
129
|
-
).toThrow());
|
|
130
|
-
});
|
package/src/utils/eerp.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Exponential interpolation
|
|
3
|
-
*
|
|
4
|
-
* https://twitter.com/FreyaHolmer/status/1068293398073929728
|
|
5
|
-
*
|
|
6
|
-
* @param {number} a
|
|
7
|
-
* @param {number} b
|
|
8
|
-
* @param {number} t
|
|
9
|
-
* @returns
|
|
10
|
-
*/
|
|
11
|
-
export default function (a, b, t) {
|
|
12
|
-
return a * Math.pow(b / a, t);
|
|
13
|
-
}
|
package/src/utils/expression.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { parseExpression, codegenExpression } from "vega-expression";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* @param {string} expr
|
|
6
|
-
*/
|
|
7
|
-
export default function createFunction(expr, global = {}) {
|
|
8
|
-
const cg = codegenExpression({
|
|
9
|
-
forbidden: [],
|
|
10
|
-
allowed: ["datum"],
|
|
11
|
-
globalvar: "global",
|
|
12
|
-
fieldvar: "datum",
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
const parsed = parseExpression(expr);
|
|
17
|
-
const generatedCode = cg(parsed);
|
|
18
|
-
|
|
19
|
-
// eslint-disable-next-line no-new-func
|
|
20
|
-
const fn = Function(
|
|
21
|
-
"datum",
|
|
22
|
-
"global",
|
|
23
|
-
`"use strict"; return (${generatedCode.code});`
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
const exprFunction = /** @param {object} x */ (x) => fn(x, global);
|
|
27
|
-
exprFunction.fields = generatedCode.fields;
|
|
28
|
-
return exprFunction;
|
|
29
|
-
} catch (e) {
|
|
30
|
-
throw new Error(`Invalid expression: ${expr}, ${e.message}`);
|
|
31
|
-
}
|
|
32
|
-
}
|
package/src/utils/field.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { field as vegaField, accessor } from "vega-util";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates an accessor function based on the field expression.
|
|
5
|
-
* This is equivalent to vega-util's field function but generates optimized
|
|
6
|
-
* accessors for trivial cases.
|
|
7
|
-
*
|
|
8
|
-
* Function calls with polymorphic objects spoil the inline caching that
|
|
9
|
-
* virtually all JavaScript engines use. Thus, we generate code and compile
|
|
10
|
-
* always a new function to "guarantee" homomorphims, given that only same
|
|
11
|
-
* type of objects are even passed to the accessor.
|
|
12
|
-
*
|
|
13
|
-
* Read more at: https://mrale.ph/blog/2015/01/11/whats-up-with-monomorphism.html
|
|
14
|
-
*
|
|
15
|
-
* @param {string} fieldExpr
|
|
16
|
-
* @param {string} [name]
|
|
17
|
-
*/
|
|
18
|
-
export function field(fieldExpr, name = fieldExpr) {
|
|
19
|
-
if (/^[A-Za-z0-9_]+$/.test(fieldExpr)) {
|
|
20
|
-
// eslint-disable-next-line no-new-func
|
|
21
|
-
const fn = /** @type {import("vega-util").AccessorFn} */ (
|
|
22
|
-
new Function("datum", `return datum[${JSON.stringify(fieldExpr)}]`)
|
|
23
|
-
);
|
|
24
|
-
return accessor(fn, [fieldExpr], name);
|
|
25
|
-
} else {
|
|
26
|
-
return vegaField(fieldExpr);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { isNumber, isString, isBoolean } from "vega-util";
|
|
2
|
-
import { format as d3format } from "d3-format";
|
|
3
|
-
import { html } from "lit-html";
|
|
4
|
-
|
|
5
|
-
const numberFormat = d3format(".4~r");
|
|
6
|
-
const exponentNumberFormat = d3format(".4~e");
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
* @param {any} object Object to format
|
|
11
|
-
*/
|
|
12
|
-
export default function formatObject(object) {
|
|
13
|
-
if (object === null) {
|
|
14
|
-
return html` <span class="na">NA</span> `;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (isString(object)) {
|
|
18
|
-
return object.substring(0, 30);
|
|
19
|
-
} else if (Number.isInteger(object)) {
|
|
20
|
-
return "" + object;
|
|
21
|
-
} else if (isNumber(object)) {
|
|
22
|
-
return Math.abs(object) > Math.pow(10, 8) ||
|
|
23
|
-
Math.abs(object) < Math.pow(10, -8)
|
|
24
|
-
? exponentNumberFormat(object)
|
|
25
|
-
: numberFormat(object);
|
|
26
|
-
} else if (isBoolean(object)) {
|
|
27
|
-
return object ? "True" : "False";
|
|
28
|
-
} else {
|
|
29
|
-
return "?" + typeof object + " " + object;
|
|
30
|
-
}
|
|
31
|
-
}
|
package/src/utils/indexer.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Assigns unique values an index number in the order they are encountered.
|
|
3
|
-
*
|
|
4
|
-
* TODO: What about undefined?
|
|
5
|
-
*
|
|
6
|
-
* @template T
|
|
7
|
-
*/
|
|
8
|
-
export default function createIndexer() {
|
|
9
|
-
let counter = 0;
|
|
10
|
-
|
|
11
|
-
/** @type {Map<T, number>} */
|
|
12
|
-
const values = new Map();
|
|
13
|
-
|
|
14
|
-
/** @param {T} value */
|
|
15
|
-
const indexer = (value) => {
|
|
16
|
-
let index = values.get(value);
|
|
17
|
-
if (index === undefined) {
|
|
18
|
-
index = counter++;
|
|
19
|
-
values.set(value, index);
|
|
20
|
-
}
|
|
21
|
-
return index;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/** @param {Iterable<T>} iterable */
|
|
25
|
-
indexer.addAll = (iterable) => {
|
|
26
|
-
for (const value of iterable) {
|
|
27
|
-
indexer(value);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/** @param {number} value */
|
|
32
|
-
indexer.invert = (value) => {
|
|
33
|
-
for (const entry of values.entries()) {
|
|
34
|
-
if (entry[1] == value) {
|
|
35
|
-
return entry[0];
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
indexer.domain = () => [...values.keys()];
|
|
41
|
-
|
|
42
|
-
return indexer;
|
|
43
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest";
|
|
2
|
-
import createIndexer from "./indexer";
|
|
3
|
-
|
|
4
|
-
test("Index values one by one", () => {
|
|
5
|
-
const indexer = createIndexer();
|
|
6
|
-
|
|
7
|
-
expect(indexer("a")).toEqual(0);
|
|
8
|
-
expect(indexer("b")).toEqual(1);
|
|
9
|
-
expect(indexer("c")).toEqual(2);
|
|
10
|
-
expect(indexer("a")).toEqual(0);
|
|
11
|
-
expect(indexer("c")).toEqual(2);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
test("Index multiple values (predefined domain)", () => {
|
|
15
|
-
const indexer = createIndexer();
|
|
16
|
-
|
|
17
|
-
indexer.addAll(["a", "b", "c"]);
|
|
18
|
-
|
|
19
|
-
expect(indexer("d")).toEqual(3);
|
|
20
|
-
expect(indexer("a")).toEqual(0);
|
|
21
|
-
expect(indexer("b")).toEqual(1);
|
|
22
|
-
expect(indexer("c")).toEqual(2);
|
|
23
|
-
expect(indexer("d")).toEqual(3);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("Indexer inverts index numbers", () => {
|
|
27
|
-
const indexer = createIndexer();
|
|
28
|
-
|
|
29
|
-
indexer.addAll(["a", "b", "c"]);
|
|
30
|
-
|
|
31
|
-
expect(indexer.invert(0)).toEqual("a");
|
|
32
|
-
expect(indexer.invert(1)).toEqual("b");
|
|
33
|
-
expect(indexer.invert(2)).toEqual("c");
|
|
34
|
-
expect(indexer.invert(3)).toBeUndefined();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("Indexer return correct domain", () => {
|
|
38
|
-
const indexer = createIndexer();
|
|
39
|
-
|
|
40
|
-
expect(indexer("a")).toEqual(0);
|
|
41
|
-
expect(indexer("b")).toEqual(1);
|
|
42
|
-
expect(indexer("c")).toEqual(2);
|
|
43
|
-
expect(indexer("a")).toEqual(0);
|
|
44
|
-
expect(indexer("c")).toEqual(2);
|
|
45
|
-
|
|
46
|
-
expect(indexer.domain()).toEqual(["a", "b", "c"]);
|
|
47
|
-
});
|
package/src/utils/inertia.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { lerp } from "vega-util";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates some inertia, mainly for zooming with a mechanical mouse wheel
|
|
5
|
-
*/
|
|
6
|
-
export default class Inertia {
|
|
7
|
-
/**
|
|
8
|
-
* @param {import("./animator").default} animator
|
|
9
|
-
* @param {boolean} [disabled] Just call the callback directly
|
|
10
|
-
*/
|
|
11
|
-
constructor(animator, disabled) {
|
|
12
|
-
this.animator = animator;
|
|
13
|
-
this.disabled = !!disabled;
|
|
14
|
-
this.damping = 0.015;
|
|
15
|
-
this.acceleration = 0.3; // per event
|
|
16
|
-
/** Use acceleration if the momentum step is greater than X */
|
|
17
|
-
this.accelerationThreshold = 100;
|
|
18
|
-
this.lowerLimit = 0.5; // When to stop updating
|
|
19
|
-
this.loop = false;
|
|
20
|
-
|
|
21
|
-
this.momentum = 0;
|
|
22
|
-
this.timestamp = 0;
|
|
23
|
-
/** @type {function(number):void} */
|
|
24
|
-
this.callback = null;
|
|
25
|
-
|
|
26
|
-
this._transitionCallback = this.animate.bind(this);
|
|
27
|
-
this.clear();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
clear() {
|
|
31
|
-
/** @type {number} */
|
|
32
|
-
this.momentum = 0;
|
|
33
|
-
this.timestamp = null;
|
|
34
|
-
this.loop = null;
|
|
35
|
-
this.callback = null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
cancel() {
|
|
39
|
-
if (this.loop) {
|
|
40
|
-
this.animator.cancelTransition(this._transitionCallback);
|
|
41
|
-
this.clear();
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
*
|
|
47
|
-
* @param {number} value
|
|
48
|
-
* @param {function(number):void} callback
|
|
49
|
-
*/
|
|
50
|
-
setMomentum(value, callback) {
|
|
51
|
-
if (this.disabled) {
|
|
52
|
-
callback(value);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// This may have some use in the future to improve the behavior of
|
|
57
|
-
// a mechanical mouse wheel:
|
|
58
|
-
// https://github.com/w3c/uievents/issues/181
|
|
59
|
-
|
|
60
|
-
if (value * this.momentum < 0) {
|
|
61
|
-
this.momentum = 0; // Stop if the direction changes
|
|
62
|
-
} else if (Math.abs(value) > this.accelerationThreshold) {
|
|
63
|
-
this.momentum = lerp([this.momentum, value], this.acceleration);
|
|
64
|
-
} else {
|
|
65
|
-
this.momentum = value;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
this.callback = callback;
|
|
69
|
-
|
|
70
|
-
if (!this.loop) {
|
|
71
|
-
this.animate();
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
*
|
|
77
|
-
* @param {number} [timestamp]
|
|
78
|
-
*/
|
|
79
|
-
animate(timestamp) {
|
|
80
|
-
this.callback(this.momentum); // TODO: This is actually a delta, should take the elapsed time into account
|
|
81
|
-
|
|
82
|
-
const timeDelta = timestamp - this.timestamp || 0;
|
|
83
|
-
this.timestamp = timestamp;
|
|
84
|
-
|
|
85
|
-
const velocity = Math.abs(this.momentum);
|
|
86
|
-
|
|
87
|
-
this.momentum =
|
|
88
|
-
Math.sign(this.momentum) *
|
|
89
|
-
Math.max(
|
|
90
|
-
0,
|
|
91
|
-
velocity - ((velocity * this.damping) ** 1.5 + 0.04) * timeDelta
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
if (Math.abs(this.momentum) > this.lowerLimit) {
|
|
95
|
-
this.loop = true;
|
|
96
|
-
this.animator.requestTransition(this._transitionCallback);
|
|
97
|
-
} else {
|
|
98
|
-
this.clear();
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* @param {T} event
|
|
105
|
-
* @template T
|
|
106
|
-
*/
|
|
107
|
-
export function makeEventTemplate(event) {
|
|
108
|
-
/** @type {Partial<Record<keyof T, any>>} */
|
|
109
|
-
const template = {};
|
|
110
|
-
const acceptedTypes = ["string", "number", "boolean"];
|
|
111
|
-
const rejectedProps = ["wheelDelta", "wheelDeltaX", "wheelDeltaY"];
|
|
112
|
-
|
|
113
|
-
// eslint-disable-next-line guard-for-in
|
|
114
|
-
for (const key in event) {
|
|
115
|
-
const k = /** @type {keyof T} */ (key);
|
|
116
|
-
if (
|
|
117
|
-
!rejectedProps.includes(key) &&
|
|
118
|
-
acceptedTypes.includes(typeof event[k])
|
|
119
|
-
) {
|
|
120
|
-
template[k] = /** @type {any} */ (event[k]);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return template;
|
|
124
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This class wraps a MouseEvent (or similar) and allows for
|
|
3
|
-
* its propagation through the view hierarchy in a similar manner
|
|
4
|
-
* as in the DOM.
|
|
5
|
-
*/
|
|
6
|
-
export default class InteractionEvent {
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
* @param {import("./layout/point").default} point Event coordinates
|
|
10
|
-
* inside the visualization canvas.
|
|
11
|
-
* @param {UIEvent} uiEvent The event to be wrapped
|
|
12
|
-
*/
|
|
13
|
-
constructor(point, uiEvent) {
|
|
14
|
-
this.point = point;
|
|
15
|
-
this.uiEvent = uiEvent;
|
|
16
|
-
this.stopped = false;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* The target is known only in the bubbling phase
|
|
20
|
-
*
|
|
21
|
-
* @type {import("../view/view").default}
|
|
22
|
-
*/
|
|
23
|
-
this.target = undefined;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
stopPropagation() {
|
|
27
|
-
this.stopped = true;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
get type() {
|
|
31
|
-
return this.uiEvent.type;
|
|
32
|
-
}
|
|
33
|
-
}
|