@genome-spy/core 0.67.0 → 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 (172) hide show
  1. package/dist/bundle/index.es.js +7641 -6313
  2. package/dist/bundle/index.js +115 -134
  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/flowInit.d.ts.map +1 -1
  11. package/dist/src/data/flowInit.js +2 -3
  12. package/dist/src/data/flowNode.d.ts +8 -0
  13. package/dist/src/data/flowNode.d.ts.map +1 -1
  14. package/dist/src/data/flowNode.js +18 -0
  15. package/dist/src/data/keyIndex.d.ts +18 -0
  16. package/dist/src/data/keyIndex.d.ts.map +1 -0
  17. package/dist/src/data/keyIndex.js +241 -0
  18. package/dist/src/data/keyIndex.test.d.ts +2 -0
  19. package/dist/src/data/keyIndex.test.d.ts.map +1 -0
  20. package/dist/src/data/sources/dataSource.d.ts.map +1 -1
  21. package/dist/src/data/sources/dataSource.js +5 -1
  22. package/dist/src/data/sources/dataSourceFactory.d.ts +14 -12
  23. package/dist/src/data/sources/dataSourceFactory.d.ts.map +1 -1
  24. package/dist/src/data/sources/dataSourceFactory.js +52 -16
  25. package/dist/src/data/sources/lazy/mockLazySource.d.ts +29 -0
  26. package/dist/src/data/sources/lazy/mockLazySource.d.ts.map +1 -0
  27. package/dist/src/data/sources/lazy/mockLazySource.js +44 -0
  28. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +22 -1
  29. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  30. package/dist/src/data/sources/lazy/singleAxisLazySource.js +34 -2
  31. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  32. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +15 -0
  33. package/dist/src/data/sources/lazy/tabixSource.d.ts.map +1 -1
  34. package/dist/src/data/sources/lazy/tabixSource.js +15 -5
  35. package/dist/src/data/transforms/stack.d.ts.map +1 -1
  36. package/dist/src/data/transforms/stack.js +1 -0
  37. package/dist/src/encoder/accessor.d.ts +43 -0
  38. package/dist/src/encoder/accessor.d.ts.map +1 -1
  39. package/dist/src/encoder/accessor.js +164 -0
  40. package/dist/src/encoder/encoder.d.ts +11 -2
  41. package/dist/src/encoder/encoder.d.ts.map +1 -1
  42. package/dist/src/encoder/encoder.js +24 -4
  43. package/dist/src/encoder/metadataChannels.d.ts +15 -0
  44. package/dist/src/encoder/metadataChannels.d.ts.map +1 -0
  45. package/dist/src/encoder/metadataChannels.js +65 -0
  46. package/dist/src/encoder/metadataChannels.test.d.ts +2 -0
  47. package/dist/src/encoder/metadataChannels.test.d.ts.map +1 -0
  48. package/dist/src/genome/scaleLocus.d.ts.map +1 -1
  49. package/dist/src/genome/scaleLocus.js +14 -1
  50. package/dist/src/genomeSpy/containerUi.d.ts +0 -1
  51. package/dist/src/genomeSpy/containerUi.d.ts.map +1 -1
  52. package/dist/src/genomeSpy/containerUi.js +0 -14
  53. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts +3 -7
  54. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts.map +1 -1
  55. package/dist/src/genomeSpy/loadingIndicatorManager.js +68 -20
  56. package/dist/src/genomeSpy/loadingStatusRegistry.d.ts +52 -0
  57. package/dist/src/genomeSpy/loadingStatusRegistry.d.ts.map +1 -0
  58. package/dist/src/genomeSpy/loadingStatusRegistry.js +86 -0
  59. package/dist/src/genomeSpy/viewContextFactory.d.ts.map +1 -1
  60. package/dist/src/genomeSpy/viewContextFactory.js +0 -1
  61. package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -1
  62. package/dist/src/genomeSpy/viewDataInit.js +56 -11
  63. package/dist/src/genomeSpy.d.ts +0 -2
  64. package/dist/src/genomeSpy.d.ts.map +1 -1
  65. package/dist/src/genomeSpy.js +46 -26
  66. package/dist/src/marks/mark.d.ts.map +1 -1
  67. package/dist/src/marks/mark.js +18 -11
  68. package/dist/src/marks/markUtils.js +1 -1
  69. package/dist/src/scale/scale.d.ts +6 -1
  70. package/dist/src/scale/scale.d.ts.map +1 -1
  71. package/dist/src/scale/scale.js +83 -23
  72. package/dist/src/scales/axisResolution.d.ts.map +1 -1
  73. package/dist/src/scales/axisResolution.js +10 -0
  74. package/dist/src/scales/{scaleDomainAggregator.d.ts → domainPlanner.d.ts} +6 -3
  75. package/dist/src/scales/domainPlanner.d.ts.map +1 -0
  76. package/dist/src/scales/{scaleDomainAggregator.js → domainPlanner.js} +128 -10
  77. package/dist/src/scales/domainPlanner.test.d.ts +2 -0
  78. package/dist/src/scales/domainPlanner.test.d.ts.map +1 -0
  79. package/dist/src/scales/scaleInteractionController.d.ts +6 -0
  80. package/dist/src/scales/scaleInteractionController.d.ts.map +1 -1
  81. package/dist/src/scales/scaleInteractionController.js +41 -3
  82. package/dist/src/scales/scaleResolution.d.ts +19 -17
  83. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  84. package/dist/src/scales/scaleResolution.js +181 -70
  85. package/dist/src/scales/scaleResolution.test.d.ts.map +1 -1
  86. package/dist/src/selection/selection.d.ts +21 -0
  87. package/dist/src/selection/selection.d.ts.map +1 -1
  88. package/dist/src/selection/selection.js +82 -0
  89. package/dist/src/spec/channel.d.ts +52 -15
  90. package/dist/src/spec/data.d.ts +4 -0
  91. package/dist/src/spec/parameter.d.ts +16 -11
  92. package/dist/src/spec/testing.d.ts +12 -0
  93. package/dist/src/spec/testing.d.ts.map +1 -0
  94. package/dist/src/spec/testing.js +20 -0
  95. package/dist/src/spec/view.d.ts +45 -10
  96. package/dist/src/styles/genome-spy.css +3 -31
  97. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  98. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  99. package/dist/src/styles/genome-spy.css.js +0 -29
  100. package/dist/src/types/encoder.d.ts +37 -2
  101. package/dist/src/types/rendering.d.ts +4 -3
  102. package/dist/src/types/viewContext.d.ts +0 -14
  103. package/dist/src/utils/throttle.d.ts +4 -1
  104. package/dist/src/utils/throttle.d.ts.map +1 -1
  105. package/dist/src/utils/throttle.js +54 -23
  106. package/dist/src/utils/throttle.test.d.ts +2 -0
  107. package/dist/src/utils/throttle.test.d.ts.map +1 -0
  108. package/dist/src/utils/transition.d.ts +21 -0
  109. package/dist/src/utils/transition.d.ts.map +1 -1
  110. package/dist/src/utils/transition.js +28 -0
  111. package/dist/src/utils/ui/tooltip.d.ts.map +1 -1
  112. package/dist/src/utils/ui/tooltip.js +7 -1
  113. package/dist/src/utils/ui/tooltip.test.d.ts +2 -0
  114. package/dist/src/utils/ui/tooltip.test.d.ts.map +1 -0
  115. package/dist/src/view/axisGridView.d.ts.map +1 -1
  116. package/dist/src/view/axisGridView.js +22 -5
  117. package/dist/src/view/axisView.d.ts.map +1 -1
  118. package/dist/src/view/axisView.js +20 -5
  119. package/dist/src/view/concatView.js +3 -3
  120. package/dist/src/view/containerMutationHelper.js +1 -1
  121. package/dist/src/view/containerView.d.ts +9 -5
  122. package/dist/src/view/containerView.d.ts.map +1 -1
  123. package/dist/src/view/containerView.js +34 -9
  124. package/dist/src/view/dataReadiness.d.ts +46 -0
  125. package/dist/src/view/dataReadiness.d.ts.map +1 -0
  126. package/dist/src/view/dataReadiness.js +267 -0
  127. package/dist/src/view/dataReadiness.test.d.ts +2 -0
  128. package/dist/src/view/dataReadiness.test.d.ts.map +1 -0
  129. package/dist/src/view/facetView.d.ts.map +1 -1
  130. package/dist/src/view/facetView.js +7 -5
  131. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  132. package/dist/src/view/flowBuilder.js +5 -1
  133. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  134. package/dist/src/view/gridView/gridChild.js +8 -0
  135. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  136. package/dist/src/view/gridView/gridView.js +119 -2
  137. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  138. package/dist/src/view/gridView/scrollbar.js +3 -0
  139. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  140. package/dist/src/view/gridView/selectionRect.js +20 -5
  141. package/dist/src/view/gridView/separatorView.d.ts +51 -0
  142. package/dist/src/view/gridView/separatorView.d.ts.map +1 -0
  143. package/dist/src/view/gridView/separatorView.js +275 -0
  144. package/dist/src/view/layerView.js +3 -3
  145. package/dist/src/view/layout/flexLayout.d.ts +0 -30
  146. package/dist/src/view/layout/flexLayout.d.ts.map +1 -1
  147. package/dist/src/view/layout/flexLayout.js +0 -86
  148. package/dist/src/view/paramMediator.d.ts +19 -0
  149. package/dist/src/view/paramMediator.d.ts.map +1 -1
  150. package/dist/src/view/paramMediator.js +86 -19
  151. package/dist/src/view/testUtils.d.ts.map +1 -1
  152. package/dist/src/view/testUtils.js +6 -1
  153. package/dist/src/view/unitView.d.ts +8 -13
  154. package/dist/src/view/unitView.d.ts.map +1 -1
  155. package/dist/src/view/unitView.js +110 -41
  156. package/dist/src/view/view.d.ts +22 -14
  157. package/dist/src/view/view.d.ts.map +1 -1
  158. package/dist/src/view/view.js +93 -9
  159. package/dist/src/view/viewFactory.d.ts.map +1 -1
  160. package/dist/src/view/viewFactory.js +20 -1
  161. package/dist/src/view/viewSelectors.d.ts +148 -0
  162. package/dist/src/view/viewSelectors.d.ts.map +1 -0
  163. package/dist/src/view/viewSelectors.js +773 -0
  164. package/dist/src/view/viewSelectors.test.d.ts +2 -0
  165. package/dist/src/view/viewSelectors.test.d.ts.map +1 -0
  166. package/dist/src/view/viewUtils.d.ts +0 -8
  167. package/dist/src/view/viewUtils.d.ts.map +1 -1
  168. package/dist/src/view/viewUtils.js +1 -21
  169. package/package.json +3 -3
  170. package/dist/src/scales/scaleDomainAggregator.d.ts.map +0 -1
  171. package/dist/src/scales/scaleDomainAggregator.test.d.ts +0 -2
  172. package/dist/src/scales/scaleDomainAggregator.test.d.ts.map +0 -1
