@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.
Files changed (191) hide show
  1. package/dist/bundle/index.es.js +7669 -6115
  2. package/dist/bundle/index.js +114 -133
  3. package/dist/schema.json +534 -132
  4. package/dist/src/data/collector.d.ts +20 -0
  5. package/dist/src/data/collector.d.ts.map +1 -1
  6. package/dist/src/data/collector.js +148 -0
  7. package/dist/src/data/dataFlow.d.ts +6 -0
  8. package/dist/src/data/dataFlow.d.ts.map +1 -1
  9. package/dist/src/data/dataFlow.js +10 -0
  10. package/dist/src/data/flowHandle.d.ts +2 -0
  11. package/dist/src/data/flowHandle.d.ts.map +1 -1
  12. package/dist/src/data/flowHandle.js +1 -0
  13. package/dist/src/data/flowInit.d.ts +12 -4
  14. package/dist/src/data/flowInit.d.ts.map +1 -1
  15. package/dist/src/data/flowInit.js +115 -17
  16. package/dist/src/data/flowNode.d.ts +8 -0
  17. package/dist/src/data/flowNode.d.ts.map +1 -1
  18. package/dist/src/data/flowNode.js +18 -0
  19. package/dist/src/data/keyIndex.d.ts +18 -0
  20. package/dist/src/data/keyIndex.d.ts.map +1 -0
  21. package/dist/src/data/keyIndex.js +241 -0
  22. package/dist/src/data/keyIndex.test.d.ts +2 -0
  23. package/dist/src/data/keyIndex.test.d.ts.map +1 -0
  24. package/dist/src/data/sources/dataSource.d.ts.map +1 -1
  25. package/dist/src/data/sources/dataSource.js +5 -1
  26. package/dist/src/data/sources/dataSourceFactory.d.ts +14 -12
  27. package/dist/src/data/sources/dataSourceFactory.d.ts.map +1 -1
  28. package/dist/src/data/sources/dataSourceFactory.js +52 -16
  29. package/dist/src/data/sources/lazy/mockLazySource.d.ts +29 -0
  30. package/dist/src/data/sources/lazy/mockLazySource.d.ts.map +1 -0
  31. package/dist/src/data/sources/lazy/mockLazySource.js +44 -0
  32. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +22 -1
  33. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  34. package/dist/src/data/sources/lazy/singleAxisLazySource.js +34 -2
  35. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  36. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +15 -0
  37. package/dist/src/data/sources/lazy/tabixSource.d.ts.map +1 -1
  38. package/dist/src/data/sources/lazy/tabixSource.js +15 -5
  39. package/dist/src/data/transforms/stack.d.ts.map +1 -1
  40. package/dist/src/data/transforms/stack.js +1 -0
  41. package/dist/src/encoder/accessor.d.ts +43 -0
  42. package/dist/src/encoder/accessor.d.ts.map +1 -1
  43. package/dist/src/encoder/accessor.js +164 -0
  44. package/dist/src/encoder/encoder.d.ts +11 -2
  45. package/dist/src/encoder/encoder.d.ts.map +1 -1
  46. package/dist/src/encoder/encoder.js +24 -4
  47. package/dist/src/encoder/metadataChannels.d.ts +15 -0
  48. package/dist/src/encoder/metadataChannels.d.ts.map +1 -0
  49. package/dist/src/encoder/metadataChannels.js +65 -0
  50. package/dist/src/encoder/metadataChannels.test.d.ts +2 -0
  51. package/dist/src/encoder/metadataChannels.test.d.ts.map +1 -0
  52. package/dist/src/genome/scaleLocus.d.ts.map +1 -1
  53. package/dist/src/genome/scaleLocus.js +14 -1
  54. package/dist/src/genomeSpy/containerUi.d.ts +0 -1
  55. package/dist/src/genomeSpy/containerUi.d.ts.map +1 -1
  56. package/dist/src/genomeSpy/containerUi.js +0 -14
  57. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts +3 -7
  58. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts.map +1 -1
  59. package/dist/src/genomeSpy/loadingIndicatorManager.js +68 -20
  60. package/dist/src/genomeSpy/loadingStatusRegistry.d.ts +52 -0
  61. package/dist/src/genomeSpy/loadingStatusRegistry.d.ts.map +1 -0
  62. package/dist/src/genomeSpy/loadingStatusRegistry.js +86 -0
  63. package/dist/src/genomeSpy/viewContextFactory.d.ts.map +1 -1
  64. package/dist/src/genomeSpy/viewContextFactory.js +0 -1
  65. package/dist/src/genomeSpy/viewDataInit.d.ts +10 -0
  66. package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -1
  67. package/dist/src/genomeSpy/viewDataInit.js +166 -2
  68. package/dist/src/genomeSpy/viewDataInit.test.d.ts +2 -0
  69. package/dist/src/genomeSpy/viewDataInit.test.d.ts.map +1 -0
  70. package/dist/src/genomeSpy.d.ts +1 -2
  71. package/dist/src/genomeSpy.d.ts.map +1 -1
  72. package/dist/src/genomeSpy.js +69 -27
  73. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  74. package/dist/src/gl/dataToVertices.js +16 -4
  75. package/dist/src/marks/mark.d.ts.map +1 -1
  76. package/dist/src/marks/mark.js +18 -11
  77. package/dist/src/marks/markUtils.js +1 -1
  78. package/dist/src/scale/scale.d.ts +6 -1
  79. package/dist/src/scale/scale.d.ts.map +1 -1
  80. package/dist/src/scale/scale.js +83 -23
  81. package/dist/src/scales/axisResolution.d.ts.map +1 -1
  82. package/dist/src/scales/axisResolution.js +10 -0
  83. package/dist/src/scales/{scaleDomainAggregator.d.ts → domainPlanner.d.ts} +8 -5
  84. package/dist/src/scales/domainPlanner.d.ts.map +1 -0
  85. package/dist/src/scales/domainPlanner.js +285 -0
  86. package/dist/src/scales/domainPlanner.test.d.ts +2 -0
  87. package/dist/src/scales/domainPlanner.test.d.ts.map +1 -0
  88. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
  89. package/dist/src/scales/scaleInstanceManager.js +8 -4
  90. package/dist/src/scales/scaleInteractionController.d.ts +6 -0
  91. package/dist/src/scales/scaleInteractionController.d.ts.map +1 -1
  92. package/dist/src/scales/scaleInteractionController.js +41 -3
  93. package/dist/src/scales/scaleResolution.d.ts +19 -16
  94. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  95. package/dist/src/scales/scaleResolution.js +255 -70
  96. package/dist/src/scales/scaleResolution.test.d.ts.map +1 -1
  97. package/dist/src/selection/selection.d.ts +21 -0
  98. package/dist/src/selection/selection.d.ts.map +1 -1
  99. package/dist/src/selection/selection.js +82 -0
  100. package/dist/src/spec/channel.d.ts +52 -15
  101. package/dist/src/spec/data.d.ts +4 -0
  102. package/dist/src/spec/parameter.d.ts +16 -11
  103. package/dist/src/spec/testing.d.ts +12 -0
  104. package/dist/src/spec/testing.d.ts.map +1 -0
  105. package/dist/src/spec/testing.js +20 -0
  106. package/dist/src/spec/view.d.ts +45 -10
  107. package/dist/src/styles/genome-spy.css +3 -31
  108. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  109. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  110. package/dist/src/styles/genome-spy.css.js +0 -29
  111. package/dist/src/types/encoder.d.ts +37 -2
  112. package/dist/src/types/rendering.d.ts +4 -3
  113. package/dist/src/types/viewContext.d.ts +0 -14
  114. package/dist/src/utils/domainArray.d.ts.map +1 -1
  115. package/dist/src/utils/domainArray.js +3 -0
  116. package/dist/src/utils/indexer.d.ts +3 -0
  117. package/dist/src/utils/indexer.d.ts.map +1 -1
  118. package/dist/src/utils/indexer.js +3 -0
  119. package/dist/src/utils/throttle.d.ts +4 -1
  120. package/dist/src/utils/throttle.d.ts.map +1 -1
  121. package/dist/src/utils/throttle.js +54 -23
  122. package/dist/src/utils/throttle.test.d.ts +2 -0
  123. package/dist/src/utils/throttle.test.d.ts.map +1 -0
  124. package/dist/src/utils/transition.d.ts +21 -0
  125. package/dist/src/utils/transition.d.ts.map +1 -1
  126. package/dist/src/utils/transition.js +28 -0
  127. package/dist/src/utils/ui/tooltip.d.ts.map +1 -1
  128. package/dist/src/utils/ui/tooltip.js +7 -1
  129. package/dist/src/utils/ui/tooltip.test.d.ts +2 -0
  130. package/dist/src/utils/ui/tooltip.test.d.ts.map +1 -0
  131. package/dist/src/view/axisGridView.d.ts.map +1 -1
  132. package/dist/src/view/axisGridView.js +22 -5
  133. package/dist/src/view/axisView.d.ts.map +1 -1
  134. package/dist/src/view/axisView.js +20 -5
  135. package/dist/src/view/concatView.js +3 -3
  136. package/dist/src/view/containerMutationHelper.d.ts.map +1 -1
  137. package/dist/src/view/containerMutationHelper.js +6 -2
  138. package/dist/src/view/containerView.d.ts +9 -5
  139. package/dist/src/view/containerView.d.ts.map +1 -1
  140. package/dist/src/view/containerView.js +34 -9
  141. package/dist/src/view/dataReadiness.d.ts +46 -0
  142. package/dist/src/view/dataReadiness.d.ts.map +1 -0
  143. package/dist/src/view/dataReadiness.js +267 -0
  144. package/dist/src/view/dataReadiness.test.d.ts +2 -0
  145. package/dist/src/view/dataReadiness.test.d.ts.map +1 -0
  146. package/dist/src/view/facetView.d.ts.map +1 -1
  147. package/dist/src/view/facetView.js +7 -5
  148. package/dist/src/view/flowBuilder.d.ts +5 -3
  149. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  150. package/dist/src/view/flowBuilder.js +74 -7
  151. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  152. package/dist/src/view/gridView/gridChild.js +8 -0
  153. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  154. package/dist/src/view/gridView/gridView.js +119 -2
  155. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  156. package/dist/src/view/gridView/scrollbar.js +3 -0
  157. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  158. package/dist/src/view/gridView/selectionRect.js +20 -5
  159. package/dist/src/view/gridView/separatorView.d.ts +51 -0
  160. package/dist/src/view/gridView/separatorView.d.ts.map +1 -0
  161. package/dist/src/view/gridView/separatorView.js +275 -0
  162. package/dist/src/view/layerView.js +3 -3
  163. package/dist/src/view/layout/flexLayout.d.ts +0 -30
  164. package/dist/src/view/layout/flexLayout.d.ts.map +1 -1
  165. package/dist/src/view/layout/flexLayout.js +0 -86
  166. package/dist/src/view/paramMediator.d.ts +19 -0
  167. package/dist/src/view/paramMediator.d.ts.map +1 -1
  168. package/dist/src/view/paramMediator.js +86 -19
  169. package/dist/src/view/testUtils.d.ts.map +1 -1
  170. package/dist/src/view/testUtils.js +11 -1
  171. package/dist/src/view/unitView.d.ts +8 -13
  172. package/dist/src/view/unitView.d.ts.map +1 -1
  173. package/dist/src/view/unitView.js +127 -43
  174. package/dist/src/view/view.d.ts +34 -14
  175. package/dist/src/view/view.d.ts.map +1 -1
  176. package/dist/src/view/view.js +119 -9
  177. package/dist/src/view/viewFactory.d.ts.map +1 -1
  178. package/dist/src/view/viewFactory.js +20 -1
  179. package/dist/src/view/viewSelectors.d.ts +148 -0
  180. package/dist/src/view/viewSelectors.d.ts.map +1 -0
  181. package/dist/src/view/viewSelectors.js +773 -0
  182. package/dist/src/view/viewSelectors.test.d.ts +2 -0
  183. package/dist/src/view/viewSelectors.test.d.ts.map +1 -0
  184. package/dist/src/view/viewUtils.d.ts +0 -8
  185. package/dist/src/view/viewUtils.d.ts.map +1 -1
  186. package/dist/src/view/viewUtils.js +1 -21
  187. package/package.json +3 -3
  188. package/dist/src/scales/scaleDomainAggregator.d.ts.map +0 -1
  189. package/dist/src/scales/scaleDomainAggregator.js +0 -162
  190. package/dist/src/scales/scaleDomainAggregator.test.d.ts +0 -2
  191. 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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dataReadiness.test.d.ts.map
