@genome-spy/core 0.66.1 → 0.68.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/dist/bundle/index.es.js +7669 -6115
- package/dist/bundle/index.js +114 -133
- package/dist/schema.json +534 -132
- package/dist/src/data/collector.d.ts +20 -0
- package/dist/src/data/collector.d.ts.map +1 -1
- package/dist/src/data/collector.js +148 -0
- package/dist/src/data/dataFlow.d.ts +6 -0
- package/dist/src/data/dataFlow.d.ts.map +1 -1
- package/dist/src/data/dataFlow.js +10 -0
- package/dist/src/data/flowHandle.d.ts +2 -0
- package/dist/src/data/flowHandle.d.ts.map +1 -1
- package/dist/src/data/flowHandle.js +1 -0
- package/dist/src/data/flowInit.d.ts +12 -4
- package/dist/src/data/flowInit.d.ts.map +1 -1
- package/dist/src/data/flowInit.js +115 -17
- package/dist/src/data/flowNode.d.ts +8 -0
- package/dist/src/data/flowNode.d.ts.map +1 -1
- package/dist/src/data/flowNode.js +18 -0
- package/dist/src/data/keyIndex.d.ts +18 -0
- package/dist/src/data/keyIndex.d.ts.map +1 -0
- package/dist/src/data/keyIndex.js +241 -0
- package/dist/src/data/keyIndex.test.d.ts +2 -0
- package/dist/src/data/keyIndex.test.d.ts.map +1 -0
- package/dist/src/data/sources/dataSource.d.ts.map +1 -1
- package/dist/src/data/sources/dataSource.js +5 -1
- package/dist/src/data/sources/dataSourceFactory.d.ts +14 -12
- package/dist/src/data/sources/dataSourceFactory.d.ts.map +1 -1
- package/dist/src/data/sources/dataSourceFactory.js +52 -16
- package/dist/src/data/sources/lazy/mockLazySource.d.ts +29 -0
- package/dist/src/data/sources/lazy/mockLazySource.d.ts.map +1 -0
- package/dist/src/data/sources/lazy/mockLazySource.js +44 -0
- package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +22 -1
- package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/singleAxisLazySource.js +34 -2
- package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +15 -0
- package/dist/src/data/sources/lazy/tabixSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/tabixSource.js +15 -5
- package/dist/src/data/transforms/stack.d.ts.map +1 -1
- package/dist/src/data/transforms/stack.js +1 -0
- package/dist/src/encoder/accessor.d.ts +43 -0
- package/dist/src/encoder/accessor.d.ts.map +1 -1
- package/dist/src/encoder/accessor.js +164 -0
- package/dist/src/encoder/encoder.d.ts +11 -2
- package/dist/src/encoder/encoder.d.ts.map +1 -1
- package/dist/src/encoder/encoder.js +24 -4
- package/dist/src/encoder/metadataChannels.d.ts +15 -0
- package/dist/src/encoder/metadataChannels.d.ts.map +1 -0
- package/dist/src/encoder/metadataChannels.js +65 -0
- package/dist/src/encoder/metadataChannels.test.d.ts +2 -0
- package/dist/src/encoder/metadataChannels.test.d.ts.map +1 -0
- package/dist/src/genome/scaleLocus.d.ts.map +1 -1
- package/dist/src/genome/scaleLocus.js +14 -1
- package/dist/src/genomeSpy/containerUi.d.ts +0 -1
- package/dist/src/genomeSpy/containerUi.d.ts.map +1 -1
- package/dist/src/genomeSpy/containerUi.js +0 -14
- package/dist/src/genomeSpy/loadingIndicatorManager.d.ts +3 -7
- package/dist/src/genomeSpy/loadingIndicatorManager.d.ts.map +1 -1
- package/dist/src/genomeSpy/loadingIndicatorManager.js +68 -20
- package/dist/src/genomeSpy/loadingStatusRegistry.d.ts +52 -0
- package/dist/src/genomeSpy/loadingStatusRegistry.d.ts.map +1 -0
- package/dist/src/genomeSpy/loadingStatusRegistry.js +86 -0
- package/dist/src/genomeSpy/viewContextFactory.d.ts.map +1 -1
- package/dist/src/genomeSpy/viewContextFactory.js +0 -1
- package/dist/src/genomeSpy/viewDataInit.d.ts +10 -0
- package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -1
- package/dist/src/genomeSpy/viewDataInit.js +166 -2
- package/dist/src/genomeSpy/viewDataInit.test.d.ts +2 -0
- package/dist/src/genomeSpy/viewDataInit.test.d.ts.map +1 -0
- package/dist/src/genomeSpy.d.ts +1 -2
- package/dist/src/genomeSpy.d.ts.map +1 -1
- package/dist/src/genomeSpy.js +69 -27
- package/dist/src/gl/dataToVertices.d.ts.map +1 -1
- package/dist/src/gl/dataToVertices.js +16 -4
- package/dist/src/marks/mark.d.ts.map +1 -1
- package/dist/src/marks/mark.js +18 -11
- package/dist/src/marks/markUtils.js +1 -1
- package/dist/src/scale/scale.d.ts +6 -1
- package/dist/src/scale/scale.d.ts.map +1 -1
- package/dist/src/scale/scale.js +83 -23
- package/dist/src/scales/axisResolution.d.ts.map +1 -1
- package/dist/src/scales/axisResolution.js +10 -0
- package/dist/src/scales/{scaleDomainAggregator.d.ts → domainPlanner.d.ts} +8 -5
- package/dist/src/scales/domainPlanner.d.ts.map +1 -0
- package/dist/src/scales/domainPlanner.js +285 -0
- package/dist/src/scales/domainPlanner.test.d.ts +2 -0
- package/dist/src/scales/domainPlanner.test.d.ts.map +1 -0
- package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
- package/dist/src/scales/scaleInstanceManager.js +8 -4
- package/dist/src/scales/scaleInteractionController.d.ts +6 -0
- package/dist/src/scales/scaleInteractionController.d.ts.map +1 -1
- package/dist/src/scales/scaleInteractionController.js +41 -3
- package/dist/src/scales/scaleResolution.d.ts +19 -16
- package/dist/src/scales/scaleResolution.d.ts.map +1 -1
- package/dist/src/scales/scaleResolution.js +255 -70
- package/dist/src/scales/scaleResolution.test.d.ts.map +1 -1
- package/dist/src/selection/selection.d.ts +21 -0
- package/dist/src/selection/selection.d.ts.map +1 -1
- package/dist/src/selection/selection.js +82 -0
- package/dist/src/spec/channel.d.ts +52 -15
- package/dist/src/spec/data.d.ts +4 -0
- package/dist/src/spec/parameter.d.ts +16 -11
- package/dist/src/spec/testing.d.ts +12 -0
- package/dist/src/spec/testing.d.ts.map +1 -0
- package/dist/src/spec/testing.js +20 -0
- package/dist/src/spec/view.d.ts +45 -10
- package/dist/src/styles/genome-spy.css +3 -31
- package/dist/src/styles/genome-spy.css.d.ts +1 -1
- package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
- package/dist/src/styles/genome-spy.css.js +0 -29
- package/dist/src/types/encoder.d.ts +37 -2
- package/dist/src/types/rendering.d.ts +4 -3
- package/dist/src/types/viewContext.d.ts +0 -14
- package/dist/src/utils/domainArray.d.ts.map +1 -1
- package/dist/src/utils/domainArray.js +3 -0
- package/dist/src/utils/indexer.d.ts +3 -0
- package/dist/src/utils/indexer.d.ts.map +1 -1
- package/dist/src/utils/indexer.js +3 -0
- package/dist/src/utils/throttle.d.ts +4 -1
- package/dist/src/utils/throttle.d.ts.map +1 -1
- package/dist/src/utils/throttle.js +54 -23
- package/dist/src/utils/throttle.test.d.ts +2 -0
- package/dist/src/utils/throttle.test.d.ts.map +1 -0
- package/dist/src/utils/transition.d.ts +21 -0
- package/dist/src/utils/transition.d.ts.map +1 -1
- package/dist/src/utils/transition.js +28 -0
- package/dist/src/utils/ui/tooltip.d.ts.map +1 -1
- package/dist/src/utils/ui/tooltip.js +7 -1
- package/dist/src/utils/ui/tooltip.test.d.ts +2 -0
- package/dist/src/utils/ui/tooltip.test.d.ts.map +1 -0
- package/dist/src/view/axisGridView.d.ts.map +1 -1
- package/dist/src/view/axisGridView.js +22 -5
- package/dist/src/view/axisView.d.ts.map +1 -1
- package/dist/src/view/axisView.js +20 -5
- package/dist/src/view/concatView.js +3 -3
- package/dist/src/view/containerMutationHelper.d.ts.map +1 -1
- package/dist/src/view/containerMutationHelper.js +6 -2
- package/dist/src/view/containerView.d.ts +9 -5
- package/dist/src/view/containerView.d.ts.map +1 -1
- package/dist/src/view/containerView.js +34 -9
- package/dist/src/view/dataReadiness.d.ts +46 -0
- package/dist/src/view/dataReadiness.d.ts.map +1 -0
- package/dist/src/view/dataReadiness.js +267 -0
- package/dist/src/view/dataReadiness.test.d.ts +2 -0
- package/dist/src/view/dataReadiness.test.d.ts.map +1 -0
- package/dist/src/view/facetView.d.ts.map +1 -1
- package/dist/src/view/facetView.js +7 -5
- package/dist/src/view/flowBuilder.d.ts +5 -3
- package/dist/src/view/flowBuilder.d.ts.map +1 -1
- package/dist/src/view/flowBuilder.js +74 -7
- package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
- package/dist/src/view/gridView/gridChild.js +8 -0
- package/dist/src/view/gridView/gridView.d.ts.map +1 -1
- package/dist/src/view/gridView/gridView.js +119 -2
- package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
- package/dist/src/view/gridView/scrollbar.js +3 -0
- package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
- package/dist/src/view/gridView/selectionRect.js +20 -5
- package/dist/src/view/gridView/separatorView.d.ts +51 -0
- package/dist/src/view/gridView/separatorView.d.ts.map +1 -0
- package/dist/src/view/gridView/separatorView.js +275 -0
- package/dist/src/view/layerView.js +3 -3
- package/dist/src/view/layout/flexLayout.d.ts +0 -30
- package/dist/src/view/layout/flexLayout.d.ts.map +1 -1
- package/dist/src/view/layout/flexLayout.js +0 -86
- package/dist/src/view/paramMediator.d.ts +19 -0
- package/dist/src/view/paramMediator.d.ts.map +1 -1
- package/dist/src/view/paramMediator.js +86 -19
- package/dist/src/view/testUtils.d.ts.map +1 -1
- package/dist/src/view/testUtils.js +11 -1
- package/dist/src/view/unitView.d.ts +8 -13
- package/dist/src/view/unitView.d.ts.map +1 -1
- package/dist/src/view/unitView.js +127 -43
- package/dist/src/view/view.d.ts +34 -14
- package/dist/src/view/view.d.ts.map +1 -1
- package/dist/src/view/view.js +119 -9
- package/dist/src/view/viewFactory.d.ts.map +1 -1
- package/dist/src/view/viewFactory.js +20 -1
- package/dist/src/view/viewSelectors.d.ts +148 -0
- package/dist/src/view/viewSelectors.d.ts.map +1 -0
- package/dist/src/view/viewSelectors.js +773 -0
- package/dist/src/view/viewSelectors.test.d.ts +2 -0
- package/dist/src/view/viewSelectors.test.d.ts.map +1 -0
- package/dist/src/view/viewUtils.d.ts +0 -8
- package/dist/src/view/viewUtils.d.ts.map +1 -1
- package/dist/src/view/viewUtils.js +1 -21
- package/package.json +3 -3
- package/dist/src/scales/scaleDomainAggregator.d.ts.map +0 -1
- package/dist/src/scales/scaleDomainAggregator.js +0 -162
- package/dist/src/scales/scaleDomainAggregator.test.d.ts +0 -2
- package/dist/src/scales/scaleDomainAggregator.test.d.ts.map +0 -1
|
@@ -35,6 +35,9 @@ export default class FlowNode {
|
|
|
35
35
|
first: null,
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
+
/** @type {boolean} */
|
|
39
|
+
#initialized = false;
|
|
40
|
+
|
|
38
41
|
/**
|
|
39
42
|
* An object that provides a paramMediator. (Most likely a View)
|
|
40
43
|
*
|
|
@@ -89,11 +92,26 @@ export default class FlowNode {
|
|
|
89
92
|
/**
|
|
90
93
|
* Allows for doing final initialization after the flow structure has been
|
|
91
94
|
* built and optimized. Must be called before any data are to be propagated.
|
|
95
|
+
* Note: Some transforms call initialize() from reset() to rebuild internal
|
|
96
|
+
* fast paths per batch. Use initializeOnce() for graph-level init to avoid
|
|
97
|
+
* double-initialization issues.
|
|
92
98
|
*/
|
|
93
99
|
initialize() {
|
|
94
100
|
// override
|
|
95
101
|
}
|
|
96
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Calls initialize() once per node instance. Intended for graph-level init
|
|
105
|
+
* passes that should not rerun when reusing existing branches.
|
|
106
|
+
*/
|
|
107
|
+
initializeOnce() {
|
|
108
|
+
if (this.#initialized) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
this.initialize();
|
|
112
|
+
this.#initialized = true;
|
|
113
|
+
}
|
|
114
|
+
|
|
97
115
|
/**
|
|
98
116
|
* Dynamically updates the propagator method to allow the JavaScript engine
|
|
99
117
|
* to employ optimizations such as inlining.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazily builds and caches lookup indexes for `encoding.key` fields so that
|
|
3
|
+
* bookmarked point selections can be resolved back to datums efficiently.
|
|
4
|
+
*
|
|
5
|
+
* TODO: Use requestIdleCallback to warm up the index to prevent jank on first access.
|
|
6
|
+
*/
|
|
7
|
+
export default class KeyIndex {
|
|
8
|
+
invalidate(): void;
|
|
9
|
+
/**
|
|
10
|
+
* @param {string[]} keyFields
|
|
11
|
+
* @param {import("../spec/channel.js").Scalar[]} keyTuple
|
|
12
|
+
* @param {Iterable<Data>} facetBatches
|
|
13
|
+
* @returns {Datum | undefined}
|
|
14
|
+
*/
|
|
15
|
+
findDatum(keyFields: string[], keyTuple: import("../spec/channel.js").Scalar[], facetBatches: Iterable<import("./flowNode.js").Data>): import("./flowNode.js").Datum | undefined;
|
|
16
|
+
#private;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=keyIndex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyIndex.d.ts","sourceRoot":"","sources":["../../../src/data/keyIndex.js"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH;IAeI,mBAIC;IAED;;;;;OAKG;IACH,qBALW,MAAM,EAAE,YACR,OAAO,oBAAoB,EAAE,MAAM,EAAE,gBACrC,QAAQ,8BAAM,GACZ,gCAAQ,SAAS,CAwC7B;;CAgGJ"}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { field } from "../utils/field.js";
|
|
2
|
+
|
|
3
|
+
const MULTI_KEY_SEPARATOR = "|";
|
|
4
|
+
const MULTI_KEY_ESCAPE = "\\";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lazily builds and caches lookup indexes for `encoding.key` fields so that
|
|
8
|
+
* bookmarked point selections can be resolved back to datums efficiently.
|
|
9
|
+
*
|
|
10
|
+
* TODO: Use requestIdleCallback to warm up the index to prevent jank on first access.
|
|
11
|
+
*/
|
|
12
|
+
export default class KeyIndex {
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {import("./flowNode.js").Datum} Datum
|
|
15
|
+
* @typedef {import("./flowNode.js").Data} Data
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** @type {Map<import("../spec/channel.js").Scalar | string, Datum> | null} */
|
|
19
|
+
#index = null;
|
|
20
|
+
|
|
21
|
+
/** @type {string[] | null} */
|
|
22
|
+
#keyFields = null;
|
|
23
|
+
|
|
24
|
+
/** @type {boolean} */
|
|
25
|
+
#usesCompositeKey = false;
|
|
26
|
+
|
|
27
|
+
invalidate() {
|
|
28
|
+
this.#index = null;
|
|
29
|
+
this.#keyFields = null;
|
|
30
|
+
this.#usesCompositeKey = false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {string[]} keyFields
|
|
35
|
+
* @param {import("../spec/channel.js").Scalar[]} keyTuple
|
|
36
|
+
* @param {Iterable<Data>} facetBatches
|
|
37
|
+
* @returns {Datum | undefined}
|
|
38
|
+
*/
|
|
39
|
+
findDatum(keyFields, keyTuple, facetBatches) {
|
|
40
|
+
if (!keyFields || keyFields.length === 0) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const fieldList = keyFields.join(", ");
|
|
45
|
+
if (keyFields.length !== keyTuple.length) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Key tuple length ${keyTuple.length} does not match fields [${fieldList}]`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!this.#index || !this.#matchesKeyFields(keyFields)) {
|
|
52
|
+
this.#buildIndex(keyFields, facetBatches);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const canonicalFields = /** @type {string[]} */ (this.#keyFields);
|
|
56
|
+
/** @type {import("../spec/channel.js").Scalar | string} */
|
|
57
|
+
let key;
|
|
58
|
+
if (!this.#usesCompositeKey) {
|
|
59
|
+
const fieldName = canonicalFields[0];
|
|
60
|
+
key = validateKeyComponent(keyTuple[0], fieldName);
|
|
61
|
+
} else {
|
|
62
|
+
let compositeKey = "";
|
|
63
|
+
for (let i = 0; i < keyTuple.length; i++) {
|
|
64
|
+
if (i > 0) {
|
|
65
|
+
compositeKey += MULTI_KEY_SEPARATOR;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const fieldName = canonicalFields[i];
|
|
69
|
+
const value = validateKeyComponent(keyTuple[i], fieldName);
|
|
70
|
+
|
|
71
|
+
compositeKey += encodeKeyPart(value);
|
|
72
|
+
}
|
|
73
|
+
key = compositeKey;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return this.#index.get(key);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {string[]} keyFields
|
|
81
|
+
* @param {Iterable<Data>} facetBatches
|
|
82
|
+
*/
|
|
83
|
+
#buildIndex(keyFields, facetBatches) {
|
|
84
|
+
/** @type {Array<(datum: Datum) => import("../spec/channel.js").Scalar>} */
|
|
85
|
+
const accessors = keyFields.map((fieldName) => field(fieldName));
|
|
86
|
+
/** @type {Map<import("../spec/channel.js").Scalar | string, Datum>} */
|
|
87
|
+
const index = new Map();
|
|
88
|
+
const fieldList = keyFields.join(", ");
|
|
89
|
+
|
|
90
|
+
const usesCompositeKey = keyFields.length !== 1;
|
|
91
|
+
|
|
92
|
+
if (!usesCompositeKey) {
|
|
93
|
+
const accessor = accessors[0];
|
|
94
|
+
const fieldName = keyFields[0];
|
|
95
|
+
for (const data of facetBatches) {
|
|
96
|
+
for (let i = 0, n = data.length; i < n; i++) {
|
|
97
|
+
const datum = data[i];
|
|
98
|
+
const key = validateKeyComponent(
|
|
99
|
+
accessor(datum),
|
|
100
|
+
fieldName
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const previous = index.get(key);
|
|
104
|
+
if (previous !== undefined) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`Duplicate key detected for fields [${fieldList}]: ${JSON.stringify(key)}`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
index.set(key, datum);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
for (const data of facetBatches) {
|
|
115
|
+
for (let i = 0, n = data.length; i < n; i++) {
|
|
116
|
+
const datum = data[i];
|
|
117
|
+
let compositeKey = "";
|
|
118
|
+
for (let j = 0; j < accessors.length; j++) {
|
|
119
|
+
if (j > 0) {
|
|
120
|
+
compositeKey += MULTI_KEY_SEPARATOR;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const fieldName = keyFields[j];
|
|
124
|
+
const value = validateKeyComponent(
|
|
125
|
+
accessors[j](datum),
|
|
126
|
+
fieldName
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
compositeKey += encodeKeyPart(value);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const previous = index.get(compositeKey);
|
|
133
|
+
if (previous !== undefined) {
|
|
134
|
+
const duplicateTuple = accessors.map((accessor) =>
|
|
135
|
+
accessor(datum)
|
|
136
|
+
);
|
|
137
|
+
throw new Error(
|
|
138
|
+
`Duplicate key detected for fields [${fieldList}]: ${JSON.stringify(duplicateTuple)}`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
index.set(compositeKey, datum);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
this.#index = index;
|
|
148
|
+
this.#keyFields = [...keyFields];
|
|
149
|
+
this.#usesCompositeKey = usesCompositeKey;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @param {string[]} keyFields
|
|
154
|
+
* @returns {boolean}
|
|
155
|
+
*/
|
|
156
|
+
#matchesKeyFields(keyFields) {
|
|
157
|
+
if (!this.#keyFields) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (this.#keyFields.length !== keyFields.length) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (let i = 0; i < keyFields.length; i++) {
|
|
166
|
+
if (this.#keyFields[i] !== keyFields[i]) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @param {unknown} value
|
|
177
|
+
* @param {string} fieldName
|
|
178
|
+
* @returns {import("../spec/channel.js").Scalar}
|
|
179
|
+
*/
|
|
180
|
+
function validateKeyComponent(value, fieldName) {
|
|
181
|
+
if (value === undefined) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
`Key field "${fieldName}" is undefined. Ensure all key fields are present in the data.`
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (value === null) {
|
|
188
|
+
throw new Error(
|
|
189
|
+
`Key field "${fieldName}" is null. Ensure all key fields are present in the data.`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (
|
|
194
|
+
typeof value !== "string" &&
|
|
195
|
+
typeof value !== "number" &&
|
|
196
|
+
typeof value !== "boolean"
|
|
197
|
+
) {
|
|
198
|
+
throw new Error(
|
|
199
|
+
`Key field "${fieldName}" must be a scalar value (string, number, or boolean).`
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return value;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @param {string} value
|
|
208
|
+
* @returns {string}
|
|
209
|
+
*/
|
|
210
|
+
function escapeKeyString(value) {
|
|
211
|
+
const needsEscaping =
|
|
212
|
+
value.indexOf(MULTI_KEY_ESCAPE) !== -1 ||
|
|
213
|
+
value.indexOf(MULTI_KEY_SEPARATOR) !== -1;
|
|
214
|
+
|
|
215
|
+
if (!needsEscaping) {
|
|
216
|
+
return value;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
let escaped = "";
|
|
220
|
+
for (let i = 0; i < value.length; i++) {
|
|
221
|
+
const char = value[i];
|
|
222
|
+
if (char === MULTI_KEY_ESCAPE || char === MULTI_KEY_SEPARATOR) {
|
|
223
|
+
escaped += MULTI_KEY_ESCAPE;
|
|
224
|
+
}
|
|
225
|
+
escaped += char;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return escaped;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* @param {import("../spec/channel.js").Scalar} scalar
|
|
233
|
+
* @returns {string}
|
|
234
|
+
*/
|
|
235
|
+
function encodeKeyPart(scalar) {
|
|
236
|
+
if (typeof scalar === "string") {
|
|
237
|
+
return escapeKeyString(scalar);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return String(scalar);
|
|
241
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyIndex.test.d.ts","sourceRoot":"","sources":["../../../src/data/keyIndex.test.js"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataSource.d.ts","sourceRoot":"","sources":["../../../../src/data/sources/dataSource.js"],"names":[],"mappings":"AAEA;IAMI;;OAEG;IACH,kBAFW,OAAO,oBAAoB,EAAE,OAAO,EAM9C;IAZD;;OAEG;IACH,MAFU,OAAO,oBAAoB,EAAE,OAAO,CAEzC;IAWL;;;;;OAKG;IACH,kBAFY,MAAM,CAIjB;IAED;;;;;;OAMG;IACH,mCAJW,OAAO,4BAA4B,EAAE,iBAAiB,WACtD,MAAM,
|
|
1
|
+
{"version":3,"file":"dataSource.d.ts","sourceRoot":"","sources":["../../../../src/data/sources/dataSource.js"],"names":[],"mappings":"AAEA;IAMI;;OAEG;IACH,kBAFW,OAAO,oBAAoB,EAAE,OAAO,EAM9C;IAZD;;OAEG;IACH,MAFU,OAAO,oBAAoB,EAAE,OAAO,CAEzC;IAWL;;;;;OAKG;IACH,kBAFY,MAAM,CAIjB;IAED;;;;;;OAMG;IACH,mCAJW,OAAO,4BAA4B,EAAE,iBAAiB,WACtD,MAAM,QAShB;IAcD,sBAEC;CAKJ;qBA7DoB,gBAAgB"}
|
|
@@ -33,7 +33,11 @@ export default class DataSource extends FlowNode {
|
|
|
33
33
|
* @protected
|
|
34
34
|
*/
|
|
35
35
|
setLoadingStatus(status, detail) {
|
|
36
|
-
this.view.context.
|
|
36
|
+
this.view.context.dataFlow.loadingStatusRegistry.set(
|
|
37
|
+
this.view,
|
|
38
|
+
status,
|
|
39
|
+
detail
|
|
40
|
+
);
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
get paramMediator() {
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers a lazy data source for a custom type.
|
|
3
|
+
*
|
|
4
|
+
* @template {import("../../spec/data.js").LazyDataParams} P
|
|
5
|
+
* @param {LazySourceEntry<P>["guard"]} guard
|
|
6
|
+
* @param {LazySourceEntry<P>["Source"]} Source
|
|
7
|
+
* @returns {() => void}
|
|
8
|
+
*/
|
|
9
|
+
export function registerLazyDataSource<P extends import("../../spec/data.js").LazyDataParams>(guard: LazySourceEntry<P>["guard"], Source: LazySourceEntry<P>["Source"]): () => void;
|
|
1
10
|
/**
|
|
2
11
|
* @param {Partial<import("../../spec/data.js").Data>} params
|
|
3
12
|
* @param {import("../../view/view.js").default} view
|
|
4
13
|
*/
|
|
5
|
-
export default function createDataSource(params: Partial<import("../../spec/data.js").Data>, view: import("../../view/view.js").default):
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import AxisGenomeSource from "./lazy/axisGenomeSource.js";
|
|
11
|
-
import IndexedFastaSource from "./lazy/indexedFastaSource.js";
|
|
12
|
-
import BigWigSource from "./lazy/bigWigSource.js";
|
|
13
|
-
import BigBedSource from "./lazy/bigBedSource.js";
|
|
14
|
-
import BamSource from "./lazy/bamSource.js";
|
|
15
|
-
import Gff3Source from "./lazy/gff3Source.js";
|
|
16
|
-
import VcfSource from "./lazy/vcfSource.js";
|
|
14
|
+
export default function createDataSource(params: Partial<import("../../spec/data.js").Data>, view: import("../../view/view.js").default): import("./dataSource.js").default;
|
|
15
|
+
export type LazySourceEntry<P extends import("../../spec/data.js").LazyDataParams> = {
|
|
16
|
+
guard: (params: import("../../spec/data.js").LazyDataParams) => params is P;
|
|
17
|
+
Source: new (params: P, view: import("../../view/view.js").default) => import("./dataSource.js").default;
|
|
18
|
+
};
|
|
17
19
|
//# sourceMappingURL=dataSourceFactory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataSourceFactory.d.ts","sourceRoot":"","sources":["../../../../src/data/sources/dataSourceFactory.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dataSourceFactory.d.ts","sourceRoot":"","sources":["../../../../src/data/sources/dataSourceFactory.js"],"names":[],"mappings":"AAuBA;;;;;;;GAOG;AACH,uCAL2D,CAAC,SAA/C,OAAQ,oBAAoB,EAAE,cAAe,SAC/C,eAAe,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAC3B,eAAe,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAC1B,MAAM,IAAI,CAYtB;AAED;;;GAGG;AACH,iDAHW,OAAO,CAAC,OAAO,oBAAoB,EAAE,IAAI,CAAC,QAC1C,OAAO,oBAAoB,EAAE,OAAO,qCAgB9C;4BAhD0D,CAAC,SAA/C,OAAQ,oBAAoB,EAAE,cAAe,IAC7C;IACR,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,oBAAoB,EAAE,cAAc,KAAK,MAAM,IAAI,CAAC,CAAC;IAC5E,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,oBAAoB,EAAE,OAAO,KAAK,OAAO,iBAAiB,EAAE,OAAO,CAAA;CACzG"}
|
|
@@ -10,6 +10,37 @@ import BamSource from "./lazy/bamSource.js";
|
|
|
10
10
|
import Gff3Source from "./lazy/gff3Source.js";
|
|
11
11
|
import VcfSource from "./lazy/vcfSource.js";
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @template {import("../../spec/data.js").LazyDataParams} P
|
|
15
|
+
* @typedef {{
|
|
16
|
+
* guard: (params: import("../../spec/data.js").LazyDataParams) => params is P,
|
|
17
|
+
* Source: new (params: P, view: import("../../view/view.js").default) => import("./dataSource.js").default
|
|
18
|
+
* }} LazySourceEntry
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** @type {LazySourceEntry<any>[]} */
|
|
22
|
+
const customLazySources = [];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Registers a lazy data source for a custom type.
|
|
26
|
+
*
|
|
27
|
+
* @template {import("../../spec/data.js").LazyDataParams} P
|
|
28
|
+
* @param {LazySourceEntry<P>["guard"]} guard
|
|
29
|
+
* @param {LazySourceEntry<P>["Source"]} Source
|
|
30
|
+
* @returns {() => void}
|
|
31
|
+
*/
|
|
32
|
+
export function registerLazyDataSource(guard, Source) {
|
|
33
|
+
/** @type {LazySourceEntry<any>} */
|
|
34
|
+
const entry = { guard, Source };
|
|
35
|
+
customLazySources.push(entry);
|
|
36
|
+
return () => {
|
|
37
|
+
const index = customLazySources.indexOf(entry);
|
|
38
|
+
if (index >= 0) {
|
|
39
|
+
customLazySources.splice(index, 1);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
13
44
|
/**
|
|
14
45
|
* @param {Partial<import("../../spec/data.js").Data>} params
|
|
15
46
|
* @param {import("../../view/view.js").default} view
|
|
@@ -109,27 +140,32 @@ function isVcfSource(params) {
|
|
|
109
140
|
return params?.type == "vcf";
|
|
110
141
|
}
|
|
111
142
|
|
|
143
|
+
/** @type {LazySourceEntry<any>[]} */
|
|
144
|
+
const builtinLazySources = [
|
|
145
|
+
{ guard: isAxisTickSource, Source: AxisTickSource },
|
|
146
|
+
{ guard: isAxisGenomeSource, Source: AxisGenomeSource },
|
|
147
|
+
{ guard: isIndexedFastaSource, Source: IndexedFastaSource },
|
|
148
|
+
{ guard: isBigWigSource, Source: BigWigSource },
|
|
149
|
+
{ guard: isBigBedSource, Source: BigBedSource },
|
|
150
|
+
{ guard: isBamSource, Source: BamSource },
|
|
151
|
+
{ guard: isGff3Source, Source: Gff3Source },
|
|
152
|
+
{ guard: isVcfSource, Source: VcfSource },
|
|
153
|
+
];
|
|
154
|
+
|
|
112
155
|
/**
|
|
113
156
|
* @param {import("../../spec/data.js").LazyDataParams} params
|
|
114
157
|
* @param {import("../../view/view.js").default} view
|
|
115
158
|
*/
|
|
116
159
|
function createLazyDataSource(params, view) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return new BigBedSource(params, view);
|
|
127
|
-
} else if (isBamSource(params)) {
|
|
128
|
-
return new BamSource(params, view);
|
|
129
|
-
} else if (isGff3Source(params)) {
|
|
130
|
-
return new Gff3Source(params, view);
|
|
131
|
-
} else if (isVcfSource(params)) {
|
|
132
|
-
return new VcfSource(params, view);
|
|
160
|
+
for (const entry of customLazySources) {
|
|
161
|
+
if (entry.guard(params)) {
|
|
162
|
+
return new entry.Source(/** @type {any} */ (params), view);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
for (const entry of builtinLazySources) {
|
|
166
|
+
if (entry.guard(params)) {
|
|
167
|
+
return new entry.Source(/** @type {any} */ (params), view);
|
|
168
|
+
}
|
|
133
169
|
}
|
|
134
170
|
|
|
135
171
|
throw new Error(
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Testing-only lazy data source that delays data publishing.
|
|
3
|
+
* Register via registerLazyDataSource in tests to avoid production exposure.
|
|
4
|
+
*/
|
|
5
|
+
export default class MockLazySource extends SingleAxisLazySource {
|
|
6
|
+
/**
|
|
7
|
+
* @param {{ channel?: import("../../../spec/channel.js").PrimaryPositionalChannel, delay?: number, data?: import("../../flowNode.js").Datum[] }} params
|
|
8
|
+
* @param {import("../../../view/view.js").default} view
|
|
9
|
+
*/
|
|
10
|
+
constructor(params: {
|
|
11
|
+
channel?: import("../../../spec/channel.js").PrimaryPositionalChannel;
|
|
12
|
+
delay?: number;
|
|
13
|
+
data?: import("../../flowNode.js").Datum[];
|
|
14
|
+
}, view: import("../../../view/view.js").default);
|
|
15
|
+
params: {
|
|
16
|
+
channel?: import("../../../spec/channel.js").PrimaryPositionalChannel;
|
|
17
|
+
delay?: number;
|
|
18
|
+
data?: import("../../flowNode.js").Datum[];
|
|
19
|
+
};
|
|
20
|
+
delay: number;
|
|
21
|
+
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
22
|
+
pendingTimer: ReturnType<typeof setTimeout> | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* @override
|
|
25
|
+
*/
|
|
26
|
+
override onDomainChanged(): void;
|
|
27
|
+
}
|
|
28
|
+
import SingleAxisLazySource from "./singleAxisLazySource.js";
|
|
29
|
+
//# sourceMappingURL=mockLazySource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mockLazySource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/mockLazySource.js"],"names":[],"mappings":"AAEA;;;GAGG;AACH;IACI;;;OAGG;IACH,oBAHW;QAAE,OAAO,CAAC,EAAE,OAAO,0BAA0B,EAAE,wBAAwB,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,mBAAmB,EAAE,KAAK,EAAE,CAAA;KAAE,QACrI,OAAO,uBAAuB,EAAE,OAAO,EAgBjD;IAXG;kBANmB,OAAO,0BAA0B,EAAE,wBAAwB;gBAAU,MAAM;eAAS,OAAO,mBAAmB,EAAE,KAAK,EAAE;MAMtH;IACpB,cAA8B;IAC9B,wDAAwD;IACxD,cADW,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,SAAS,CACvB;IAUjC;;OAEG;IACH,iCAYC;CACJ;iCA3CgC,2BAA2B"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import SingleAxisLazySource from "./singleAxisLazySource.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Testing-only lazy data source that delays data publishing.
|
|
5
|
+
* Register via registerLazyDataSource in tests to avoid production exposure.
|
|
6
|
+
*/
|
|
7
|
+
export default class MockLazySource extends SingleAxisLazySource {
|
|
8
|
+
/**
|
|
9
|
+
* @param {{ channel?: import("../../../spec/channel.js").PrimaryPositionalChannel, delay?: number, data?: import("../../flowNode.js").Datum[] }} params
|
|
10
|
+
* @param {import("../../../view/view.js").default} view
|
|
11
|
+
*/
|
|
12
|
+
constructor(params, view) {
|
|
13
|
+
super(view, params.channel ?? "x");
|
|
14
|
+
|
|
15
|
+
this.params = params;
|
|
16
|
+
this.delay = params.delay ?? 0;
|
|
17
|
+
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
18
|
+
this.pendingTimer = undefined;
|
|
19
|
+
|
|
20
|
+
this.view.registerDisposer(() => {
|
|
21
|
+
if (this.pendingTimer) {
|
|
22
|
+
clearTimeout(this.pendingTimer);
|
|
23
|
+
this.pendingTimer = undefined;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @override
|
|
30
|
+
*/
|
|
31
|
+
onDomainChanged() {
|
|
32
|
+
if (this.pendingTimer) {
|
|
33
|
+
clearTimeout(this.pendingTimer);
|
|
34
|
+
this.pendingTimer = undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const data = this.params.data ?? [];
|
|
38
|
+
this.pendingTimer = setTimeout(() => {
|
|
39
|
+
this.pendingTimer = undefined;
|
|
40
|
+
this.publishData([data]);
|
|
41
|
+
this.requestRender();
|
|
42
|
+
}, this.delay);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Partial<Record<import("../../../spec/channel.js").PrimaryPositionalChannel, number[]>>} DataReadinessRequest
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {{isDataReadyForDomain: (request: DataReadinessRequest) => boolean}} DataReadinessCheckable
|
|
6
|
+
*/
|
|
1
7
|
/**
|
|
2
8
|
* Base class for data sources that listen a domain and propagate data lazily.
|
|
3
9
|
*
|
|
4
10
|
* @abstract
|
|
11
|
+
* @implements {DataReadinessCheckable}
|
|
5
12
|
*/
|
|
6
|
-
export default class SingleAxisLazySource extends DataSource {
|
|
13
|
+
export default class SingleAxisLazySource extends DataSource implements DataReadinessCheckable {
|
|
7
14
|
/**
|
|
8
15
|
* @param {import("../../../view/view.js").default} view
|
|
9
16
|
* @param {import("../../../spec/channel.js").PrimaryPositionalChannel} channel
|
|
@@ -14,6 +21,11 @@ export default class SingleAxisLazySource extends DataSource {
|
|
|
14
21
|
* @protected
|
|
15
22
|
*/
|
|
16
23
|
protected initializedPromise: Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* @type {number[] | undefined}
|
|
26
|
+
* @protected
|
|
27
|
+
*/
|
|
28
|
+
protected _lastLoadedDomain: number[] | undefined;
|
|
17
29
|
/** @type {import("../../../spec/channel.js").PrimaryPositionalChannel} */
|
|
18
30
|
channel: import("../../../spec/channel.js").PrimaryPositionalChannel;
|
|
19
31
|
scaleResolution: import("../../../scales/scaleResolution.js").default;
|
|
@@ -48,6 +60,15 @@ export default class SingleAxisLazySource extends DataSource {
|
|
|
48
60
|
* @protected
|
|
49
61
|
*/
|
|
50
62
|
protected publishData(chunks: import("../../flowNode.js").Datum[][]): void;
|
|
63
|
+
/**
|
|
64
|
+
* @param {DataReadinessRequest} request
|
|
65
|
+
* @returns {boolean}
|
|
66
|
+
*/
|
|
67
|
+
isDataReadyForDomain(request: DataReadinessRequest): boolean;
|
|
51
68
|
}
|
|
69
|
+
export type DataReadinessRequest = Partial<Record<import("../../../spec/channel.js").PrimaryPositionalChannel, number[]>>;
|
|
70
|
+
export type DataReadinessCheckable = {
|
|
71
|
+
isDataReadyForDomain: (request: DataReadinessRequest) => boolean;
|
|
72
|
+
};
|
|
52
73
|
import DataSource from "../dataSource.js";
|
|
53
74
|
//# sourceMappingURL=singleAxisLazySource.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"singleAxisLazySource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/singleAxisLazySource.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"singleAxisLazySource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/singleAxisLazySource.js"],"names":[],"mappings":"AAGA;;GAEG;AAEH;;GAEG;AAEH;;;;;GAKG;AACH,wEAFgB,sBAAsB;IAelC;;;OAGG;IACH,kBAHW,OAAO,uBAAuB,EAAE,OAAO,WACvC,OAAO,0BAA0B,EAAE,wBAAwB,EA+CrE;IA7DD;;;OAGG;IACH,4CAAuC;IAEvC;;;OAGG;IACH,6BAHU,MAAM,EAAE,GAAG,SAAS,CAGZ;IAmBd,2EAA2E;IAC3E,SADW,OAAO,0BAA0B,EAAE,wBAAwB,CAChD;IAEtB,sEAA4D;IA+BhE;;;;OAIG;IACH,oEASC;IAED;;;;;;OAMG;IACH,wBAJW,MAAM,EAAE,iBACR,OAAO,yBAAyB,EAAE,gBAAgB,EAAE,QAK9D;IAED;;;;;OAKG;IACH,gCAGC;IAQD;;;;;;;;OAQG;IACH,8BAHW,OAAO,mBAAmB,EAAE,KAAK,EAAE,EAAE,QAe/C;IAED;;;OAGG;IACH,8BAHW,oBAAoB,GAClB,OAAO,CAenB;CACJ;mCAlKY,OAAO,CAAC,MAAM,CAAC,OAAO,0BAA0B,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC,CAAC;qCAItF;IAAC,oBAAoB,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAA;CAAC;uBAPxD,kBAAkB"}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import UnitView from "../../../view/unitView.js";
|
|
2
2
|
import DataSource from "../dataSource.js";
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {Partial<Record<import("../../../spec/channel.js").PrimaryPositionalChannel, number[]>>} DataReadinessRequest
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {{isDataReadyForDomain: (request: DataReadinessRequest) => boolean}} DataReadinessCheckable
|
|
10
|
+
*/
|
|
4
11
|
|
|
5
12
|
/**
|
|
6
13
|
* Base class for data sources that listen a domain and propagate data lazily.
|
|
7
14
|
*
|
|
8
15
|
* @abstract
|
|
16
|
+
* @implements {DataReadinessCheckable}
|
|
9
17
|
*/
|
|
10
18
|
export default class SingleAxisLazySource extends DataSource {
|
|
11
19
|
/**
|
|
@@ -14,6 +22,12 @@ export default class SingleAxisLazySource extends DataSource {
|
|
|
14
22
|
*/
|
|
15
23
|
initializedPromise = Promise.resolve();
|
|
16
24
|
|
|
25
|
+
/**
|
|
26
|
+
* @type {number[] | undefined}
|
|
27
|
+
* @protected
|
|
28
|
+
*/
|
|
29
|
+
_lastLoadedDomain;
|
|
30
|
+
|
|
17
31
|
/**
|
|
18
32
|
* @param {import("../../../view/view.js").default} view
|
|
19
33
|
* @param {import("../../../spec/channel.js").PrimaryPositionalChannel} channel
|
|
@@ -119,6 +133,7 @@ export default class SingleAxisLazySource extends DataSource {
|
|
|
119
133
|
* @protected
|
|
120
134
|
*/
|
|
121
135
|
publishData(chunks) {
|
|
136
|
+
this._lastLoadedDomain = Array.from(this.scaleResolution.getDomain());
|
|
122
137
|
this.reset();
|
|
123
138
|
this.beginBatch({ type: "file" });
|
|
124
139
|
|
|
@@ -129,7 +144,24 @@ export default class SingleAxisLazySource extends DataSource {
|
|
|
129
144
|
}
|
|
130
145
|
|
|
131
146
|
this.complete();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param {DataReadinessRequest} request
|
|
151
|
+
* @returns {boolean}
|
|
152
|
+
*/
|
|
153
|
+
isDataReadyForDomain(request) {
|
|
154
|
+
const domain = request[this.channel];
|
|
155
|
+
if (!domain || !this._lastLoadedDomain) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
132
158
|
|
|
133
|
-
|
|
159
|
+
const [min, max] =
|
|
160
|
+
domain[0] <= domain[1] ? domain : [domain[1], domain[0]];
|
|
161
|
+
const [loadedMin, loadedMax] =
|
|
162
|
+
this._lastLoadedDomain[0] <= this._lastLoadedDomain[1]
|
|
163
|
+
? this._lastLoadedDomain
|
|
164
|
+
: [this._lastLoadedDomain[1], this._lastLoadedDomain[0]];
|
|
165
|
+
return min >= loadedMin && max <= loadedMax;
|
|
134
166
|
}
|
|
135
167
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"singleAxisWindowedSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/singleAxisWindowedSource.js"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH;IAWI;;;OAGG;IACH,kBAHU;QAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,4BAA4B,EAAE,OAAO,CAAA;KAAC,CAGvE;IAEP;;;OAGG;IACH,0CAHW,OAAO,uBAAuB,EAAE,aAAa,QAqBvD;IAED;;;;OAIG;IACH,wBAFW,MAAM,EAAE,QAqBlB;
|
|
1
|
+
{"version":3,"file":"singleAxisWindowedSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/singleAxisWindowedSource.js"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH;IAWI;;;OAGG;IACH,kBAHU;QAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,4BAA4B,EAAE,OAAO,CAAA;KAAC,CAGvE;IAEP;;;OAGG;IACH,0CAHW,OAAO,uBAAuB,EAAE,aAAa,QAqBvD;IAED;;;;OAIG;IACH,wBAFW,MAAM,EAAE,QAqBlB;IAeD;;;;;OAKG;IACH,iCAHW,MAAM,EAAE,iBAKlB;IArBD;;OAEG;IACH,mCAQC;IAyBD;;;;;;;;;OASG;IACH,4BAHa,CAAC,YAHH,MAAM,EAAE,UACR,CAAC,eAAe,EAAE,OAAO,mCAAmC,EAAE,0BAA0B,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3H,OAAO,CAAC,CAAC,EAAE,CAAC,CAyCvB;IAED;;;;;;OAMG;IACH,yCALW,MAAM,EAAE,cACR,MAAM,YACN,CAAS,IAAQ,EAAR,MAAM,EAAE,KAAE,IAAI,QAyBjC;;CACJ;iCA9LgC,2BAA2B"}
|