@@ -191,8 +191,14 @@ export default class Tooltip {
191
191
  Promise.resolve(html` ${JSON.stringify(d)} `);
192
192
  }
193
193
 
194
+ const requestedDatum = datum;
194
195
  converter(datum)
195
- .then((result) => this.setContent(result))
196
+ .then((result) => {
197
+ if (this.#previousTooltipDatum !== requestedDatum) {
198
+ return;
199
+ }
200
+ this.setContent(result);
201
+ })
196
202
  .catch((error) => {
197
203
  if (error !== "debounced") {
198
204
  throw error;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tooltip.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tooltip.test.d.ts","sourceRoot":"","sources":["../../../../src/utils/ui/tooltip.test.js"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"axisGridView.d.ts","sourceRoot":"","sources":["../../../src/view/axisGridView.js"],"names":[],"mappings":"AAGA;;;GAGG;AAEH;;;;;;GAMG;AACH;IACI;;;;;;;OAOG;IACH,uBAPW,IAAI,QAEJ,MAAM,WADN,OAAO,yBAAyB,EAAE,OAAO,gBAEzC,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,WAAW,EAAE,OAAO,YAC3B,OAAO,WAAW,EAAE,WAAW,EA4BzC;IADG,iFAA8B;IAGlC,kDAEC;CAKJ;gCAvDY,OAAO,oBAAoB,EAAE,wBAAwB;iCACrD,OAAO,iBAAiB,EAAE,kBAAkB;;;;mBAM5C,OAAO,WAAW,EAAE,OAAO;;;;mBAC3B,OAAO,iBAAiB,EAAE,IAAI;;;;yBAC9B,OAAO,iBAAiB,EAAE,UAAU;sBAb3B,gBAAgB"}
1
+ {"version":3,"file":"axisGridView.d.ts","sourceRoot":"","sources":["../../../src/view/axisGridView.js"],"names":[],"mappings":"AAIA;;;GAGG;AAEH;;;;;;GAMG;AACH;IACI;;;;;;;OAOG;IACH,uBAPW,IAAI,QAEJ,MAAM,WADN,OAAO,yBAAyB,EAAE,OAAO,gBAEzC,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,WAAW,EAAE,OAAO,YAC3B,OAAO,WAAW,EAAE,WAAW,EA6BzC;IAHG,iFAA8B;IAKlC,kDAEC;CAKJ;gCAxDY,OAAO,oBAAoB,EAAE,wBAAwB;iCACrD,OAAO,iBAAiB,EAAE,kBAAkB;;;;mBAM5C,OAAO,WAAW,EAAE,OAAO;;;;mBAC3B,OAAO,iBAAiB,EAAE,IAAI;;;;yBAC9B,OAAO,iBAAiB,EAAE,UAAU;sBAd3B,gBAAgB"}
@@ -1,5 +1,6 @@
1
1
  import LayerView from "./layerView.js";
2
2
  import { orient2channel } from "./axisView.js";
3
+ import { markViewAsNonAddressable } from "./viewSelectors.js";
3
4
 
4
5
  /**
5
6
  * @typedef {import("../spec/channel.js").PrimaryPositionalChannel} PositionalChannel
@@ -42,12 +43,13 @@ export default class AxisGridView extends LayerView {
42
43
  `axisGrid_${axisProps.orient}`,
43
44
  {
44
45
  blockEncodingInheritance: true,
45
- contributesToScaleDomain: false,
46
46
  ...options,
47
47
  }
48
48
  );
49
49
 
50
50
  this.axisProps = fullAxisProps;
51
+
52
+ markViewAsNonAddressable(this, { skipSubtree: true });
51
53
  }
52
54
 
53
55
  getOrient() {
@@ -121,7 +123,10 @@ function createRegularAxisGrid(axisProps, type) {
121
123
  minBufferSize: 300,
122
124
  },
123
125
  encoding: {
124
- [channel]: { field: "value", type },
126
+ [channel]: {
127
+ field: "value",
128
+ type,
129
+ },
125
130
  },
126
131
  };
127
132
  }
@@ -153,7 +158,11 @@ function createChromAxisGrid(axisProps, type) {
153
158
  },
154
159
  encoding: {
155
160
  // TODO: { chrom: "name", type: "locus" } // without pos = pos is 0
156
- [channel]: { field: "continuousStart", type, band: 0 },
161
+ [channel]: {
162
+ field: "continuousStart",
163
+ type,
164
+ band: 0,
165
+ },
157
166
  },
158
167
  };
159
168
  }
@@ -180,8 +189,15 @@ function createChromAxisFill(axisProps, type) {
180
189
  },
181
190
  encoding: {
182
191
  // TODO: { chrom: "name", type: "locus" } // without pos = pos is 0
183
- [channel]: { field: "continuousStart", type, band: 0 },
184
- [channel + "2"]: { field: "continuousEnd", band: 0 },
192
+ [channel]: {
193
+ field: "continuousStart",
194
+ type,
195
+ band: 0,
196
+ },
197
+ [channel + "2"]: {
198
+ field: "continuousEnd",
199
+ band: 0,
200
+ },
185
201
  fill: {
186
202
  field: "odd",
187
203
  type: "nominal",
@@ -245,6 +261,7 @@ function createAxisGrid(axisProps, type) {
245
261
  opacity: "independent",
246
262
  },
247
263
  },
264
+ domainInert: true,
248
265
  layer: layers,
249
266
  };
250
267
  }
@@ -1 +1 @@
1
- {"version":3,"file":"axisView.d.ts","sourceRoot":"","sources":["../../../src/view/axisView.js"],"names":[],"mappings":"AAoCA;;GAEG;AACH,kIAEC;AAkYD;;;;GAIG;AACH,wFAHW,MAAM,uCA2MhB;AArmBD;;GAEG;AACH,8BAFU,MAAM,CAAC,OAAO,oBAAoB,EAAE,wBAAwB,EAAE,sCAAY,CAAC,CAKnF;AAEF;;GAEG;AACH,8BAFU,MAAM,uCAAa,OAAO,oBAAoB,EAAE,wBAAwB,CAAC,CAMjF;AASF;;;;;GAKG;AACH;IACI;;;;;;;;;;OAUG;IAEH;;;;;;;OAOG;IACH,6DALW,MAAM,WADN,OAAO,yBAAyB,EAAE,OAAO,gBAEzC,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,WAAW,EAAE,OAAO,YAC3B,OAAO,WAAW,EAAE,WAAW,EAiCzC;IADG,iFAA8B;IAiBlC,+BAEC;CAKJ;sBA5HqB,gBAAgB"}
1
+ {"version":3,"file":"axisView.d.ts","sourceRoot":"","sources":["../../../src/view/axisView.js"],"names":[],"mappings":"AAqCA;;GAEG;AACH,kIAEC;AAyYD;;;;GAIG;AACH,wFAHW,MAAM,uCAkNhB;AAnnBD;;GAEG;AACH,8BAFU,MAAM,CAAC,OAAO,oBAAoB,EAAE,wBAAwB,EAAE,sCAAY,CAAC,CAKnF;AAEF;;GAEG;AACH,8BAFU,MAAM,uCAAa,OAAO,oBAAoB,EAAE,wBAAwB,CAAC,CAMjF;AASF;;;;;GAKG;AACH;IACI;;;;;;;;;;OAUG;IAEH;;;;;;;OAOG;IACH,6DALW,MAAM,WADN,OAAO,yBAAyB,EAAE,OAAO,gBAEzC,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,WAAW,EAAE,OAAO,YAC3B,OAAO,WAAW,EAAE,WAAW,EAkCzC;IAHG,iFAA8B;IAmBlC,+BAEC;CAKJ;sBA9HqB,gBAAgB"}
@@ -1,5 +1,6 @@
1
1
  import LayerView from "./layerView.js";
2
2
  import { FlexDimensions } from "./layout/flexLayout.js";
3
+ import { markViewAsNonAddressable } from "./viewSelectors.js";
3
4
 
4
5
  const CHROM_LAYER_NAME = "chromosome_ticks_and_labels";
5
6
 
@@ -93,12 +94,13 @@ export default class AxisView extends LayerView {
93
94
  `axis_${axisProps.orient}`,
94
95
  {
95
96
  blockEncodingInheritance: true,
96
- contributesToScaleDomain: false,
97
97
  ...options,
98
98
  }
99
99
  );
100
100
 
101
101
  this.axisProps = fullAxisProps;
102
+
103
+ markViewAsNonAddressable(this, { skipSubtree: true });
102
104
  }
103
105
 
104
106
  getSize() {
@@ -266,6 +268,11 @@ function createAxis(axisProps, type) {
266
268
 
267
269
  const anchor = ap.orient == "bottom" || ap.orient == "left" ? 1 : 0;
268
270
 
271
+ const makeMainDomainDef = () => ({
272
+ field: "value",
273
+ type,
274
+ });
275
+
269
276
  /**
270
277
  * @return {import("../spec/view.js").UnitSpec}
271
278
  */
@@ -302,7 +309,7 @@ function createAxis(axisProps, type) {
302
309
  minBufferSize: 1500, // to prevent GPU buffer reallocation when zooming
303
310
  },
304
311
  encoding: {
305
- [main]: { field: "value", type },
312
+ [main]: makeMainDomainDef(),
306
313
  text: { field: "label" },
307
314
  },
308
315
  });
@@ -358,7 +365,7 @@ function createAxis(axisProps, type) {
358
365
  const spec = {
359
366
  name: "ticks_and_labels",
360
367
  encoding: {
361
- [main]: { field: "value", type },
368
+ [main]: makeMainDomainDef(),
362
369
  },
363
370
  layer: [],
364
371
  };
@@ -378,6 +385,7 @@ function createAxis(axisProps, type) {
378
385
  const axisSpec = {
379
386
  // Force the resolution towards the parent view even if it has "independent" behavior
380
387
  resolve: { scale: { [main]: "forced" } },
388
+ domainInert: true,
381
389
  [CHANNEL_DIMENSIONS[getPerpendicularChannel(main)]]: ap.extent,
382
390
  data: {
383
391
  lazy: {
@@ -527,7 +535,10 @@ export function createGenomeAxis(axisProps, type) {
527
535
  ...chromLabelMarkProps,
528
536
  },
529
537
  encoding: {
530
- [main + "2"]: { field: "continuousEnd", type },
538
+ [main + "2"]: {
539
+ field: "continuousEnd",
540
+ type,
541
+ },
531
542
  text: { field: "name" },
532
543
  },
533
544
  };
@@ -582,7 +593,11 @@ export function createGenomeAxis(axisProps, type) {
582
593
  },
583
594
  encoding: {
584
595
  // TODO: { chrom: "name", type: "locus" } // without pos = pos is 0
585
- [main]: { field: "continuousStart", type, band: 0 },
596
+ [main]: {
597
+ field: "continuousStart",
598
+ type,
599
+ band: 0,
600
+ },
586
601
  },
587
602
  layer: [],
588
603
  };
@@ -44,12 +44,12 @@ export default class ConcatView extends GridView {
44
44
 
45
45
  this.setChildren(
46
46
  await Promise.all(
47
- childSpecs.map((childSpec, i) =>
47
+ childSpecs.map((childSpec) =>
48
48
  this.context.createOrImportView(
49
49
  childSpec,
50
50
  this,
51
51
  this,
52
- "grid" + i
52
+ this.getNextAutoName("grid")
53
53
  )
54
54
  )
55
55
  )
@@ -151,7 +151,7 @@ export default class ConcatView extends GridView {
151
151
  afterRemove: async () => {
152
152
  await this.syncSharedAxes();
153
153
  },
154
- defaultName: (_index) => "grid" + this.childCount,
154
+ defaultName: () => this.getNextAutoName("grid"),
155
155
  });
156
156
  }
157
157
  }
@@ -55,7 +55,7 @@ export default class ContainerMutationHelper {
55
55
  const insertIndex = index ?? specs.length;
56
56
  const name =
57
57
  this.options.defaultName?.(insertIndex, childSpec) ??
58
- "child" + specs.length;
58
+ this.container.getNextAutoName("child");
59
59
 
60
60
  const childView = await this.container.context.createOrImportView(
61
61
  childSpec,
@@ -14,16 +14,19 @@ export default class ContainerView extends View {
14
14
  constructor(spec: import("../spec/view.js").ContainerSpec, context: import("../types/viewContext.js").default, layoutParent: ContainerView, dataParent: import("./view.js").default, name: string, options?: import("./view.js").ViewOptions);
15
15
  spec: import("../spec/view.js").ContainerSpec;
16
16
  initializeChildren(): Promise<void>;
17
+ /**
18
+ * Generates an auto name that is guaranteed to be unique within this container
19
+ * for the given prefix. Intended for debugging-only default names.
20
+ *
21
+ * @param {string} prefix
22
+ * @returns {string}
23
+ */
24
+ getNextAutoName(prefix: string): string;
17
25
  /**
18
26
  * @param {string[]} path An array of view names
19
27
  * @returns {View}
20
28
  */
21
29
  findDescendantByPath(path: string[]): View;
22
- /**
23
- *
24
- * @param {string} name
25
- */
26
- findChildByName(name: string): View;
27
30
  /**
28
31
  *
29
32
  * @param {string} name
@@ -33,6 +36,7 @@ export default class ContainerView extends View {
33
36
  * @returns {IterableIterator<View>}
34
37
  */
35
38
  [Symbol.iterator](): IterableIterator<View>;
39
+ #private;
36
40
  }
37
41
  import View from "./view.js";
38
42
  //# sourceMappingURL=containerView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"containerView.d.ts","sourceRoot":"","sources":["../../../src/view/containerView.js"],"names":[],"mappings":"AAEA;;GAEG;AACH;IACI;;;;;;;;OAQG;IACH,kBAPW,OAAO,iBAAiB,EAAE,aAAa,WACvC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,aAAa,cACb,OAAO,WAAW,EAAE,OAAO,QAC3B,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,EAMzC;IADG,8CAAgB;IAGpB,oCAEC;IAsDD;;;OAGG;IACH,2BAHW,MAAM,EAAE,GACN,IAAI,CAYhB;IAED;;;OAGG;IACH,sBAFW,MAAM,QAQhB;IAED;;;OAGG;IACH,2BAFW,MAAM,QAchB;IAhGD;;OAEG;IACH,qBAFa,gBAAgB,CAAC,IAAI,CAAC,CAIlC;CAqGJ;iBAnI4C,WAAW"}
1
+ {"version":3,"file":"containerView.d.ts","sourceRoot":"","sources":["../../../src/view/containerView.js"],"names":[],"mappings":"AAEA;;GAEG;AACH;IAII;;;;;;;;OAQG;IACH,kBAPW,OAAO,iBAAiB,EAAE,aAAa,WACvC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,aAAa,cACb,OAAO,WAAW,EAAE,OAAO,QAC3B,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,EAMzC;IADG,8CAAgB;IAGpB,oCAEC;IAED;;;;;;OAMG;IACH,wBAHW,MAAM,GACJ,MAAM,CAMlB;IAsDD;;;OAGG;IACH,2BAHW,MAAM,EAAE,GACN,IAAI,CAsBhB;IAaD;;;OAGG;IACH,2BAFW,MAAM,QAchB;IAzGD;;OAEG;IACH,qBAFa,gBAAgB,CAAC,IAAI,CAAC,CAIlC;;CA8GJ;iBA5J4C,WAAW"}
@@ -4,6 +4,9 @@ import View, { VISIT_STOP, VISIT_SKIP } from "./view.js";
4
4
  * Compositor view represents a non-leaf node in the view hierarchy.
5
5
  */
6
6
  export default class ContainerView extends View {
7
+ /** @type {Map<string, number>} */
8
+ #autoNameCounters = new Map();
9
+
7
10
  /**
8
11
  *
9
12
  * @param {import("../spec/view.js").ContainerSpec} spec
@@ -23,6 +26,19 @@ export default class ContainerView extends View {
23
26
  // override
24
27
  }
25
28
 
29
+ /**
30
+ * Generates an auto name that is guaranteed to be unique within this container
31
+ * for the given prefix. Intended for debugging-only default names.
32
+ *
33
+ * @param {string} prefix
34
+ * @returns {string}
35
+ */
36
+ getNextAutoName(prefix) {
37
+ const counter = this.#autoNameCounters.get(prefix) ?? 0;
38
+ this.#autoNameCounters.set(prefix, counter + 1);
39
+ return prefix + counter;
40
+ }
41
+
26
42
  /**
27
43
  * @returns {IterableIterator<View>}
28
44
  */
@@ -80,22 +96,31 @@ export default class ContainerView extends View {
80
96
  * @returns {View}
81
97
  */
82
98
  findDescendantByPath(path) {
83
- for (const child of this) {
84
- if (child.name === path[0]) {
85
- if (path.length == 1) {
86
- return child;
87
- } else if (child instanceof ContainerView) {
88
- return child.findDescendantByPath(path.slice(1));
89
- }
99
+ /** @type {View | ContainerView} */
100
+ let current = this;
101
+
102
+ for (let i = 0; i < path.length; i++) {
103
+ if (!(current instanceof ContainerView)) {
104
+ return;
105
+ }
106
+
107
+ const next = current.#findImmediateChildByName(path[i]);
108
+ if (!next) {
109
+ return;
90
110
  }
111
+
112
+ if (i === path.length - 1) {
113
+ return next;
114
+ }
115
+
116
+ current = next;
91
117
  }
92
118
  }
93
119
 
94
120
  /**
95
- *
96
121
  * @param {string} name
97
122
  */
98
- findChildByName(name) {
123
+ #findImmediateChildByName(name) {
99
124
  for (const child of this) {
100
125
  if (child.name === name) {
101
126
  return child;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @typedef {import("../view/view.js").default} View
3
+ * @typedef {import("../data/sources/lazy/singleAxisLazySource.js").DataReadinessRequest} DataReadinessRequest
4
+ */
5
+ /**
6
+ * Builds a readiness request for the provided channels.
7
+ *
8
+ * @param {View} view
9
+ * @param {import("../spec/channel.js").PrimaryPositionalChannel[]} channels
10
+ * @returns {DataReadinessRequest | undefined}
11
+ */
12
+ export function buildReadinessRequest(view: View, channels: import("../spec/channel.js").PrimaryPositionalChannel[]): DataReadinessRequest | undefined;
13
+ /**
14
+ * Checks whether all data sources under the subtree report readiness.
15
+ *
16
+ * @param {View} subtreeRoot
17
+ * @param {DataReadinessRequest} readinessRequest
18
+ * @param {(view: View) => boolean} [viewFilter]
19
+ * @returns {boolean}
20
+ */
21
+ export function isSubtreeReady(subtreeRoot: View, readinessRequest: DataReadinessRequest, viewFilter?: (view: View) => boolean): boolean;
22
+ /**
23
+ * Checks readiness for lazy data sources under the subtree. Non-lazy sources
24
+ * are ignored so they do not block readiness checks.
25
+ *
26
+ * @param {View} subtreeRoot
27
+ * @param {DataReadinessRequest | undefined} readinessRequest
28
+ * @param {(view: View) => boolean} [viewFilter]
29
+ * @returns {boolean}
30
+ */
31
+ export function isSubtreeLazyReady(subtreeRoot: View, readinessRequest: DataReadinessRequest | undefined, viewFilter?: (view: View) => boolean): boolean;
32
+ /**
33
+ * Waits until lazy data sources under the subtree satisfy the readiness request.
34
+ * Non-lazy sources are ignored so they do not block readiness checks.
35
+ *
36
+ * @param {import("../types/viewContext.js").default} context
37
+ * @param {View} subtreeRoot
38
+ * @param {DataReadinessRequest} readinessRequest
39
+ * @param {AbortSignal} [signal]
40
+ * @param {(view: View) => boolean} [viewFilter]
41
+ * @returns {Promise<void>}
42
+ */
43
+ export function awaitSubtreeLazyReady(context: import("../types/viewContext.js").default, subtreeRoot: View, readinessRequest: DataReadinessRequest, signal?: AbortSignal, viewFilter?: (view: View) => boolean): Promise<void>;
44
+ export type View = import("../view/view.js").default;
45
+ export type DataReadinessRequest = import("../data/sources/lazy/singleAxisLazySource.js").DataReadinessRequest;
46
+ //# sourceMappingURL=dataReadiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataReadiness.d.ts","sourceRoot":"","sources":["../../../src/view/dataReadiness.js"],"names":[],"mappings":"AAGA;;;GAGG;AAEH;;;;;;GAMG;AACH,4CAJW,IAAI,YACJ,OAAO,oBAAoB,EAAE,wBAAwB,EAAE,GACrD,oBAAoB,GAAG,SAAS,CAe5C;AAED;;;;;;;GAOG;AACH,4CALW,IAAI,oBACJ,oBAAoB,eACpB,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,GACrB,OAAO,CAiDnB;AAED;;;;;;;;GAQG;AACH,gDALW,IAAI,oBACJ,oBAAoB,GAAG,SAAS,eAChC,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,GACrB,OAAO,CAwDnB;AAED;;;;;;;;;;GAUG;AACH,+CAPW,OAAO,yBAAyB,EAAE,OAAO,eACzC,IAAI,oBACJ,oBAAoB,WACpB,WAAW,eACX,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,GACrB,OAAO,CAAC,IAAI,CAAC,CAyGzB;mBAtQY,OAAO,iBAAiB,EAAE,OAAO;mCACjC,OAAO,8CAA8C,EAAE,oBAAoB"}
@@ -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"}