@@ -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":"AAmDA;;;;;;;;;;;;;;GAcG;AACH;IACI;;;;;;;OAOG;IACH;;;;;;OAMG;IACH,kBALW,OAAO,gBAAgB,EAAE,SAAS,WAClC,OAAO,gBAAgB,EAAE,WAAW,UACpC,aAAa,QACb,MAAM,EA8BhB;IAzBG,UAAgB;IAEhB,WAEC;IAED;;;;OAIG;IACH,aAFU,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAYvC;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;2BAjbY,QAAQ,GAAG,KAAK;;;;;;aA4CnB,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE;;;0BA1Df,oBAAoB;qBACzB,eAAe"}
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
- channel,
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 {View} view
14
+ * @param {import("./unitView.js").default} view
13
15
  */
14
- export function linearizeLocusAccess(view: import("./view.js").default): {
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":"AAwBA;;;;GAIG;AACH,gFAHW,QAAQ,YAmNlB;AAED;;;;;;GAMG;AACH;;;IAgGc;;;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;qBA7aoB,qBAAqB;sBANpB,sBAAsB"}
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(root, existingFlow) {
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
- root.getDescendants(),
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 {View} view
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(view.getEncoding())) {
329
+ for (const [c, channelDef] of Object.entries(encoding)) {
267
330
  const channel = /** @type {Channel} */ (c);
268
- if (isPositionalChannel(channel) && isChromPosDef(channelDef)) {
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
- view.getEncoding()[channel] ??
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":"AA4rBA;;;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;AA1vBD;IACI;;;;;;OAMG;IAEH;;;;OAIG;IACH,kBAJW,OAAO,YAAY,EAAE,OAAO,gBAC5B,OAAO,qBAAqB,EAAE,OAAO,UACrC,MAAM,EAyFhB;IAtFG,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;IAoZhC,sEAiBC;IAED;;OAEG;IACH,4BAwKC;IAED;;OAEG;IACH,yBAWC;IAED,uBAqBC;IAED,iCAEC;;CACJ;qBA3qBoB,gBAAgB;qBANK,gBAAgB;yBADjC,oBAAoB;sBAQvB,gBAAgB;0BACZ,oBAAoB;sBAJxB,wBAAwB;oBAF1B,sBAAsB"}
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":"AA42BA;;GAEG;AACH,+EAUC;AAED;;;;;GAKG;AACH,4CAJW,OAAO,wBAAwB,EAAE,OAAO,UACxC,OAAO,oBAAoB,EAAE,UAAU,YACvC,QAAQ,aAmBlB;AA/3BD;;;;;;;;;;;;;;;GAeG;AACH;IAoCI;;;;;;;;;OASG;IACH,kBARW,OAAO,oBAAoB,EAAE,aAAa,WAC1C,OAAO,4BAA4B,EAAE,OAAO,gBAC5C,aAAa,kDAEb,MAAM,WACN,MAAM,YACN,OAAO,YAAY,EAAE,WAAW,EAoB1C;IARG,iDAAgB;IAOhB,uBAA0B;IAG9B;;OAEG;IACH,sDAEC;IAED;;;;;;OAMG;IACH,qDAFa,SAAS,CAIrB;IAED;;;;;;;OAOG;IACH,6DAHW,MAAM,GACJ,SAAS,CAQrB;IAED;;;;;OAKG;IACH,0DAQC;IAED;;;;;OAKG;IACH,qBAFW,MAAM,QAShB;IAeD;;OAEG;IACH,mBAFW,8BAAM,QAUhB;IAYD;;OAEG;IACH,+CAEC;IAED,yBAEC;IAED;;OAEG;IACH,sCAKC;IAED;;;;OAIG;IACH,gCAqCC;;CAwkBJ;qBAr0B0D,gBAAgB;sBADrD,wBAAwB;0BAEpB,qBAAqB;sBAIzB,gBAAgB"}
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"}