@genome-spy/core 0.66.1 → 0.67.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 (44) hide show
  1. package/dist/bundle/index.es.js +6144 -5918
  2. package/dist/bundle/index.js +89 -89
  3. package/dist/src/data/flowHandle.d.ts +2 -0
  4. package/dist/src/data/flowHandle.d.ts.map +1 -1
  5. package/dist/src/data/flowHandle.js +1 -0
  6. package/dist/src/data/flowInit.d.ts +12 -4
  7. package/dist/src/data/flowInit.d.ts.map +1 -1
  8. package/dist/src/data/flowInit.js +114 -15
  9. package/dist/src/genomeSpy/viewDataInit.d.ts +10 -0
  10. package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -1
  11. package/dist/src/genomeSpy/viewDataInit.js +121 -2
  12. package/dist/src/genomeSpy/viewDataInit.test.d.ts +2 -0
  13. package/dist/src/genomeSpy/viewDataInit.test.d.ts.map +1 -0
  14. package/dist/src/genomeSpy.d.ts +1 -0
  15. package/dist/src/genomeSpy.d.ts.map +1 -1
  16. package/dist/src/genomeSpy.js +23 -1
  17. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  18. package/dist/src/gl/dataToVertices.js +16 -4
  19. package/dist/src/scales/scaleDomainAggregator.d.ts +2 -2
  20. package/dist/src/scales/scaleDomainAggregator.d.ts.map +1 -1
  21. package/dist/src/scales/scaleDomainAggregator.js +15 -10
  22. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
  23. package/dist/src/scales/scaleInstanceManager.js +8 -4
  24. package/dist/src/scales/scaleResolution.d.ts +3 -2
  25. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  26. package/dist/src/scales/scaleResolution.js +90 -16
  27. package/dist/src/utils/domainArray.d.ts.map +1 -1
  28. package/dist/src/utils/domainArray.js +3 -0
  29. package/dist/src/utils/indexer.d.ts +3 -0
  30. package/dist/src/utils/indexer.d.ts.map +1 -1
  31. package/dist/src/utils/indexer.js +3 -0
  32. package/dist/src/view/containerMutationHelper.d.ts.map +1 -1
  33. package/dist/src/view/containerMutationHelper.js +5 -1
  34. package/dist/src/view/flowBuilder.d.ts +5 -3
  35. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  36. package/dist/src/view/flowBuilder.js +69 -6
  37. package/dist/src/view/testUtils.d.ts.map +1 -1
  38. package/dist/src/view/testUtils.js +5 -0
  39. package/dist/src/view/unitView.d.ts.map +1 -1
  40. package/dist/src/view/unitView.js +17 -2
  41. package/dist/src/view/view.d.ts +12 -0
  42. package/dist/src/view/view.d.ts.map +1 -1
  43. package/dist/src/view/view.js +26 -0
  44. package/package.json +2 -2
@@ -12,8 +12,8 @@ import createDomain from "../utils/domainArray.js";
12
12
  */
13
13
 
