@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
@@ -33,25 +33,20 @@ export default class UnitView extends View {
33
33
  * @param {Channel} channel
34
34
  */
35
35
  getDataAccessor(channel: import("../spec/channel.js").Channel): import("../types/encoder.js").Accessor<import("../spec/channel.js").Scalar>;
36
+ /**
37
+ * Returns data accessors configured for the `search` channel.
38
+ *
39
+ * @returns {import("vega-util").AccessorFn[]}
40
+ */
41
+ getSearchAccessors(): import("vega-util").AccessorFn[];
36
42
  /**
37
43
  * Returns a collector that is associated with this view.
38
44
  */
39
45
  getCollector(): import("../data/collector.js").default;
40
46
  /**
41
- * Extracts the domain from the data.
42
- *
43
- * TODO: Optimize! Now this performs redundant work if multiple views share the same collector.
44
- * Also, all relevant fields should be processed in one iteration: https://jsbench.me/y5kkqy52jo/1
45
- * In fact, domain extraction could be a responsibility of the collector: As it handles data items,
46
- * it extracts domains for all fields (and data types) that need extracted domains.
47
- * Alternatively, extractor nodes could be added to the data flow, just like Vega does
48
- * (with aggregate and extent).
49
- *
50
- * @param {Channel} channel
51
- * @param {import("../spec/channel.js").Type} type
52
- * @returns {DomainArray}
47
+ * Registers collector subscriptions that keep scale domains up to date.
53
48
  */
54
- extractDataDomain(channel: import("../spec/channel.js").Channel, type: import("../spec/channel.js").Type): import("../utils/domainArray.js").DomainArray;
49
+ registerDomainSubscriptions(): void;
55
50
  getZoomLevel(): number;
56
51
  /**
57
52
  * @param {string} channel
@@ -1 +1 @@
1
- {"version":3,"file":"unitView.d.ts","sourceRoot":"","sources":["../../../src/view/unitView.js"],"names":[],"mappings":"AA6BA;;;;GAIG;AACH,wBAHU,MAAM,CAAC,OAAO,iBAAiB,EAAE,QAAQ,EAAE,cAAc,kBAAkB,EAAE,OAAO,CAAC,CAc7F;AAEF;IAeI;;;;;;;;OAQG;IACH,kBAPW,OAAO,iBAAiB,EAAE,QAAQ,WAClC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,WAAW,EAAE,OAAO,QAC3B,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,EAyCzC;IApCG,yCAAgB;IAIZ,iDAAiD;IACjD,MADW,OAAO,kBAAkB,EAAE,OAAO,CACnB;IAoKlC,2DAIC;IAgBD;;;;;OAKG;IAEH,iEAyJC;IAUD;;;;;OAKG;IACH,4IAMC;IAkBD;;OAEG;IACH,uDAEC;IAED;;;;;;;;;;;;;OAaG;IACH,uEAHW,OAAO,oBAAoB,EAAE,IAAI,iDAqB3C;IAED,uBAQC;IAgBD;;;;OAIG;IACH,8BAJW,MAAM,+DAEJ,OAAO,iBAAiB,EAAE,kBAAkB,CAKxD;;CACJ;iBAvgBgB,WAAW"}
1
+ {"version":3,"file":"unitView.d.ts","sourceRoot":"","sources":["../../../src/view/unitView.js"],"names":[],"mappings":"AA+BA;;;;GAIG;AACH,wBAHU,MAAM,CAAC,OAAO,iBAAiB,EAAE,QAAQ,EAAE,cAAc,kBAAkB,EAAE,OAAO,CAAC,CAc7F;AAEF;IAwBI;;;;;;;;OAQG;IACH,kBAPW,OAAO,iBAAiB,EAAE,QAAQ,WAClC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,WAAW,EAAE,OAAO,QAC3B,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,EAyCzC;IApCG,yCAAgB;IAIZ,iDAAiD;IACjD,MADW,OAAO,kBAAkB,EAAE,OAAO,CACnB;IAoKlC,2DAIC;IAoBD;;;;;OAKG;IAEH,iEAoJC;IAUD;;;;;OAKG;IACH,4IAMC;IAED;;;;OAIG;IACH,sBAFa,OAAO,WAAW,EAAE,UAAU,EAAE,CAS5C;IAkBD;;OAEG;IACH,uDAEC;IAED;;OAEG;IACH,oCA0EC;IAED,uBAQC;IAgBD;;;;OAIG;IACH,8BAJW,MAAM,+DAEJ,OAAO,iBAAiB,EAAE,kBAAkB,CAKxD;;CACJ;iBA5kBgB,WAAW"}
@@ -14,7 +14,7 @@ import {
14
14
  isPrimaryPositionalChannel,
15
15
  isValueDefWithCondition,
16
16
  } from "../encoder/encoder.js";
17
- import createDomain from "../utils/domainArray.js";
17
+ import { isScaleAccessor } from "../encoder/accessor.js";
18
18
  import AxisResolution from "../scales/axisResolution.js";
19
19
  import View from "./view.js";
20
20
  import {
@@ -24,8 +24,10 @@ import {
24
24
  isPointSelectionConfig,
25
25
  updateMultiPointSelection,
26
26
  } from "../selection/selection.js";
27
+ import { getEncodingSearchFields } from "../encoder/metadataChannels.js";
27
28
  import { UNIQUE_ID_KEY } from "../data/transforms/identifier.js";
28
29
  import { createEventFilterFunction } from "../utils/expression.js";
30
+ import { field } from "../utils/field.js";
29
31
 
30
32
  /**
31
33
  *
@@ -48,7 +50,6 @@ export const markTypes = {
48
50
  export default class UnitView extends View {
49
51
  /**
50
52
  * @typedef {import("../spec/channel.js").Channel} Channel
51
- * @typedef {import("../utils/domainArray.js").DomainArray} DomainArray
52
53
  * @typedef {import("../spec/view.js").ResolutionTarget} ResolutionTarget
53
54
  * @typedef {((datum: import("../data/flowNode.js").Datum) => import("../spec/channel.js").Scalar) & { fieldDef: import("../spec/channel.js").FieldDef}} FieldAccessor
54
55
  *
@@ -60,6 +61,16 @@ export default class UnitView extends View {
60
61
  */
61
62
  #zoomLevelSetter;
62
63
 
64
+ /**
65
+ * @type {boolean}
66
+ */
67
+ #domainSubscriptionsRegistered = false;
68
+
69
+ /**
70
+ * @type {import("vega-util").AccessorFn[] | null}
71
+ */
72
+ #searchAccessors = null;
73
+
63
74
  /**
64
75
  *
65
76
  * @param {import("../spec/view.js").UnitSpec} spec
@@ -253,6 +264,10 @@ export default class UnitView extends View {
253
264
  const encoding = super.getEncoding();
254
265
  const supportedChannels = this.mark.getSupportedChannels();
255
266
  for (const channel of Object.keys(encoding)) {
267
+ if (channel === "key") {
268
+ continue;
269
+ }
270
+
256
271
  if (!supportedChannels.includes(channel)) {
257
272
  delete encoding[channel];
258
273
  }
@@ -284,6 +299,10 @@ export default class UnitView extends View {
284
299
  continue;
285
300
  }
286
301
 
302
+ if (Array.isArray(channelDef)) {
303
+ continue;
304
+ }
305
+
287
306
  /** @type {import("../spec/channel.js").ChannelDefWithScale} */
288
307
  let channelDefWithScale;
289
308
 
@@ -392,23 +411,14 @@ export default class UnitView extends View {
392
411
  });
