@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
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import DataSource from "../data/sources/dataSource.js";
|
|
2
|
+
import UnitView from "./unitView.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import("../view/view.js").default} View
|
|
6
|
+
* @typedef {import("../data/sources/lazy/singleAxisLazySource.js").DataReadinessRequest} DataReadinessRequest
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Builds a readiness request for the provided channels.
|
|
11
|
+
*
|
|
12
|
+
* @param {View} view
|
|
13
|
+
* @param {import("../spec/channel.js").PrimaryPositionalChannel[]} channels
|
|
14
|
+
* @returns {DataReadinessRequest | undefined}
|
|
15
|
+
*/
|
|
16
|
+
export function buildReadinessRequest(view, channels) {
|
|
17
|
+
/** @type {DataReadinessRequest} */
|
|
18
|
+
const request = {};
|
|
19
|
+
|
|
20
|
+
for (const channel of channels) {
|
|
21
|
+
const resolution = view.getScaleResolution(channel);
|
|
22
|
+
if (!resolution) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
request[channel] = Array.from(resolution.getDomain());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return Object.keys(request).length ? request : undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Checks whether all data sources under the subtree report readiness.
|
|
33
|
+
*
|
|
34
|
+
* @param {View} subtreeRoot
|
|
35
|
+
* @param {DataReadinessRequest} readinessRequest
|
|
36
|
+
* @param {(view: View) => boolean} [viewFilter]
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
export function isSubtreeReady(subtreeRoot, readinessRequest, viewFilter) {
|
|
40
|
+
const shouldConsiderView =
|
|
41
|
+
viewFilter ??
|
|
42
|
+
((/** @type {View} */ view) => view.isConfiguredVisible());
|
|
43
|
+
|
|
44
|
+
const unitViews = subtreeRoot
|
|
45
|
+
.getDescendants()
|
|
46
|
+
.filter((view) => view instanceof UnitView && shouldConsiderView(view));
|
|
47
|
+
|
|
48
|
+
if (unitViews.length === 0) {
|
|
49
|
+
return subtreeRoot.isDataInitialized();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
for (const view of unitViews) {
|
|
53
|
+
/** @type {import("../data/collector.js").default | undefined} */
|
|
54
|
+
const collector = view.flowHandle?.collector;
|
|
55
|
+
if (!collector || !collector.completed) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** @type {import("../data/flowNode.js").default | undefined} */
|
|
60
|
+
let node = collector;
|
|
61
|
+
while (node && !(node instanceof DataSource)) {
|
|
62
|
+
node = node.parent;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const dataSource = /** @type {DataSource | undefined} */ (node);
|
|
66
|
+
if (!dataSource) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if ("isDataReadyForDomain" in dataSource) {
|
|
71
|
+
// It's available in SingleAxisLazySource and its subclasses
|
|
72
|
+
const checkableSource =
|
|
73
|
+
/** @type {import("../data/sources/lazy/singleAxisLazySource.js").DataReadinessCheckable} */ (
|
|
74
|
+
dataSource
|
|
75
|
+
);
|
|
76
|
+
if (
|
|
77
|
+
!readinessRequest ||
|
|
78
|
+
!checkableSource.isDataReadyForDomain(readinessRequest)
|
|
79
|
+
) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Checks readiness for lazy data sources under the subtree. Non-lazy sources
|
|
90
|
+
* are ignored so they do not block readiness checks.
|
|
91
|
+
*
|
|
92
|
+
* @param {View} subtreeRoot
|
|
93
|
+
* @param {DataReadinessRequest | undefined} readinessRequest
|
|
94
|
+
* @param {(view: View) => boolean} [viewFilter]
|
|
95
|
+
* @returns {boolean}
|
|
96
|
+
*/
|
|
97
|
+
export function isSubtreeLazyReady(subtreeRoot, readinessRequest, viewFilter) {
|
|
98
|
+
const shouldConsiderView =
|
|
99
|
+
viewFilter ??
|
|
100
|
+
((/** @type {View} */ view) => view.isConfiguredVisible());
|
|
101
|
+
|
|
102
|
+
/** @type {Set<DataSource>} */
|
|
103
|
+
const dataSources = new Set();
|
|
104
|
+
|
|
105
|
+
subtreeRoot.visit((view) => {
|
|
106
|
+
if (!(view instanceof UnitView)) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (!shouldConsiderView(view)) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** @type {View | null} */
|
|
114
|
+
let current = view;
|
|
115
|
+
while (current) {
|
|
116
|
+
if (current.flowHandle && current.flowHandle.dataSource) {
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
current = current.dataParent;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!current || !current.flowHandle) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const dataSource = current.flowHandle.dataSource;
|
|
126
|
+
if (!("isDataReadyForDomain" in dataSource)) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
dataSources.add(dataSource);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (!dataSources.size) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!readinessRequest) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for (const dataSource of dataSources) {
|
|
141
|
+
const checkReady =
|
|
142
|
+
/** @type {import("../data/sources/lazy/singleAxisLazySource.js").DataReadinessCheckable["isDataReadyForDomain"]} */ (
|
|
143
|
+
/** @type {any} */ (dataSource).isDataReadyForDomain
|
|
144
|
+
);
|
|
145
|
+
if (!checkReady.call(dataSource, readinessRequest)) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Waits until lazy data sources under the subtree satisfy the readiness request.
|
|
155
|
+
* Non-lazy sources are ignored so they do not block readiness checks.
|
|
156
|
+
*
|
|
157
|
+
* @param {import("../types/viewContext.js").default} context
|
|
158
|
+
* @param {View} subtreeRoot
|
|
159
|
+
* @param {DataReadinessRequest} readinessRequest
|
|
160
|
+
* @param {AbortSignal} [signal]
|
|
161
|
+
* @param {(view: View) => boolean} [viewFilter]
|
|
162
|
+
* @returns {Promise<void>}
|
|
163
|
+
*/
|
|
164
|
+
export function awaitSubtreeLazyReady(
|
|
165
|
+
context,
|
|
166
|
+
subtreeRoot,
|
|
167
|
+
readinessRequest,
|
|
168
|
+
signal,
|
|
169
|
+
viewFilter
|
|
170
|
+
) {
|
|
171
|
+
const shouldConsiderView =
|
|
172
|
+
viewFilter ??
|
|
173
|
+
((/** @type {View} */ view) => view.isConfiguredVisible());
|
|
174
|
+
|
|
175
|
+
if (!readinessRequest) {
|
|
176
|
+
if (
|
|
177
|
+
isSubtreeLazyReady(
|
|
178
|
+
subtreeRoot,
|
|
179
|
+
readinessRequest,
|
|
180
|
+
shouldConsiderView
|
|
181
|
+
)
|
|
182
|
+
) {
|
|
183
|
+
return Promise.resolve();
|
|
184
|
+
}
|
|
185
|
+
return Promise.reject(
|
|
186
|
+
new Error("Lazy subtree readiness requires a readiness request.")
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return new Promise((resolve, reject) => {
|
|
191
|
+
/** @type {Set<() => void>} */
|
|
192
|
+
const unregisters = new Set();
|
|
193
|
+
/** @type {Set<import("../data/collector.js").default>} */
|
|
194
|
+
const observedCollectors = new Set();
|
|
195
|
+
|
|
196
|
+
/** @type {(message: import("./view.js").BroadcastMessage) => void} */
|
|
197
|
+
const broadcastListener = () => {
|
|
198
|
+
attachCollectors();
|
|
199
|
+
checkReady();
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const cleanup = () => {
|
|
203
|
+
for (const unregister of unregisters) {
|
|
204
|
+
unregister();
|
|
205
|
+
}
|
|
206
|
+
unregisters.clear();
|
|
207
|
+
context.removeBroadcastListener(
|
|
208
|
+
"subtreeDataReady",
|
|
209
|
+
broadcastListener
|
|
210
|
+
);
|
|
211
|
+
if (signal) {
|
|
212
|
+
signal.removeEventListener("abort", abortHandler);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const checkReady = () => {
|
|
217
|
+
if (
|
|
218
|
+
isSubtreeLazyReady(
|
|
219
|
+
subtreeRoot,
|
|
220
|
+
readinessRequest,
|
|
221
|
+
shouldConsiderView
|
|
222
|
+
)
|
|
223
|
+
) {
|
|
224
|
+
cleanup();
|
|
225
|
+
resolve();
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const attachCollectors = () => {
|
|
230
|
+
subtreeRoot.visit((view) => {
|
|
231
|
+
if (!(view instanceof UnitView)) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (!shouldConsiderView(view)) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const collector = view.flowHandle?.collector;
|
|
238
|
+
if (!collector) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (observedCollectors.has(collector)) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
observedCollectors.add(collector);
|
|
245
|
+
unregisters.add(collector.observe(checkReady));
|
|
246
|
+
});
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const abortHandler = () => {
|
|
250
|
+
cleanup();
|
|
251
|
+
reject(new Error("Lazy subtree readiness was aborted."));
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
attachCollectors();
|
|
255
|
+
checkReady();
|
|
256
|
+
|
|
257
|
+
context.addBroadcastListener("subtreeDataReady", broadcastListener);
|
|
258
|
+
|
|
259
|
+
if (signal) {
|
|
260
|
+
if (signal.aborted) {
|
|
261
|
+
abortHandler();
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataReadiness.test.d.ts","sourceRoot":"","sources":["../../../src/view/dataReadiness.test.js"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"facetView.d.ts","sourceRoot":"","sources":["../../../src/view/facetView.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"facetView.d.ts","sourceRoot":"","sources":["../../../src/view/facetView.js"],"names":[],"mappings":"AAoDA;;;;;;;;;;;;;;GAcG;AACH;IACI;;;;;;;OAOG;IACH;;;;;;OAMG;IACH,kBALW,OAAO,gBAAgB,EAAE,SAAS,WAClC,OAAO,gBAAgB,EAAE,WAAW,UACpC,aAAa,QACb,MAAM,EA+BhB;IA1BG,UAAgB;IAEhB,WAEC;IAED;;;;OAIG;IACH,aAFU,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAavC;IAED,oDAAoD;IACpD,kBADY,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,CACa;IAajE,sBAIC;IAED;;;OAGG;IACH,qBAFW,KAAK,GAAG,QAAQ,OAwB1B;IAED,qBAyCC;IAED,qBASC;IA6BD,kDAgBC;IAOD;;;;OAIG;IACH,gBAJW,OAAO,4CAA4C,EAAE,OAAO,UAC5D,OAAO,uBAAuB,EAAE,OAAO,YACvC,OAAO,WAAW,EAAE,gBAAgB,QA2L9C;IA3KO,wBAA0B;CA4KrC;2BAlbY,QAAQ,GAAG,KAAK;;;;;;aA4CnB,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE;;;0BA3Df,oBAAoB;qBACzB,eAAe"}
|
|
@@ -12,6 +12,7 @@ import coalesce from "../utils/coalesce.js";
|
|
|
12
12
|
import { field as vegaField } from "vega-util";
|
|
13
13
|
import DecoratorView from "./decoratorView.js";
|
|
14
14
|
import Padding from "./layout/padding.js";
|
|
15
|
+
import { markViewAsNonAddressable } from "./viewSelectors.js";
|
|
15
16
|
|
|
16
17
|
const DEFAULT_SPACING = 20;
|
|
17
18
|
|
|
@@ -95,15 +96,16 @@ export default class FacetView extends ContainerView {
|
|
|
95
96
|
* @type {Record<FacetChannel, UnitView>}
|
|
96
97
|
*/
|
|
97
98
|
this._labelViews = Object.fromEntries(
|
|
98
|
-
FACET_CHANNELS.map((channel) =>
|
|
99
|
-
|
|
100
|
-
new UnitView(
|
|
99
|
+
FACET_CHANNELS.map((channel) => {
|
|
100
|
+
const labelView = new UnitView(
|
|
101
101
|
createLabelViewSpec(headerConfigs[channel]),
|
|
102
102
|
this.context,
|
|
103
103
|
this,
|
|
104
104
|
`facetLabel-${channel}`
|
|
105
|
-
)
|
|
106
|
-
|
|
105
|
+
);
|
|
106
|
+
markViewAsNonAddressable(labelView, { skipSubtree: true });
|
|
107
|
+
return [channel, labelView];
|
|
108
|
+
})
|
|
107
109
|
);
|
|
108
110
|
|
|
109
111
|
/** @type {Record<FacetChannel, FacetDimension>} */
|
|
@@ -2,16 +2,18 @@
|
|
|
2
2
|
* @param {View} root
|
|
3
3
|
* @param {DataFlow} [existingFlow] Add data flow
|
|
4
4
|
* graphs to an existing DataFlow object.
|
|
5
|
+
* @param {(view: View) => boolean} [viewFilter]
|
|
6
|
+
* @param {(view: View) => boolean} [viewInitializationPredicate]
|
|
5
7
|
*/
|
|
6
|
-
export function buildDataFlow(root: import("./view.js").default, existingFlow?: DataFlow): DataFlow;
|
|
8
|
+
export function buildDataFlow(root: import("./view.js").default, existingFlow?: DataFlow, viewFilter?: (view: import("./view.js").default) => boolean, viewInitializationPredicate?: (view: import("./view.js").default) => boolean): DataFlow;
|
|
7
9
|
/**
|
|
8
10
|
* Changes the ChromPos channelDefs into FieldDefs and returns
|
|
9
11
|
* LinearizeGenomicCoordinate transform(s) that should be inserted into
|
|
10
12
|
* the data flow.
|
|
11
13
|
*
|
|
12
|
-
* @param {
|
|
14
|
+
* @param {import("./unitView.js").default} view
|
|
13
15
|
*/
|
|
14
|
-
export function linearizeLocusAccess(view: import("./
|
|
16
|
+
export function linearizeLocusAccess(view: import("./unitView.js").default): {
|
|
15
17
|
transforms: import("../data/flowNode.js").default[];
|
|
16
18
|
rewrittenEncoding: import("../spec/channel.js").Encoding;
|
|
17
19
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flowBuilder.d.ts","sourceRoot":"","sources":["../../../src/view/flowBuilder.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"flowBuilder.d.ts","sourceRoot":"","sources":["../../../src/view/flowBuilder.js"],"names":[],"mappings":"AAyBA;;;;;;GAMG;AACH,gFALW,QAAQ,eAER,CAAC,IAAI,6BAAM,KAAK,OAAO,gCACvB,CAAC,IAAI,6BAAM,KAAK,OAAO,YAoPjC;AAuBD;;;;;;GAMG;AACH,2CAFW,OAAO,eAAe,EAAE,OAAO;;;IA2G5B;;;OAGG;;EAYhB;AAgCD;;;;;;GAMG;AACH,4BAFwB,CAAC,SAAZ,qCAAU,cAFZ,CAAC,iBACA,uCAAW;;;0BAwBG,OAAO,CAAC,QAAQ,CAAC,OAAO,qBAAqB,EAAE,KAAK,CAAC,CAAC;EAkB/E;qBA/eoB,qBAAqB;sBAPpB,sBAAsB"}
|
|
@@ -2,6 +2,7 @@ import Collector from "../data/collector.js";
|
|
|
2
2
|
import createTransform from "../data/transforms/transformFactory.js";
|
|
3
3
|
import createDataSource from "../data/sources/dataSourceFactory.js";
|
|
4
4
|
import UnitView from "./unitView.js";
|
|
5
|
+
import { VISIT_SKIP } from "./view.js";
|
|
5
6
|
import { BEHAVIOR_MODIFIES } from "../data/flowNode.js";
|
|
6
7
|
import CloneTransform from "../data/transforms/clone.js";
|
|
7
8
|
import DataFlow from "../data/dataFlow.js";
|
|
@@ -26,8 +27,15 @@ import { nodesToTreesWithAccessor, visitTree } from "../utils/trees.js";
|
|
|
26
27
|
* @param {View} root
|
|
27
28
|
* @param {DataFlow} [existingFlow] Add data flow
|
|
28
29
|
* graphs to an existing DataFlow object.
|
|
30
|
+
* @param {(view: View) => boolean} [viewFilter]
|
|
31
|
+
* @param {(view: View) => boolean} [viewInitializationPredicate]
|
|
29
32
|
*/
|
|
30
|
-
export function buildDataFlow(
|
|
33
|
+
export function buildDataFlow(
|
|
34
|
+
root,
|
|
35
|
+
existingFlow,
|
|
36
|
+
viewFilter,
|
|
37
|
+
viewInitializationPredicate
|
|
38
|
+
) {
|
|
31
39
|
/**
|
|
32
40
|
* @typedef {import("./view.js").default} View
|
|
33
41
|
* @typedef {import("../data/flowNode.js").default} FlowNode
|
|
@@ -47,6 +55,8 @@ export function buildDataFlow(root, existingFlow) {
|
|
|
47
55
|
/** @type {(function():void)[]} */
|
|
48
56
|
const postProcessOps = [];
|
|
49
57
|
|
|
58
|
+
const shouldInitializeView = viewInitializationPredicate ?? (() => true);
|
|
59
|
+
|
|
50
60
|
/**
|
|
51
61
|
* @param {FlowNode} node
|
|
52
62
|
* @param {function():Error} [onMissingParent]
|
|
@@ -121,6 +131,27 @@ export function buildDataFlow(root, existingFlow) {
|
|
|
121
131
|
|
|
122
132
|
/** @param {View} view */
|
|
123
133
|
const processView = (view) => {
|
|
134
|
+
if (!shouldInitializeView(view)) {
|
|
135
|
+
const flowNode = view.flowHandle?.node;
|
|
136
|
+
if (flowNode) {
|
|
137
|
+
if (flowNode !== currentNode) {
|
|
138
|
+
currentNode = flowNode;
|
|
139
|
+
nodeStack.push(flowNode);
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (
|
|
144
|
+
view.spec.data ||
|
|
145
|
+
view.spec.transform ||
|
|
146
|
+
view instanceof UnitView
|
|
147
|
+
) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
"Cannot reuse missing flow nodes for " +
|
|
150
|
+
view.getPathString()
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
124
155
|
if (view.spec.data) {
|
|
125
156
|
const previousDataSource = view.flowHandle?.dataSource;
|
|
126
157
|
if (
|
|
@@ -205,12 +236,18 @@ export function buildDataFlow(root, existingFlow) {
|
|
|
205
236
|
view.flowHandle ??= {};
|
|
206
237
|
view.flowHandle.collector = collector;
|
|
207
238
|
}
|
|
239
|
+
|
|
240
|
+
if (currentNode) {
|
|
241
|
+
view.flowHandle ??= {};
|
|
242
|
+
view.flowHandle.node = currentNode;
|
|
243
|
+
}
|
|
208
244
|
};
|
|
209
245
|
|
|
210
246
|
// Views only keep track of their children based on the layout hierachy.
|
|
211
247
|
// Thus, let's get traversable hierarchies using dataParents.
|
|
248
|
+
const views = collectSubtreeViews(root, viewFilter);
|
|
212
249
|
const dataTrees = nodesToTreesWithAccessor(
|
|
213
|
-
|
|
250
|
+
views,
|
|
214
251
|
(view) => view.dataParent
|
|
215
252
|
);
|
|
216
253
|
|
|
@@ -237,16 +274,36 @@ export function buildDataFlow(root, existingFlow) {
|
|
|
237
274
|
return dataFlow;
|
|
238
275
|
}
|
|
239
276
|
|
|
277
|
+
/**
|
|
278
|
+
* @param {import("./view.js").default} root
|
|
279
|
+
* @param {(view: import("./view.js").default) => boolean} [viewFilter]
|
|
280
|
+
* @returns {import("./view.js").default[]}
|
|
281
|
+
*/
|
|
282
|
+
function collectSubtreeViews(root, viewFilter) {
|
|
283
|
+
if (!viewFilter) {
|
|
284
|
+
return root.getDescendants();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** @type {import("./view.js").default[]} */
|
|
288
|
+
const views = [];
|
|
289
|
+
root.visit((view) => {
|
|
290
|
+
if (!viewFilter(view)) {
|
|
291
|
+
return VISIT_SKIP;
|
|
292
|
+
}
|
|
293
|
+
views.push(view);
|
|
294
|
+
});
|
|
295
|
+
return views;
|
|
296
|
+
}
|
|
297
|
+
|
|
240
298
|
/**
|
|
241
299
|
* Changes the ChromPos channelDefs into FieldDefs and returns
|
|
242
300
|
* LinearizeGenomicCoordinate transform(s) that should be inserted into
|
|
243
301
|
* the data flow.
|
|
244
302
|
*
|
|
245
|
-
* @param {
|
|
303
|
+
* @param {import("./unitView.js").default} view
|
|
246
304
|
*/
|
|
247
305
|
export function linearizeLocusAccess(view) {
|
|
248
306
|
/**
|
|
249
|
-
* @typedef {import("./view.js").default} View
|
|
250
307
|
* @typedef {import("../data/flowNode.js").default} FlowNode
|
|
251
308
|
* @typedef {import("../spec/channel.js").Channel} Channel
|
|
252
309
|
* @typedef {import("../spec/channel.js").Encoding} Encoding
|
|
@@ -258,14 +315,24 @@ export function linearizeLocusAccess(view) {
|
|
|
258
315
|
/** @type {Encoding} */
|
|
259
316
|
const rewrittenEncoding = {};
|
|
260
317
|
|
|
318
|
+
// Use mark.encoding so we see the same channel defs that encoders consume,
|
|
319
|
+
// including inherited channels and mark defaults. getEncoding() only returns
|
|
320
|
+
// spec/inherited encodings and can omit channels during lazy init (e.g.,
|
|
321
|
+
// summary views that inherit chrom/pos), which would skip chrom/pos rewrites.
|
|
322
|
+
const encoding = view.mark.encoding;
|
|
323
|
+
|
|
261
324
|
/** @type {{ channel: Channel, chromPosDef: import("../spec/channel.js").ChromPosDef}[]} */
|
|
262
325
|
const channelsAndChromPosDefs = [];
|
|
263
326
|
|
|
264
327
|
// Optimize the number of transforms. Use only a single transform for positions
|
|
265
328
|
// that share the chromosome field and channel.
|
|
266
|
-
for (const [c, channelDef] of Object.entries(
|
|
329
|
+
for (const [c, channelDef] of Object.entries(encoding)) {
|
|
267
330
|
const channel = /** @type {Channel} */ (c);
|
|
268
|
-
if (
|
|
331
|
+
if (
|
|
332
|
+
isPositionalChannel(channel) &&
|
|
333
|
+
!Array.isArray(channelDef) &&
|
|
334
|
+
isChromPosDef(channelDef)
|
|
335
|
+
) {
|
|
269
336
|
channelsAndChromPosDefs.push({ channel, chromPosDef: channelDef });
|
|
270
337
|
}
|
|
271
338
|
}
|
|
@@ -302,7 +369,7 @@ export function linearizeLocusAccess(view) {
|
|
|
302
369
|
/** @type {any} */
|
|
303
370
|
const newFieldDef = {
|
|
304
371
|
...(view.spec.encoding?.[channel] ??
|
|
305
|
-
|
|
372
|
+
encoding[channel] ??
|
|
306
373
|
{}),
|
|
307
374
|
field: linearizedField,
|
|
308
375
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gridChild.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/gridChild.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gridChild.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/gridChild.js"],"names":[],"mappings":"AAosBA;;;GAGG;AACH,iDAHW,OAAO,oBAAoB,EAAE,cAAc,GACzC,OAAO,oBAAoB,EAAE,QAAQ,CA8BjD;AAED;;;GAGG;AACH,uDAHW,OAAO,oBAAoB,EAAE,cAAc,GACzC,OAAO,oBAAoB,EAAE,QAAQ,CA6CjD;AAjwBD;IACI;;;;;;OAMG;IAEH;;;;OAIG;IACH,kBAJW,OAAO,YAAY,EAAE,OAAO,gBAC5B,OAAO,qBAAqB,EAAE,OAAO,UACrC,MAAM,EAgGhB;IA7FG,oDAAgC;IAChC,mCAAgB;IAChB,eAAoB;IAEpB,uBAAuB;IACvB,YADW,QAAQ,CACQ;IAE3B,uBAAuB;IACvB,kBADW,QAAQ,CACc;IAEjC,sFAAsF;IACtF,MADW,OAAO,CAAC,MAAM,CAAC,OAAO,oBAAoB,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAC/D;IAEd,+FAA+F;IAC/F,WADW,OAAO,CAAC,MAAM,CAAC,OAAO,oBAAoB,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAC9D;IAEnB,mFAAmF;IACnF,YADW,OAAO,CAAC,MAAM,CAAC,OAAO,gBAAgB,EAAE,eAAe,EAAE,SAAS,CAAC,CAAC,CAC3D;IAEpB,4BAA4B;IAC5B,eADW,aAAa,CACM;IAE9B,uBAAuB;IACvB,OADW,QAAQ,CACG;IAEtB,wBAAwB;IACxB,QADW,SAAS,CACQ;IA2ZhC,sEAiBC;IAED;;OAEG;IACH,4BAwKC;IAED;;OAEG;IACH,yBAWC;IAED,uBAqBC;IAED,iCAEC;;CACJ;qBAnrBoB,gBAAgB;qBANK,gBAAgB;yBADjC,oBAAoB;sBASvB,gBAAgB;0BACZ,oBAAoB;sBALxB,wBAAwB;oBAF1B,sBAAsB"}
|
|
@@ -14,6 +14,7 @@ import Point from "../layout/point.js";
|
|
|
14
14
|
import Rectangle from "../layout/rectangle.js";
|
|
15
15
|
import createTitle from "../title.js";
|
|
16
16
|
import UnitView from "../unitView.js";
|
|
17
|
+
import { markViewAsNonAddressable } from "../viewSelectors.js";
|
|
17
18
|
import Scrollbar from "./scrollbar.js";
|
|
18
19
|
import SelectionRect from "./selectionRect.js";
|
|
19
20
|
|
|
@@ -76,6 +77,9 @@ export default class GridChild {
|
|
|
76
77
|
blockEncodingInheritance: true,
|
|
77
78
|
}
|
|
78
79
|
);
|
|
80
|
+
markViewAsNonAddressable(this.background, {
|
|
81
|
+
skipSubtree: true,
|
|
82
|
+
});
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
const backgroundStrokeSpec = createBackgroundStroke(viewBackground);
|
|
@@ -90,6 +94,9 @@ export default class GridChild {
|
|
|
90
94
|
blockEncodingInheritance: true,
|
|
91
95
|
}
|
|
92
96
|
);
|
|
97
|
+
markViewAsNonAddressable(this.backgroundStroke, {
|
|
98
|
+
skipSubtree: true,
|
|
99
|
+
});
|
|
93
100
|
}
|
|
94
101
|
|
|
95
102
|
const title = createTitle(view.spec.title);
|
|
@@ -105,6 +112,7 @@ export default class GridChild {
|
|
|
105
112
|
}
|
|
106
113
|
);
|
|
107
114
|
this.title = unitView;
|
|
115
|
+
markViewAsNonAddressable(this.title, { skipSubtree: true });
|
|
108
116
|
}
|
|
109
117
|
}
|
|
110
118
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gridView.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/gridView.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gridView.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/gridView.js"],"names":[],"mappings":"AAg9BA;;GAEG;AACH,+EAUC;AAmBD;;;;;GAKG;AACH,4CAJW,OAAO,wBAAwB,EAAE,OAAO,UACxC,OAAO,oBAAoB,EAAE,UAAU,YACvC,QAAQ,aAmBlB;AAn/BD;;;;;;;;;;;;;;;GAeG;AACH;IAuCI;;;;;;;;;OASG;IACH,kBARW,OAAO,oBAAoB,EAAE,aAAa,WAC1C,OAAO,4BAA4B,EAAE,OAAO,gBAC5C,aAAa,kDAEb,MAAM,WACN,MAAM,YACN,OAAO,YAAY,EAAE,WAAW,EAkC1C;IAtBG,iDAAgB;IAOhB,uBAA0B;IAiB9B;;OAEG;IACH,sDAEC;IAED;;;;;;OAMG;IACH,qDAFa,SAAS,CAIrB;IAED;;;;;;;OAOG;IACH,6DAHW,MAAM,GACJ,SAAS,CASrB;IAED;;;;;OAKG;IACH,0DAQC;IAED;;;;;OAKG;IACH,qBAFW,MAAM,QAUhB;IAeD;;OAEG;IACH,mBAFW,8BAAM,QAWhB;IAYD;;OAEG;IACH,+CAEC;IAED,yBAEC;IAED;;OAEG;IACH,sCAKC;IAED;;;;OAIG;IACH,gCAqCC;;CAupBJ;qBAz6B0D,gBAAgB;sBADrD,wBAAwB;0BAEpB,qBAAqB;sBAIzB,gBAAgB"}
|