14
14
  export default class ScaleDomainAggregator {
15
- /** @type {Set<ScaleResolutionMember>} */
16
- #members;
15
+ /** @type {() => Set<ScaleResolutionMember>} */
16
+ #getMembers;
17
17
 
18
18
  /** @type {() => import("../spec/channel.js").Type} */
19
19
  #getType;
@@ -35,7 +35,7 @@ export default class ScaleDomainAggregator {
35
35
  * @param {(interval: ScalarDomain | ComplexDomain) => number[]} options.fromComplexInterval
36
36
  */
37
37
  constructor({ getMembers, getType, getLocusExtent, fromComplexInterval }) {
38
- this.#members = getMembers();
38
+ this.#getMembers = getMembers;
39
39
  this.#getType = getType;
40
40
  this.#getLocusExtent = getLocusExtent;
41
41
  this.#fromComplexInterval = fromComplexInterval;
@@ -77,7 +77,7 @@ export default class ScaleDomainAggregator {
77
77
  */
78
78
  getConfiguredDomain() {
79
79
  return resolveConfiguredDomain(
80
- this.#members,
80
+ this.#getMembers(),
81
81
  this.#fromComplexInterval
82
82
  );
83
83
  }
@@ -85,10 +85,10 @@ export default class ScaleDomainAggregator {
85
85
  /**
86
86
  * Extracts and unions the data domains of all participating views.
87
87
  *
88
- * @return {DomainArray}
88
+ * @return {DomainArray | undefined}
89
89
  */
90
90
  getDataDomain() {
91
- return resolveDataDomain(this.#members, this.#getType);
91
+ return resolveDataDomain(this.#getMembers(), this.#getType);
92
92
  }
93
93
 
94
94
  /**
@@ -139,13 +139,18 @@ function resolveConfiguredDomain(members, fromComplexInterval) {
139
139
  /**
140
140
  * @param {Set<ScaleResolutionMember>} members
141
141
  * @param {() => import("../spec/channel.js").Type} getType
142
- * @returns {DomainArray}
142
+ * @returns {DomainArray | undefined}
143
143
  */
144
144
  function resolveDataDomain(members, getType) {
145
- return Array.from(members)
145
+ const domains = Array.from(members)
146
146
  .map((member) => member.dataDomainSource?.(member.channel, getType()))
147
- .filter((domain) => !!domain)
148
- .reduce((acc, curr) => acc.extendAll(curr));
147
+ .filter((domain) => !!domain);
148
+
149
+ if (domains.length === 0) {
150
+ return undefined;
151
+ }
152
+
153
+ return domains.reduce((acc, curr) => acc.extendAll(curr));
149
154
  }
150
155
 
151
156
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"scaleInstanceManager.d.ts","sourceRoot":"","sources":["../../../src/scales/scaleInstanceManager.js"],"names":[],"mappings":"AAMA;IA0BI;;;;;;OAMG;IACH,kFALG;QAAkE,gBAAgB,EAA1E,MAAM,OAAO,0BAA0B,EAAE,OAAO;QAC5B,aAAa,EAAjC,MAAM,IAAI;QACW,cAAc,GAAnC,MAAM,IAAI;QAC6D,cAAc,GAArF,MAAM,OAAO,0BAA0B,EAAE,OAAO,GAAG,SAAS;KAA0B,EAYhG;IAED;eA1CkC,OAAO,kBAAkB,EAAE,KAAK;MA4CjE;IAED;;OAEG;IACH,kBAFa,OAAO,qBAAqB,EAAE,OAAO,CASjD;IAED;;;OAGG;IACH,mBAHW,OAAO,kBAAkB,EAAE,KAAK;eA3DT,OAAO,kBAAkB,EAAE,KAAK;MAgFjE;IAoBD;;OAEG;IACH,wBAFW,OAAO,kBAAkB,EAAE,KAAK,QAc1C;IAED;;;OAGG;IACH,4CAHW,MAAM,IAAI,GACR,IAAI,CAShB;;CA6EJ"}
1
+ {"version":3,"file":"scaleInstanceManager.d.ts","sourceRoot":"","sources":["../../../src/scales/scaleInstanceManager.js"],"names":[],"mappings":"AAMA;IA0BI;;;;;;OAMG;IACH,kFALG;QAAkE,gBAAgB,EAA1E,MAAM,OAAO,0BAA0B,EAAE,OAAO;QAC5B,aAAa,EAAjC,MAAM,IAAI;QACW,cAAc,GAAnC,MAAM,IAAI;QAC6D,cAAc,GAArF,MAAM,OAAO,0BAA0B,EAAE,OAAO,GAAG,SAAS;KAA0B,EAYhG;IAED;eA1CkC,OAAO,kBAAkB,EAAE,KAAK;MA4CjE;IAED;;OAEG;IACH,kBAFa,OAAO,qBAAqB,EAAE,OAAO,CASjD;IAED;;;OAGG;IACH,mBAHW,OAAO,kBAAkB,EAAE,KAAK;eA3DT,OAAO,kBAAkB,EAAE,KAAK;MAgFjE;IAoBD;;OAEG;IACH,wBAFW,OAAO,kBAAkB,EAAE,KAAK,QAc1C;IAED;;;OAGG;IACH,4CAHW,MAAM,IAAI,GACR,IAAI,CAShB;;CAiFJ"}
@@ -142,12 +142,16 @@ export default class ScaleInstanceManager {
142
142
  * @returns {import("../spec/scale.js").Scale}
143
143
  */
144
144
  #stripNonScaleProps(props) {
145
- if (!("assembly" in props)) {
146
- return props;
147
- }
148
145
  // Avoid sending non-scale properties into vega-scale.
149
- const { assembly: _assembly, ...rest } = props;
146
+ // Strip internal runtime-only props before passing into vega-scale.
147
+ const propsAny = /** @type {any} */ (props);
148
+ const {
149
+ assembly: _assembly,
150
+ domainIndexer: _domainIndexer,
151
+ ...rest
152
+ } = propsAny;
150
153
  void _assembly;
154
+ void _domainIndexer;
151
155
  return rest;
152
156
  }
153
157
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Reconfigures scale domains, starting from the given view.
2
+ * Reconfigures scale domains for resolutions used by the given view(s).
3
3
  *
4
4
  * Use this for data-driven updates where only domains need refreshing.
5
5
  *
@@ -10,8 +10,9 @@
10
10
  * Causes performance issues with domains that are extracted from data.
11
11
  *
12
12
  * @param {import("../view/view.js").default | import("../view/view.js").default[]} fromViews
13
+ * @param {(view: import("../view/view.js").default) => boolean} [viewFilter]
13
14
  */
14
- export function reconfigureScaleDomains(fromViews: import("../view/view.js").default | import("../view/view.js").default[]): void;
15
+ export function reconfigureScaleDomains(fromViews: import("../view/view.js").default | import("../view/view.js").default[], viewFilter?: (view: import("../view/view.js").default) => boolean): void;
15
16
  /**
16
17
  * @template {ChannelWithScale}[T=ChannelWithScale]
17
18
  *
@@ -1 +1 @@
1
- {"version":3,"file":"scaleResolution.d.ts","sourceRoot":"","sources":["../../../src/scales/scaleResolution.js"],"names":[],"mappings":"AA0mBA;;;;;;;;;;;;GAYG;AACH,mDAFW,OAAO,iBAAiB,EAAE,OAAO,GAAG,OAAO,iBAAiB,EAAE,OAAO,EAAE,QA4BjF;AA5mBD;;;;;;;;GAQG;AACH;;;;;;;;GAQG;AACH;IAsCI;;OAEG;IACH,2DAgCC;IA/BG,8CAAsB;IACtB,0FAA0F;IAC1F,MADW,OAAO,oBAAoB,EAAE,IAAI,CAC5B;IAEhB,iEAAiE;IACjE,MADW,MAAM,CACI;IA2CzB,2BASC;IAqBD;;;;;;;OAOG;IACH,4KAEC;IAED;;;OAGG;IACH,+KAEC;IAyED;;;OAGG;IACH,uBAHW,qBAAqB,GACnB,MAAM,OAAO,CAQzB;IA8ED;;;;;OAKG;IACH,oBAGC;IAED;;;;OAIG;IACH,0BAKC;IAkDD;;OAEG;IACH;eAtWkC,OAAO,kBAAkB,EAAE,KAAK;MA6WjE;IAED;;;;;;OAMG;IACH;eAtXkC,OAAO,kBAAkB,EAAE,KAAK;MAwXjE;IAED;;;;OAIG;IACH;eA/XkC,OAAO,kBAAkB,EAAE,KAAK;MAwYjE;IAED,mBAEC;IAED;;;;OAIG;IACH,+DAEC;IAED;;OAEG;IACH,oBAFa,mFAA6B,CAMzC;IAED;;;;OAIG;IACH,oBAEC;IAED;;OAEG;IACH,sBAGC;IAED;;;;;;;OAOG;IACH,kBALW,MAAM,eACN,MAAM,OACN,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;OAMG;IACH,eAJW,mFAA6B,aAC7B,OAAO,GAAG,MAAM,iBAK1B;IAED;;;;OAIG;IACH,qBAEC;IAED;;;;;OAKG;IACH,uBAEC;IAED;;;;;;;OAOG;IACH,wBAoBC;IAED;;;;;OAKG;IACH,uBAFW,MAAM,yDAUhB;IAED;;OAEG;IACH,iBAFW,MAAM,yDAIhB;IAED;;;OAGG;IACH,qBAHW,MAAM,+CAAmB,GACvB,MAAM,CAIlB;IAED;;;OAGG;IACH,8BAHW,kFAA4B,GAC1B,MAAM,EAAE,CAOpB;;CACJ;kCAlkB+B,CAAC,SAApB,6CAAkB;;;;UAGrB,OAAO,qBAAqB,EAAE,OAAO;aACrC,CAAC;gBACD,OAAO,oBAAoB,EAAE,mBAAmB;sBAChD,CAAC,OAAO,+CAAkB,EAAE,IAAI,EAAE,OAAO,oBAAoB,EAAE,IAAI,kDAAgB;;sBArBtF,+BAA+B;sBAA/B,+BAA+B;wBAA/B,+BAA+B;wBAA/B,+BAA+B;6BAA/B,+BAA+B"}
1
+ {"version":3,"file":"scaleResolution.d.ts","sourceRoot":"","sources":["../../../src/scales/scaleResolution.js"],"names":[],"mappings":"AAmrBA;;;;;;;;;;;;;GAaG;AACH,mDAHW,OAAO,iBAAiB,EAAE,OAAO,GAAG,OAAO,iBAAiB,EAAE,OAAO,EAAE,eACvE,CAAC,IAAI,EAAE,OAAO,iBAAiB,EAAE,OAAO,KAAK,OAAO,QA4B9D;AAprBD;;;;;;;;GAQG;AACH;;;;;;;;GAQG;AACH;IA2CI;;OAEG;IACH,2DAgCC;IA/BG,8CAAsB;IACtB,0FAA0F;IAC1F,MADW,OAAO,oBAAoB,EAAE,IAAI,CAC5B;IAEhB,iEAAiE;IACjE,MADW,MAAM,CACI;IA+DzB,2BASC;IAqBD;;;;;;;OAOG;IACH,4KAEC;IAED;;;OAGG;IACH,+KAEC;IAyED;;;OAGG;IACH,uBAHW,qBAAqB,GACnB,MAAM,OAAO,CAQzB;IA4HD;;;;;OAKG;IACH,oBAGC;IAED;;;;OAIG;IACH,0BAKC;IAkDD;;OAEG;IACH;eA7akC,OAAO,kBAAkB,EAAE,KAAK;MAobjE;IAED;;;;;;OAMG;IACH;eA7bkC,OAAO,kBAAkB,EAAE,KAAK;MA+bjE;IAED;;;;OAIG;IACH;eAtckC,OAAO,kBAAkB,EAAE,KAAK;MA+cjE;IAED,mBAEC;IAED;;;;OAIG;IACH,+DAEC;IAED;;OAEG;IACH,oBAFa,mFAA6B,CAMzC;IAED;;;;OAIG;IACH,oBAEC;IAED;;OAEG;IACH,sBAGC;IAED;;;;;;;OAOG;IACH,kBALW,MAAM,eACN,MAAM,OACN,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;OAMG;IACH,eAJW,mFAA6B,aAC7B,OAAO,GAAG,MAAM,iBAK1B;IAED;;;;OAIG;IACH,qBAEC;IAED;;;;;OAKG;IACH,uBAEC;IAED;;;;;;;OAOG;IACH,wBAoBC;IAED;;;;;OAKG;IACH,uBAFW,MAAM,yDAUhB;IAED;;OAEG;IACH,iBAFW,MAAM,yDAIhB;IAED;;;OAGG;IACH,qBAHW,MAAM,+CAAmB,GACvB,MAAM,CAIlB;IAED;;;OAGG;IACH,8BAHW,kFAA4B,GAC1B,MAAM,EAAE,CAOpB;;CACJ;kCAzoB+B,CAAC,SAApB,6CAAkB;;;;UAGrB,OAAO,qBAAqB,EAAE,OAAO;aACrC,CAAC;gBACD,OAAO,oBAAoB,EAAE,mBAAmB;sBAChD,CAAC,OAAO,+CAAkB,EAAE,IAAI,EAAE,OAAO,oBAAoB,EAAE,IAAI,kDAAgB;;sBAvBtF,+BAA+B;sBAA/B,+BAA+B;wBAA/B,+BAA+B;wBAA/B,+BAA+B;6BAA/B,+BAA+B"}
@@ -26,6 +26,8 @@ import {
26
26
  import { isSecondaryChannel } from "../encoder/encoder.js";
27
27
  import { NominalDomain } from "../utils/domainArray.js";
28
28
  import { asArray, shallowArrayEquals } from "../utils/arrayUtils.js";
29
+ import { VISIT_SKIP } from "../view/view.js";
30
+ import createIndexer from "../utils/indexer.js";
29
31
 
30
32
  // Register scaleLocus to Vega-Scale.
31
33
  // Loci are discrete but the scale's domain can be adjusted in a continuous manner.
@@ -91,6 +93,11 @@ export default class ScaleResolution {
91
93
  /** @type {ScaleInteractionController} */
92
94
  #interactionController;
93
95
 
96
+ /** @type {ReturnType<typeof createIndexer> | undefined} */
97
+ #categoricalIndexer;
98
+
99
+ #categoricalIndexerExplicit = false;
100
+
94
101
  /**
95
102
  * @param {Channel} channel
96
103
  */
@@ -103,7 +110,7 @@ export default class ScaleResolution {
103
110
  this.name = undefined;
104
111
 
105
112
  this.#domainAggregator = new ScaleDomainAggregator({
106
- getMembers: () => this.#members,
113
+ getMembers: () => this.#getActiveMembers(),
107
114
  getType: () => this.type,
108
115
  getLocusExtent: () => this.#getLocusExtent(),
109
116
  fromComplexInterval: this.fromComplexInterval.bind(this),
@@ -139,6 +146,26 @@ export default class ScaleResolution {
139
146
  return first.view;
140
147
  }
141
148
 
149
+ #getActiveMembers() {
150
+ /** @type {Set<ScaleResolutionMember>} */
151
+ const active = new Set();
152
+ for (const member of this.#members) {
153
+ const view = member.view;
154
+ if (!view.isConfiguredVisible()) {
155
+ continue;
156
+ }
157
+ if (
158
+ !view.isDataInitialized() &&
159
+ !member.channelDef?.scale?.domain
160
+ ) {
161
+ // Explicit domains should be honored even before data init.
162
+ continue;
163
+ }
164
+ active.add(member);
165
+ }
166
+ return active;
167
+ }
168
+
142
169
  get #viewContext() {
143
170
  return this.#firstMemberView.context;
144
171
  }
@@ -337,10 +364,42 @@ export default class ScaleResolution {
337
364
  extractDataDomain
338
365
  );
339
366
 
340
- if (domain && domain.length > 0) {
367
+ if (isDiscrete(props.type)) {
368
+ const isExplicit = this.#isExplicitDomain();
369
+ const indexer = this.#getCategoricalIndexer(isExplicit);
370
+ if (domain != null) {
371
+ if (
372
+ isExplicit &&
373
+ indexer.domain().length > 0 &&
374
+ !shallowArrayEquals(indexer.domain(), domain)
375
+ ) {
376
+ this.#categoricalIndexer = undefined;
377
+ return this.#getScaleProps(extractDataDomain);
378
+ }
379
+ indexer.addAll(domain);
380
+ const active = new Set(domain);
381
+ const indexedDomain = indexer
382
+ .domain()
383
+ .filter((value) => active.has(value));
384
+ props.domain =
385
+ indexedDomain.length > 0
386
+ ? /** @type {import("../spec/scale.js").ScalarDomain} */ (
387
+ indexedDomain
388
+ )
389
+ : new NominalDomain();
390
+ } else {
391
+ const indexedDomain = indexer.domain();
392
+ props.domain =
393
+ indexedDomain.length > 0
394
+ ? /** @type {import("../spec/scale.js").ScalarDomain} */ (
395
+ indexedDomain
396
+ )
397
+ : new NominalDomain();
398
+ }
399
+ // Scale props are spec-shaped; keep the indexer off the public type.
400
+ /** @type {any} */ (props).domainIndexer = indexer;
401
+ } else if (domain && domain.length > 0) {
341
402
  props.domain = domain;
342
- } else if (isDiscrete(props.type)) {
343
- props.domain = new NominalDomain();
344
403
  }
345
404
 
346
405
  if (!props.domain && props.domainMid !== undefined) {
@@ -352,6 +411,20 @@ export default class ScaleResolution {
352
411
  return props;
353
412
  }
354
413
 
414
+ /**
415
+ * @param {boolean} isExplicit
416
+ */
417
+ #getCategoricalIndexer(isExplicit) {
418
+ if (
419
+ !this.#categoricalIndexer ||
420
+ this.#categoricalIndexerExplicit !== isExplicit
421
+ ) {
422
+ this.#categoricalIndexer = createIndexer();
423
+ this.#categoricalIndexerExplicit = isExplicit;
424
+ }
425
+ return this.#categoricalIndexer;
426
+ }
427
+
355
428
  /**
356
429
  * Reconfigures the scale: updates domain and other settings.
357
430
  *
@@ -617,7 +690,7 @@ export default class ScaleResolution {
617
690
  }
618
691
 
619
692
  /**
620
- * Reconfigures scale domains, starting from the given view.
693
+ * Reconfigures scale domains for resolutions used by the given view(s).
621
694
  *
622
695
  * Use this for data-driven updates where only domains need refreshing.
623
696
  *
@@ -628,8 +701,9 @@ export default class ScaleResolution {
628
701
  * Causes performance issues with domains that are extracted from data.
629
702
  *
630
703
  * @param {import("../view/view.js").default | import("../view/view.js").default[]} fromViews
704
+ * @param {(view: import("../view/view.js").default) => boolean} [viewFilter]
631
705
  */
632
- export function reconfigureScaleDomains(fromViews) {
706
+ export function reconfigureScaleDomains(fromViews, viewFilter) {
633
707
  /** @type {Set<ScaleResolution>} */
634
708
  const uniqueResolutions = new Set();
635
709
 
@@ -640,19 +714,19 @@ export function reconfigureScaleDomains(fromViews) {
640
714
  }
641
715
  }
642
716
 
643
- for (const fromView of asArray(fromViews)) {
644
- // Descendants
645
- fromView.visit(collectResolutions);
646
-
647
- // Ancestors
648
- for (const view of fromView.getDataAncestors()) {
649
- // Skip axis views etc. They should not mess with the domains.
650
- if (!view.options.contributesToScaleDomain) {
651
- break;
652
- }
717
+ /** @type {import("../view/view.js").VisitorCallback} */
718
+ function collectVisibleResolutions(view) {
719
+ if (viewFilter && !viewFilter(view)) {
720
+ return VISIT_SKIP;
721
+ }
722
+ if (view.options.contributesToScaleDomain) {
653
723
  collectResolutions(view);
654
724
  }
655
725
  }
656
726
 
727
+ for (const fromView of asArray(fromViews)) {
728
+ fromView.visit(collectVisibleResolutions);
729
+ }
730
+
657
731
  uniqueResolutions.forEach((resolution) => resolution.reconfigureDomain());
658
732
  }
@@ -1 +1 @@
1
- {"version":3,"file":"domainArray.d.ts","sourceRoot":"","sources":["../../../src/utils/domainArray.js"],"names":[],"mappings":"AA8KA;;;;GAIG;AACH,2CAHW,MAAM,kBACN,MAAM,EAAE,eAiBlB;AAED;;;;GAIG;AACH,4CAFW,WAAW,GAAG,GAAG,EAAE,SAI7B;AA3MD;;GAEG;AAEH;IACI,cAIC;IAFG,qBAAqB;IACrB,MADW,MAAM,CACI;IAGzB;;;;OAIG;IACH,cAHW,MAAM,GACJ,WAAW,CAIvB;IAED;;;;OAIG;IACH,kBAHW,QAAQ,CAAC,MAAM,CAAC,GACd,WAAW,CAcvB;IAED;;;;;OAKG;IACH,sBAFa,CAAC,UAHH,QAAQ,CAAC,CAAC,CAAC,aACX,CAAS,IAAC,EAAD,CAAC,KAAE,MAAM,GAChB,WAAW,CASvB;CACJ;AAED;IAoBgB,UAAe;IAEf,UAAe;CAS9B;AAED;;GAEG;AACH;IAKQ,0BAA0B;IAC1B,cADW,GAAG,CAAC,MAAM,CAAC,CACO;CAoBpC;AAED;CAKC;AAED;IACI;;;OAGG;IACH,2BAFW,MAAM,EAAE,EAiBlB;CAgBJ;qBAhKY,OAAO,GAAG,MAAM,GAAG,MAAM"}
1
+ {"version":3,"file":"domainArray.d.ts","sourceRoot":"","sources":["../../../src/utils/domainArray.js"],"names":[],"mappings":"AAiLA;;;;GAIG;AACH,2CAHW,MAAM,kBACN,MAAM,EAAE,eAiBlB;AAED;;;;GAIG;AACH,4CAFW,WAAW,GAAG,GAAG,EAAE,SAI7B;AA9MD;;GAEG;AAKH;IACI,cAIC;IAFG,qBAAqB;IACrB,MADW,MAAM,CACI;IAGzB;;;;OAIG;IACH,cAHW,MAAM,GACJ,WAAW,CAIvB;IAED;;;;OAIG;IACH,kBAHW,QAAQ,CAAC,MAAM,CAAC,GACd,WAAW,CAcvB;IAED;;;;;OAKG;IACH,sBAFa,CAAC,UAHH,QAAQ,CAAC,CAAC,CAAC,aACX,CAAS,IAAC,EAAD,CAAC,KAAE,MAAM,GAChB,WAAW,CASvB;CACJ;AAED;IAoBgB,UAAe;IAEf,UAAe;CAS9B;AAED;;GAEG;AACH;IAKQ,0BAA0B;IAC1B,cADW,GAAG,CAAC,MAAM,CAAC,CACO;CAoBpC;AAED;CAKC;AAED;IACI;;;OAGG;IACH,2BAFW,MAAM,EAAE,EAiBlB;CAgBJ;qBAnKY,OAAO,GAAG,MAAM,GAAG,MAAM"}
@@ -2,6 +2,9 @@
2
2
  * @typedef {boolean | number | string} scalar
3
3
  */
4
4
 
5
+ // DomainArray tracks categorical order for scale domain extraction.
6
+ // For rendering, ScaleResolution maintains a stable Indexer to prevent
7
+ // categorical indices from changing across updates.
5
8
  export class DomainArray /** @type {Array<scalar>} */ extends Array {
6
9
  constructor() {
7
10
  super();
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * Assigns unique values an index number in the order they are encountered.
3
3
  *
4
+ * Used to keep categorical GPU encodings stable: once a value gets an index,
5
+ * it must never change for the lifetime of the owning scale.
6
+ *
4
7
  * TODO: What about undefined?
5
8
  *
6
9
  * @template T
@@ -1 +1 @@
1
- {"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../../../src/utils/indexer.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,sCAFa,CAAC;YAYE,CAAC;qBAeD,QAAQ,CAAC,CAAC,CAAC;kBAOX,MAAM;;EAYrB"}
1
+ {"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../../../src/utils/indexer.js"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,sCAFa,CAAC;YAYE,CAAC;qBAeD,QAAQ,CAAC,CAAC,CAAC;kBAOX,MAAM;;EAYrB"}
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * Assigns unique values an index number in the order they are encountered.
3
3
  *
4
+ * Used to keep categorical GPU encodings stable: once a value gets an index,
5
+ * it must never change for the lifetime of the owning scale.
6
+ *
4
7
  * TODO: What about undefined?
5
8
  *
6
9
  * @template T
@@ -1 +1 @@
1
- {"version":3,"file":"containerMutationHelper.d.ts","sourceRoot":"","sources":["../../../src/view/containerMutationHelper.js"],"names":[],"mappings":"AAOA;;;GAGG;AACH;IACI;;;;;;;;;;OAUG;IAEH;;;;;;;;;;OAUG;IAEH;;;OAGG;IACH,uBAHW,OAAO,oBAAoB,EAAE,OAAO;uBAX3B;mBARR,CAAC,yEAAqB,CAAC,EAAE;sBACtB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,yEAAqB,KAAK,IAAI;sBACpD,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;SAMF;oBACnB,CAAC,IAAI,6BAAM,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG;oBAClC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;sBACrB,CAAC,IAAI,6BAAM,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC;sBAClE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;sBAChC,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,yEAAqB,KAAK,MAAM;wBACpD,OAAO;OAW3B;IAFG,gDAA0B;IAC1B;uBAhBgB;mBARR,CAAC,yEAAqB,CAAC,EAAE;sBACtB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,yEAAqB,KAAK,IAAI;sBACpD,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;SAMF;oBACnB,CAAC,IAAI,6BAAM,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG;oBAClC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;sBACrB,CAAC,IAAI,6BAAM,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC;sBAClE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;sBAChC,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,yEAAqB,KAAK,MAAM;wBACpD,OAAO;MAUF;IAG1B;;;;;;OAMG;IACH,wBAJW,OAAO,iBAAiB,EAAE,QAAQ,GAAG,OAAO,iBAAiB,EAAE,UAAU,UACzE,MAAM,GACJ,OAAO,6BAAM,CA0CzB;IAED;;;;OAIG;IACH,qBAFW,MAAM,iBAehB;CACJ"}
1
+ {"version":3,"file":"containerMutationHelper.d.ts","sourceRoot":"","sources":["../../../src/view/containerMutationHelper.js"],"names":[],"mappings":"AAOA;;;GAGG;AACH;IACI;;;;;;;;;;OAUG;IAEH;;;;;;;;;;OAUG;IAEH;;;OAGG;IACH,uBAHW,OAAO,oBAAoB,EAAE,OAAO;uBAX3B;mBARR,CAAC,yEAAqB,CAAC,EAAE;sBACtB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,yEAAqB,KAAK,IAAI;sBACpD,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;SAMF;oBACnB,CAAC,IAAI,6BAAM,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG;oBAClC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;sBACrB,CAAC,IAAI,6BAAM,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC;sBAClE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;sBAChC,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,yEAAqB,KAAK,MAAM;wBACpD,OAAO;OAW3B;IAFG,gDAA0B;IAC1B;uBAhBgB;mBARR,CAAC,yEAAqB,CAAC,EAAE;sBACtB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,yEAAqB,KAAK,IAAI;sBACpD,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;SAMF;oBACnB,CAAC,IAAI,6BAAM,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG;oBAClC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;sBACrB,CAAC,IAAI,6BAAM,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC;sBAClE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;sBAChC,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,yEAAqB,KAAK,MAAM;wBACpD,OAAO;MAUF;IAG1B;;;;;;OAMG;IACH,wBAJW,OAAO,iBAAiB,EAAE,QAAQ,GAAG,OAAO,iBAAiB,EAAE,UAAU,UACzE,MAAM,GACJ,OAAO,6BAAM,CA8CzB;IAED;;;;OAIG;IACH,qBAFW,MAAM,iBAehB;CACJ"}
@@ -77,9 +77,13 @@ export default class ContainerMutationHelper {
77
77
 
78
78
  configureViewOpacity(childView);
79
79
 
80
+ const visibilityPredicate = (
81
+ /** @type {import("./view.js").default} */ view
82
+ ) => view.isConfiguredVisible();
80
83
  const { dataSources, graphicsPromises } = initializeViewSubtree(
81
84
  childView,
82
- this.container.context.dataFlow
85
+ this.container.context.dataFlow,
86
+ visibilityPredicate
83
87
  );
84
88
  await loadViewSubtreeData(childView, dataSources);
85
89
  await finalizeSubtreeGraphics(graphicsPromises);
@@ -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;;;IAuG5B;;;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;qBA3eoB,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,12 +315,18 @@ 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
331
  if (isPositionalChannel(channel) && isChromPosDef(channelDef)) {
269
332
  channelsAndChromPosDefs.push({ channel, chromPosDef: channelDef });
@@ -302,7 +365,7 @@ export function linearizeLocusAccess(view) {
302
365
  /** @type {any} */
303
366
  const newFieldDef = {
304
367
  ...(view.spec.encoding?.[channel] ??
305
- view.getEncoding()[channel] ??
368
+ encoding[channel] ??
306
369
  {}),
307
370
  field: linearizedField,
308
371
  };
@@ -1 +1 @@
1
- {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../../src/view/testUtils.js"],"names":[],"mappings":"AAoBA;;;GAGG;AACH,2DAHW,OAAO,kBAAkB,EAAE,kBAAkB,6CA0DvD;AAGS,uBAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,uBAAuB,OAAO,kBAAkB,EAAE,kBAAkB,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAgBhL,oCAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,YAAY,WAAW,YAAY;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAC,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;;;;;uBA9FpL,OAAO,iBAAiB,EAAE,QAAQ;;;;;0BAClC,OAAO,yBAAyB,EAAE,OAAO"}
1
+ {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../../src/view/testUtils.js"],"names":[],"mappings":"AAoBA;;;GAGG;AACH,2DAHW,OAAO,kBAAkB,EAAE,kBAAkB,6CA+DvD;AAGS,uBAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,uBAAuB,OAAO,kBAAkB,EAAE,kBAAkB,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAgBhL,oCAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,YAAY,WAAW,YAAY;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAC,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;;;;;uBAnGpL,OAAO,iBAAiB,EAAE,QAAQ;;;;;0BAClC,OAAO,yBAAyB,EAAE,OAAO"}
@@ -66,6 +66,11 @@ export function createTestViewContext(viewFactoryOptions = {}) {
66
66
  /** @type {(callback: () => void) => void} */ (
67
67
  (callback) => callback()
68
68
  ),
69
+ transition: (/** @type {any} */ options) => {
70
+ const to = typeof options.to === "number" ? options.to : 1;
71
+ options.onUpdate(to);
72
+ return Promise.resolve();
73
+ },
69
74
  })
70
75
  ),
71
76
 
@@ -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,iEA0IC;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;iBAxfgB,WAAW"}
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"}
@@ -368,12 +368,27 @@ export default class UnitView extends View {
368
368
  const resolution = new ScaleResolution(targetChannel);
369
369
  view.resolutions[type][targetChannel] = resolution;
370
370
 
371
- resolution.addEventListener("range", (event) => {
372
- // Create if WebGLHelper is available, i.e., if not running in headless mode
371
+ const updateRangeTexture = (
372
+ /** @type {import("../types/scaleResolutionApi.js").ScaleResolutionEvent} */ event
373
+ ) => {
374
+ // Create if WebGLHelper is available, i.e., if not running in headless mode.
375
+ // Domain changes can alter discrete texture sizes as well.
373
376
  this.context.glHelper?.createRangeTexture(
374
377
  event.scaleResolution,
375
378
  true
376
379
  );
380
+ };
381
+ resolution.addEventListener("range", updateRangeTexture);
382
+ resolution.addEventListener("domain", updateRangeTexture);
383
+ this.registerDisposer(() => {
384
+ resolution.removeEventListener(
385
+ "range",
386
+ updateRangeTexture
387
+ );
388
+ resolution.removeEventListener(
389
+ "domain",
390
+ updateRangeTexture
391
+ );
377
392
  });
378
393
  }
379
394
 
@@ -146,6 +146,18 @@ export default class View {
146
146
  * @returns {boolean}
147
147
  */
148
148
  isVisible(): boolean;
149
+ /**
150
+ * @returns {"none" | "pending" | "ready"}
151
+ */
152
+ getDataInitializationState(): "none" | "pending" | "ready";
153
+ /**
154
+ * Internal hook for lazy dataflow initialization.
155
+ * Use only from flow initialization helpers to avoid inconsistent state.
156
+ *
157
+ * @param {"none" | "pending" | "ready"} state
158
+ */
159
+ _setDataInitializationState(state: "none" | "pending" | "ready"): void;
160
+ isDataInitialized(): boolean;
149
161
  /**
150
162
  * Returns the effective opacity of this view, e.g., view's opacity multiplied
151
163
  * by opacities of its ancestors.
@@ -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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"}