393
412
  }
394
413
 
395
- const dataDomainSource =
396
- this.getLayoutAncestors()
397
- // TODO: Should check until the resolved scale resolution
398
- .some(
399
- (view) => !view.options.contributesToScaleDomain
400
- ) ||
401
- (isChannelDefWithScale(channelDefWithScale) &&
402
- channelDefWithScale.contributesToScaleDomain === false)
403
- ? undefined
404
- : this.extractDataDomain.bind(this);
414
+ const contributesToDomain = !this.isDomainInert();
405
415
 
406
416
  const resolution = view.resolutions[type][targetChannel];
407
417
  const unregister = resolution.registerMember({
408
418
  view: this,
409
419
  channel,
410
420
  channelDef: channelDefWithScale,
411
- dataDomainSource,
421
+ contributesToDomain,
412
422
  });
413
423
  this.registerDisposer(() => {
414
424
  // Unregister returns true when it removed the last member.
@@ -445,6 +455,20 @@ export default class UnitView extends View {
445
455
  return encoders[channel]?.dataAccessor;
446
456
  }
447
457
 
458
+ /**
459
+ * Returns data accessors configured for the `search` channel.
460
+ *
461
+ * @returns {import("vega-util").AccessorFn[]}
462
+ */
463
+ getSearchAccessors() {
464
+ if (!this.#searchAccessors) {
465
+ const fields = getEncodingSearchFields(this.getEncoding()) ?? [];
466
+ this.#searchAccessors = fields.map((fieldName) => field(fieldName));
467
+ }
468
+
469
+ return this.#searchAccessors;
470
+ }
471
+
448
472
  /**
449
473
  * Returns an accessor that returns a (composite) key for partitioning the data
450
474
  *
@@ -469,37 +493,82 @@ export default class UnitView extends View {
469
493
  }
470
494
 
471
495
  /**
472
- * Extracts the domain from the data.
473
- *
474
- * TODO: Optimize! Now this performs redundant work if multiple views share the same collector.
475
- * Also, all relevant fields should be processed in one iteration: https://jsbench.me/y5kkqy52jo/1
476
- * In fact, domain extraction could be a responsibility of the collector: As it handles data items,
477
- * it extracts domains for all fields (and data types) that need extracted domains.
478
- * Alternatively, extractor nodes could be added to the data flow, just like Vega does
479
- * (with aggregate and extent).
480
- *
481
- * @param {Channel} channel
482
- * @param {import("../spec/channel.js").Type} type
483
- * @returns {DomainArray}
496
+ * Registers collector subscriptions that keep scale domains up to date.
484
497
  */
485
- extractDataDomain(channel, type) {
486
- /** @type {DomainArray} */
487
- let domain = createDomain(type);
488
-
489
- (this.mark.encoders[channel]?.accessors ?? [])
490
- .filter((a) => a.scaleChannel)
491
- .forEach((accessor) => {
492
- if (accessor.constant) {
493
- domain.extend(accessor({}));
494
- } else {
495
- const collector = this.getCollector();
496
- if (collector?.completed) {
497
- collector.visitData((d) => domain.extend(accessor(d)));
498
- }
498
+ registerDomainSubscriptions() {
499
+ if (this.#domainSubscriptionsRegistered) {
500
+ return;
501
+ }
502
+
503
+ if (this.isDomainInert()) {
504
+ return;
505
+ }
506
+
507
+ const collector = this.getCollector();
508
+ if (!collector) {
509
+ return;
510
+ }
511
+
512
+ const encoders = this.mark.encoders;
513
+ if (!encoders) {
514
+ throw new Error("Encoders are not initialized!");
515
+ }
516
+
517
+ this.#domainSubscriptionsRegistered = true;
518
+
519
+ /** @type {Map<import("../scales/scaleResolution.js").default, Set<import("../types/encoder.js").ScaleAccessor>>} */
520
+ const accessorsByResolution = new Map();
521
+
522
+ for (const encoder of Object.values(encoders)) {
523
+ if (!encoder) {
524
+ continue;
525
+ }
526
+
527
+ const accessors = encoder.accessors ?? [];
528
+ if (accessors.length === 0) {
529
+ continue;
530
+ }
531
+
532
+ for (const accessor of accessors) {
533
+ if (!isScaleAccessor(accessor)) {
534
+ continue;
535
+ }
536
+ if (accessor.channelDef.domainInert) {
537
+ continue;
538
+ }
539
+ const resolution = this.getScaleResolution(
540
+ accessor.scaleChannel
541
+ );
542
+ if (!resolution) {
543
+ throw new Error(
544
+ "Missing scale resolution for channel: " +
545
+ accessor.scaleChannel
546
+ );
499
547
  }
500
- });
501
548
 
502
- return domain;
549
+ let accessorsForResolution =
550
+ accessorsByResolution.get(resolution);
551
+ if (!accessorsForResolution) {
552
+ accessorsForResolution = new Set();
553
+ accessorsByResolution.set(
554
+ resolution,
555
+ accessorsForResolution
556
+ );
557
+ }
558
+ accessorsForResolution.add(accessor);
559
+ }
560
+ }
561
+
562
+ for (const [resolution, accessors] of accessorsByResolution) {
563
+ if (accessors.size === 0) {
564
+ continue;
565
+ }
566
+ const unregister = resolution.registerCollectorSubscriptions(
567
+ collector,
568
+ accessors
569
+ );
570
+ this.registerDisposer(unregister);
571
+ }
503
572
  }
504
573
 
505
574
  getZoomLevel() {
@@ -27,9 +27,6 @@ export const VISIT_STOP: "VISIT_STOP";
27
27
  * @typedef {object} ViewOptions
28
28
  * @prop {boolean} [blockEncodingInheritance]
29
29
  * Don't inherit encodings from parent. Default: false.
30
- * @prop {boolean} [contributesToScaleDomain]
31
- * Whether ScaleResolution should include this view or its children in the
32
- * domain. Default: true
33
30
  * @prop {boolean} [layersChildren]
34
31
  * View's children are layered on top of each other and they have the same
35
32
  * coordinates as their parent.
@@ -60,7 +57,6 @@ export default class View {
60
57
  context: import("../types/viewContext.js").default;
61
58
  layoutParent: import("./containerView.js").default;
62
59
  dataParent: View;
63
- name: string;
64
60
  spec: import("../spec/view.js").ViewSpec;
65
61
  resolutions: {
66
62
  /**
@@ -79,11 +75,6 @@ export default class View {
79
75
  * Don't inherit encodings from parent. Default: false.
80
76
  */
81
77
  blockEncodingInheritance: boolean;
82
- /**
83
- * Whether ScaleResolution should include this view or its children in the
84
- * domain. Default: true
85
- */
86
- contributesToScaleDomain: boolean;
87
78
  /**
88
79
  * View's children are layered on top of each other and they have the same
89
80
  * coordinates as their parent.
@@ -102,6 +93,20 @@ export default class View {
102
93
  needsAxes: Record<import("../spec/channel.js").PrimaryPositionalChannel, boolean>;
103
94
  /** @type {ParamMediator} */
104
95
  paramMediator: ParamMediator;
96
+ /**
97
+ * Effective view name. Equals the explicit name (`spec.name`) when provided,
98
+ * otherwise falls back to an auto-generated default name.
99
+ */
100
+ get name(): string;
101
+ /**
102
+ * The explicit name from the spec (`spec.name`), if any.
103
+ */
104
+ get explicitName(): string;
105
+ /**
106
+ * The auto-generated default name that was assigned by the parent/factory.
107
+ * Intended for debugging only.
108
+ */
109
+ get defaultName(): string;
105
110
  /**
106
111
  * Returns the coords of the view. If view has been faceted, returns the coords
107
112
  * of an arbitrary facet. If all or specific facet coords are needed, use `facetCoords`.
@@ -134,6 +139,7 @@ export default class View {
134
139
  * @returns {FlexDimensions}
135
140
  */
136
141
  getViewportSize(): FlexDimensions;
142
+ registerStepSizeInvalidation(): void;
137
143
  isConfiguredVisible(): boolean;
138
144
  isVisibleInSpec(): boolean;
139
145
  /**
@@ -146,6 +152,12 @@ export default class View {
146
152
  * @returns {boolean}
147
153
  */
148
154
  isVisible(): boolean;
155
+ /**
156
+ * Returns true if this view or any ancestor is marked as domain inert.
157
+ *
158
+ * @returns {boolean}
159
+ */
160
+ isDomainInert(): boolean;
149
161
  /**
150
162
  * @returns {"none" | "pending" | "ready"}
151
163
  */
@@ -250,6 +262,7 @@ export default class View {
250
262
  * pass. The order is depth first, pre order.
251
263
  */
252
264
  onBeforeRender(): void;
265
+ hasRendered(): boolean;
253
266
  render(context: import("./renderingContext/viewRenderingContext.js").default, coords: import("./layout/rectangle.js").default, options?: import("../types/rendering.js").RenderingOptions): void;
254
267
  /**
255
268
  * Returns the encodings specified in this view combined with the inherited
@@ -372,11 +385,6 @@ export type ViewOptions = {
372
385
  * Don't inherit encodings from parent. Default: false.
373
386
  */
374
387
  blockEncodingInheritance?: boolean;
375
- /**
376
- * Whether ScaleResolution should include this view or its children in the
377
- * domain. Default: true
378
- */
379
- contributesToScaleDomain?: boolean;
380
388
  /**
381
389
  * View's children are layered on top of each other and they have the same
382
390
  * coordinates as their parent.
@@ -1 +1 @@
1
- {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../../src/view/view.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../../src/view/view.js"],"names":[],"mappings":"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"}
@@ -58,14 +58,14 @@ const defaultOpacityFunction = (parentOpacity) => parentOpacity;
58
58
  * @typedef {object} ViewOptions
59
59
  * @prop {boolean} [blockEncodingInheritance]
60
60
  * Don't inherit encodings from parent. Default: false.
61
- * @prop {boolean} [contributesToScaleDomain]
62
- * Whether ScaleResolution should include this view or its children in the
63
- * domain. Default: true
64
61
  * @prop {boolean} [layersChildren]
65
62
  * View's children are layered on top of each other and they have the same
66
63
  * coordinates as their parent.
67
64
  */
68
65
  export default class View {
66
+ /** @type {string | undefined} */
67
+ #defaultName;
68
+
69
69
  /** @type {Record<string, (function(BroadcastMessage):void)[]>} */
70
70
  #broadcastHandlers = {};
71
71
 
@@ -81,6 +81,9 @@ export default class View {
81
81
  /** @type {(value: number) => void} */
82
82
  #heightSetter;
83
83
 
84
+ /** @type {boolean} */
85
+ #hasRendered = false;
86
+
84
87
  /**
85
88
  * @type {function(number):number}
86
89
  */
@@ -122,7 +125,7 @@ export default class View {
122
125
  this.context = context;
123
126
  this.layoutParent = layoutParent;
124
127
  this.dataParent = dataParent;
125
- this.name = spec.name || name;
128
+ this.#defaultName = name;
126
129
  this.spec = spec;
127
130
 
128
131
  this.resolutions = {
@@ -142,7 +145,6 @@ export default class View {
142
145
 
143
146
  this.options = {
144
147
  blockEncodingInheritance: false,
145
- contributesToScaleDomain: true,
146
148
  ...options,
147
149
  };
148
150
 
@@ -184,6 +186,29 @@ export default class View {
184
186
  }
185
187
  }
186
188
 
189
+ /**
190
+ * Effective view name. Equals the explicit name (`spec.name`) when provided,
191
+ * otherwise falls back to an auto-generated default name.
192
+ */
193
+ get name() {
194
+ return this.spec.name ?? this.#defaultName;
195
+ }
196
+
197
+ /**
198
+ * The explicit name from the spec (`spec.name`), if any.
199
+ */
200
+ get explicitName() {
201
+ return this.spec.name;
202
+ }
203
+
204
+ /**
205
+ * The auto-generated default name that was assigned by the parent/factory.
206
+ * Intended for debugging only.
207
+ */
208
+ get defaultName() {
209
+ return this.#defaultName;
210
+ }
211
+
187
212
  /**
188
213
  * Returns the coords of the view. If view has been faceted, returns the coords
189
214
  * of an arbitrary facet. If all or specific facet coords are needed, use `facetCoords`.
@@ -265,11 +290,12 @@ export default class View {
265
290
  */
266
291
  #getDimensionSize(dimension) {
267
292
  let value = this.spec[dimension];
293
+ const needsStepInvalidation = isStepSize(value);
268
294
 
269
295
  const viewport =
270
296
  dimension == "viewportWidth" || dimension == "viewportHeight";
271
297
 
272
- if (isStepSize(value)) {
298
+ if (needsStepInvalidation) {
273
299
  if (viewport) {
274
300
  throw new ViewError(
275
301
  `Cannot use step-based size with "${dimension}"!`,
@@ -313,7 +339,7 @@ export default class View {
313
339
  return { px: steps * stepSize, grow: 0 };
314
340
  } else {
315
341
  throw new ViewError(
316
- "Cannot use 'step' size with missing scale!",
342
+ `Cannot use step-based size with "${dimension}"!`,
317
343
  this
318
344
  );
319
345
  }
@@ -325,6 +351,36 @@ export default class View {
325
351
  }
326
352
  }
327
353
 
354
+ registerStepSizeInvalidation() {
355
+ this.#registerStepSizeInvalidationFor("width", "x");
356
+ this.#registerStepSizeInvalidationFor("height", "y");
357
+ }
358
+
359
+ /**
360
+ * @param {"width" | "height"} dimension
361
+ * @param {import("../spec/channel.js").PrimaryPositionalChannel} channel
362
+ */
363
+ #registerStepSizeInvalidationFor(dimension, channel) {
364
+ const value = this.spec[dimension];
365
+ if (!isStepSize(value)) {
366
+ return;
367
+ }
368
+
369
+ const resolution = this.getScaleResolution(channel);
370
+ if (!resolution) {
371
+ throw new ViewError(
372
+ "Cannot use 'step' size without a scale!",
373
+ this
374
+ );
375
+ }
376
+
377
+ const listener = () => this.invalidateSizeCache();
378
+ resolution.addEventListener("domain", listener);
379
+ this.registerDisposer(() =>
380
+ resolution.removeEventListener("domain", listener)
381
+ );
382
+ }
383
+
328
384
  isConfiguredVisible() {
329
385
  return this.context.isViewConfiguredVisible(this);
330
386
  }
@@ -348,6 +404,24 @@ export default class View {
348
404
  );
349
405
  }
350
406
 
407
+ /**
408
+ * Returns true if this view or any ancestor is marked as domain inert.
409
+ *
410
+ * @returns {boolean}
411
+ */
412
+ isDomainInert() {
413
+ if (this.spec.domainInert) {
414
+ return true;
415
+ }
416
+
417
+ const parent = this.dataParent;
418
+ if (!parent) {
419
+ return false;
420
+ }
421
+
422
+ return parent.isDomainInert();
423
+ }
424
+
351
425
  /**
352
426
  * @returns {"none" | "pending" | "ready"}
353
427
  */
@@ -568,6 +642,8 @@ export default class View {
568
642
  this.context.dataFlow.removeDataSource(handle.dataSource);
569
643
  }
570
644
 
645
+ this.context.dataFlow.loadingStatusRegistry.delete(this);
646
+
571
647
  this.flowHandle = undefined;
572
648
  }
573
649
 
@@ -609,7 +685,13 @@ export default class View {
609
685
  * pass. The order is depth first, pre order.
610
686
  */
611
687
  onBeforeRender() {
612
- //
688
+ if (!this.#hasRendered) {
689
+ this.#hasRendered = true;
690
+ }
691
+ }
692
+
693
+ hasRendered() {
694
+ return this.#hasRendered;
613
695
  }
614
696
 
615
697
  /**
@@ -832,7 +914,9 @@ export default class View {
832
914
  }
833
915
 
834
916
  invalidateSizeCache() {
835
- this._invalidateCacheByPrefix("size/", "ancestors");
917
+ // Clear both "size" and "size/*" cache keys.
918
+ invalidatePrefix(this, "size");
919
+ this._invalidateCacheByPrefix("size", "ancestors");
836
920
  }
837
921
 
838
922
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"viewFactory.d.ts","sourceRoot":"","sources":["../../../src/view/viewFactory.js"],"names":[],"mappings":"AA4RA;;;;GAIG;AACH,sEAFa,IAAI,sCAAY,CAI5B;AAED;;;;GAIG;AACH,uEAFa,IAAI,uCAAa,CAI7B;AAED;;;;GAIG;AACH,uEAFa,IAAI,uCAAa,CAS7B;AAED;;;;GAIG;AACH,kFAFa,IAAI,IAAI,OAAO,iBAAiB,EAAE,oBAAoB,CAQlE;AAED;;;;GAIG;AACH,mCAHW,MAAM,GACJ,IAAI,IAAI,OAAO,iBAAiB,EAAE,UAAU,CAIxD;AAED;;;;GAIG;AACH,yEAFa,IAAI,yCAAe,CAI/B;AAED;;;;GAIG;AACH,yEAFa,IAAI,IAAI,WAAW,CAI/B;AAED;;;;GAIG;AACH,wEAFa,IAAI,wCAAc,CAI9B;AAED;;;;GAIG;AACH,wEAFa,IAAI,8CAAc,CAS9B;AA5WD,6BAA8B,UAAU,CAAC;AAEzC;;;;GAIG;AAEH;;GAEG;AACH;IAiBI;;OAEG;IACH,sBAFW,kBAAkB,EAoC5B;IAjCG,2CAA2C;IAC3C,SADW,QAAQ,CAAC,kBAAkB,CAAC,CAKtC;IA8BL;;;OAGG;IACH,qEAlDiC,OAAO,yHAC2B,OAAO,oBAAoB,EAAE,OAAO,eAAe,OAAO,WAAW,EAAE,OAAO,gBAAgB,MAAM,KAAK,IAAI,QAmD/K;IAED;;;;;;OAMG;IACH,wHAJW,OAAO,oBAAoB,EAAE,OAAO,eACpC,OAAO,WAAW,EAAE,OAAO,gBAC3B,MAAM,QAmBhB;IAED;;;;OAIG;IACH,sDAFa,IAAI,sCAAY,CAU5B;IAED;;;;;;;;;;OAUG;IACH,yBAPW,qCAAW,OAAO,iBAAiB,EAAE,UAAU,qEAE/C,OAAO,oBAAoB,EAAE,OAAO,eACpC,OAAO,WAAW,EAAE,OAAO,gBAC3B,MAAM,cACN,CAAC,IAAI,oCAAU,KAAK,IAAI,iBAiFlC;;CACJ;;;;;kBA3Ma,OAAO;eACP,OAAO;;iBAjBJ,WAAW"}
1
+ {"version":3,"file":"viewFactory.d.ts","sourceRoot":"","sources":["../../../src/view/viewFactory.js"],"names":[],"mappings":"AA+SA;;;;GAIG;AACH,sEAFa,IAAI,sCAAY,CAI5B;AAED;;;;GAIG;AACH,uEAFa,IAAI,uCAAa,CAI7B;AAED;;;;GAIG;AACH,uEAFa,IAAI,uCAAa,CAS7B;AAED;;;;GAIG;AACH,kFAFa,IAAI,IAAI,OAAO,iBAAiB,EAAE,oBAAoB,CAQlE;AAED;;;;GAIG;AACH,mCAHW,MAAM,GACJ,IAAI,IAAI,OAAO,iBAAiB,EAAE,UAAU,CAIxD;AAED;;;;GAIG;AACH,yEAFa,IAAI,yCAAe,CAI/B;AAED;;;;GAIG;AACH,yEAFa,IAAI,IAAI,WAAW,CAI/B;AAED;;;;GAIG;AACH,wEAFa,IAAI,wCAAc,CAI9B;AAED;;;;GAIG;AACH,wEAFa,IAAI,8CAAc,CAS9B;AA3XD,6BAA8B,UAAU,CAAC;AAEzC;;;;GAIG;AAEH;;GAEG;AACH;IAiBI;;OAEG;IACH,sBAFW,kBAAkB,EAoC5B;IAjCG,2CAA2C;IAC3C,SADW,QAAQ,CAAC,kBAAkB,CAAC,CAKtC;IA8BL;;;OAGG;IACH,qEAlDiC,OAAO,yHAC2B,OAAO,oBAAoB,EAAE,OAAO,eAAe,OAAO,WAAW,EAAE,OAAO,gBAAgB,MAAM,KAAK,IAAI,QAmD/K;IAED;;;;;;OAMG;IACH,wHAJW,OAAO,oBAAoB,EAAE,OAAO,eACpC,OAAO,WAAW,EAAE,OAAO,gBAC3B,MAAM,QAmBhB;IAED;;;;OAIG;IACH,sDAFa,IAAI,sCAAY,CAU5B;IAED;;;;;;;;;;OAUG;IACH,yBAPW,qCAAW,OAAO,iBAAiB,EAAE,UAAU,qEAE/C,OAAO,oBAAoB,EAAE,OAAO,eACpC,OAAO,WAAW,EAAE,OAAO,gBAC3B,MAAM,cACN,CAAC,IAAI,oCAAU,KAAK,IAAI,iBAgGlC;;CACJ;;;;;kBA1Na,OAAO;eACP,OAAO;;iBArBJ,WAAW"}
@@ -10,6 +10,10 @@ import ContainerView from "./containerView.js";
10
10
  import ViewError from "./viewError.js";
11
11
  import { isSelectionParameter } from "./paramMediator.js";
12
12
  import { asSelectionConfig } from "../selection/selection.js";
13
+ import {
14
+ markViewAsNonAddressable,
15
+ registerImportInstance,
16
+ } from "./viewSelectors.js";
13
17
 
14
18
  export const VIEW_ROOT_NAME = "viewRoot";
15
19
 
@@ -60,7 +64,7 @@ export class ViewFactory {
60
64
  context,
61
65
  layoutParent,
62
66
  dataParent,
63
- spec.name ?? defaultName
67
+ defaultName
64
68
  )
65
69
  );
66
70
 
@@ -148,6 +152,9 @@ export class ViewFactory {
148
152
  ) {
149
153
  /** @type {ViewSpec} */
150
154
  let viewSpec;
155
+ const importScopeName = isImportSpec(spec)
156
+ ? (spec.name ?? null)
157
+ : undefined;
151
158
 
152
159
  if (isImportSpec(spec)) {
153
160
  /** @type {ViewSpec} */
@@ -190,6 +197,7 @@ export class ViewFactory {
190
197
  );
191
198
 
192
199
  // Wrap a unit spec at root into a grid view to get axes, etc.
200
+ let isImplicitRoot = false;
193
201
  if (
194
202
  !dataParent &&
195
203
  this.options.wrapRoot &&
@@ -202,6 +210,7 @@ export class ViewFactory {
202
210
  name: "implicitRoot",
203
211
  vconcat: [viewSpec],
204
212
  };
213
+ isImplicitRoot = true;
205
214
  }
206
215
 
207
216
  const view = this.createView(
@@ -212,10 +221,20 @@ export class ViewFactory {
212
221
  defaultName
213
222
  );
214
223
 
224
+ if (importScopeName !== undefined) {
225
+ registerImportInstance(view, importScopeName);
226
+ }
227
+
228
+ if (isImplicitRoot) {
229
+ markViewAsNonAddressable(view);
230
+ }
231
+
215
232
  if (view instanceof ContainerView) {
216
233
  await view.initializeChildren();
217
234
  }
218
235
 
236
+ view.registerStepSizeInvalidation();
237
+
219
238
  return view;
220
239
  }
221
240
  }