@genome-spy/core 0.63.0 → 0.65.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 (138) hide show
  1. package/dist/bundle/{index-CCJIjehY.js → AbortablePromiseCache-CcuMrnn7.js} +22 -91
  2. package/dist/bundle/browser-txUcLy2H.js +123 -0
  3. package/dist/bundle/index-BQpbYrv4.js +1712 -0
  4. package/dist/bundle/index-BhtHKLUo.js +73 -0
  5. package/dist/bundle/index-C0llXMqm.js +280 -0
  6. package/dist/bundle/index-CCe8rnZz.js +716 -0
  7. package/dist/bundle/index-CD7FLu9x.js +269 -0
  8. package/dist/bundle/{index-C08YCM2T.js → index-D-w7Mmt9.js} +246 -126
  9. package/dist/bundle/index-D74H8TTz.js +508 -0
  10. package/dist/bundle/index-DhcU-Gk-.js +1487 -0
  11. package/dist/bundle/index.es.js +5394 -4989
  12. package/dist/bundle/index.js +420 -362
  13. package/dist/bundle/inflate-DRgHi_KK.js +1050 -0
  14. package/dist/schema.json +93 -13
  15. package/dist/src/data/collector.d.ts +7 -2
  16. package/dist/src/data/collector.d.ts.map +1 -1
  17. package/dist/src/data/collector.js +13 -2
  18. package/dist/src/data/dataFlow.d.ts +20 -42
  19. package/dist/src/data/dataFlow.d.ts.map +1 -1
  20. package/dist/src/data/dataFlow.js +57 -80
  21. package/dist/src/data/dataFlow.test.js +35 -2
  22. package/dist/src/data/flowHandle.d.ts +15 -0
  23. package/dist/src/data/flowHandle.d.ts.map +1 -0
  24. package/dist/src/data/flowHandle.js +13 -0
  25. package/dist/src/data/flowInit.d.ts +85 -0
  26. package/dist/src/data/flowInit.d.ts.map +1 -0
  27. package/dist/src/data/flowInit.js +238 -0
  28. package/dist/src/data/flowInit.test.d.ts +2 -0
  29. package/dist/src/data/flowInit.test.d.ts.map +1 -0
  30. package/dist/src/data/flowInit.test.js +413 -0
  31. package/dist/src/data/flowOptimizer.d.ts +6 -4
  32. package/dist/src/data/flowOptimizer.d.ts.map +1 -1
  33. package/dist/src/data/flowOptimizer.js +29 -14
  34. package/dist/src/data/flowOptimizer.test.js +20 -15
  35. package/dist/src/data/sources/lazy/bamSource.js +1 -1
  36. package/dist/src/data/sources/lazy/bigBedSource.js +1 -1
  37. package/dist/src/data/sources/lazy/bigWigSource.js +1 -1
  38. package/dist/src/data/sources/lazy/gff3Source.d.ts +2 -6
  39. package/dist/src/data/sources/lazy/gff3Source.d.ts.map +1 -1
  40. package/dist/src/data/sources/lazy/gff3Source.js +4 -8
  41. package/dist/src/data/sources/lazy/indexedFastaSource.d.ts.map +1 -1
  42. package/dist/src/data/sources/lazy/indexedFastaSource.js +17 -17
  43. package/dist/src/data/sources/lazy/tabixSource.js +1 -1
  44. package/dist/src/genomeSpy.d.ts +1 -1
  45. package/dist/src/genomeSpy.d.ts.map +1 -1
  46. package/dist/src/genomeSpy.js +18 -61
  47. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  48. package/dist/src/gl/webGLHelper.js +8 -0
  49. package/dist/src/marks/link.fragment.glsl.js +1 -1
  50. package/dist/src/marks/link.vertex.glsl.js +1 -1
  51. package/dist/src/marks/mark.d.ts +1 -0
  52. package/dist/src/marks/mark.d.ts.map +1 -1
  53. package/dist/src/marks/mark.js +22 -1
  54. package/dist/src/marks/point.fragment.glsl.js +1 -1
  55. package/dist/src/marks/point.vertex.glsl.js +1 -1
  56. package/dist/src/marks/rect.fragment.glsl.js +1 -1
  57. package/dist/src/marks/rect.vertex.glsl.js +1 -1
  58. package/dist/src/marks/rule.fragment.glsl.js +1 -1
  59. package/dist/src/marks/rule.vertex.glsl.js +1 -1
  60. package/dist/src/marks/text.fragment.glsl.js +1 -1
  61. package/dist/src/marks/text.vertex.glsl.js +1 -1
  62. package/dist/src/selection/selection.d.ts +5 -0
  63. package/dist/src/selection/selection.d.ts.map +1 -1
  64. package/dist/src/selection/selection.js +43 -6
  65. package/dist/src/selection/selection.test.d.ts +2 -0
  66. package/dist/src/selection/selection.test.d.ts.map +1 -0
  67. package/dist/src/selection/selection.test.js +14 -0
  68. package/dist/src/spec/parameter.d.ts +28 -2
  69. package/dist/src/spec/sampleView.d.ts +3 -2
  70. package/dist/src/styles/{genome-spy.scss → genome-spy.css} +25 -21
  71. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  72. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  73. package/dist/src/styles/genome-spy.css.js +264 -195
  74. package/dist/src/styles/update.sh +14 -4
  75. package/dist/src/types/viewContext.d.ts +1 -1
  76. package/dist/src/utils/expression.d.ts +5 -0
  77. package/dist/src/utils/expression.d.ts.map +1 -1
  78. package/dist/src/utils/expression.js +37 -0
  79. package/dist/src/utils/interactionEvent.d.ts +18 -1
  80. package/dist/src/utils/interactionEvent.d.ts.map +1 -1
  81. package/dist/src/utils/interactionEvent.js +101 -1
  82. package/dist/src/utils/interactionEvent.test.d.ts +2 -0
  83. package/dist/src/utils/interactionEvent.test.d.ts.map +1 -0
  84. package/dist/src/utils/interactionEvent.test.js +35 -0
  85. package/dist/src/view/axisResolution.d.ts +5 -0
  86. package/dist/src/view/axisResolution.d.ts.map +1 -1
  87. package/dist/src/view/axisResolution.js +16 -1
  88. package/dist/src/view/facetView.d.ts +1 -1
  89. package/dist/src/view/facetView.d.ts.map +1 -1
  90. package/dist/src/view/facetView.js +1 -0
  91. package/dist/src/view/flowBuilder.d.ts +2 -2
  92. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  93. package/dist/src/view/flowBuilder.js +21 -4
  94. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  95. package/dist/src/view/gridView/gridView.js +13 -0
  96. package/dist/src/view/gridView/selectionRect.d.ts +8 -4
  97. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  98. package/dist/src/view/gridView/selectionRect.js +28 -3
  99. package/dist/src/view/gridView/selectionRect.test.d.ts +2 -0
  100. package/dist/src/view/gridView/selectionRect.test.d.ts.map +1 -0
  101. package/dist/src/view/gridView/selectionRect.test.js +87 -0
  102. package/dist/src/view/paramMediator.d.ts +2 -1
  103. package/dist/src/view/paramMediator.d.ts.map +1 -1
  104. package/dist/src/view/paramMediator.js +13 -1
  105. package/dist/src/view/paramMediator.test.js +22 -0
  106. package/dist/src/view/scaleResolution.d.ts +5 -0
  107. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  108. package/dist/src/view/scaleResolution.js +10 -0
  109. package/dist/src/view/testUtils.d.ts.map +1 -1
  110. package/dist/src/view/testUtils.js +16 -4
  111. package/dist/src/view/unitView.d.ts.map +1 -1
  112. package/dist/src/view/unitView.js +103 -10
  113. package/dist/src/view/view.d.ts +17 -1
  114. package/dist/src/view/view.d.ts.map +1 -1
  115. package/dist/src/view/view.js +57 -1
  116. package/dist/src/view/viewDispose.test.d.ts +2 -0
  117. package/dist/src/view/viewDispose.test.d.ts.map +1 -0
  118. package/dist/src/view/viewDispose.test.js +110 -0
  119. package/dist/src/view/viewUtils.d.ts +4 -4
  120. package/dist/src/view/viewUtils.d.ts.map +1 -1
  121. package/dist/src/view/viewUtils.js +19 -15
  122. package/dist/src/view/viewUtils.test.d.ts +2 -0
  123. package/dist/src/view/viewUtils.test.d.ts.map +1 -0
  124. package/dist/src/view/viewUtils.test.js +87 -0
  125. package/package.json +16 -16
  126. package/dist/bundle/__vite-browser-external-C--ziKoh.js +0 -8
  127. package/dist/bundle/_commonjsHelpers-DjF3Plf2.js +0 -26
  128. package/dist/bundle/index-5ajWdKly.js +0 -1319
  129. package/dist/bundle/index-B03-Om4z.js +0 -274
  130. package/dist/bundle/index-BftNdA0O.js +0 -27
  131. package/dist/bundle/index-Bg7C4Xat.js +0 -2750
  132. package/dist/bundle/index-C3QR8Lv6.js +0 -2131
  133. package/dist/bundle/index-DTcHjAHp.js +0 -505
  134. package/dist/bundle/index-DnIkxb0L.js +0 -1025
  135. package/dist/bundle/index-Ww3TAo6_.js +0 -71
  136. package/dist/bundle/index-g8iXgW0W.js +0 -651
  137. package/dist/bundle/long-B-FASCSo.js +0 -2387
  138. package/dist/bundle/remoteFile-BuaqFGWk.js +0 -94
@@ -0,0 +1,87 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+
3
+ import ConcatView from "../concatView.js";
4
+ import UnitView from "../unitView.js";
5
+ import SelectionRect from "./selectionRect.js";
6
+ import { createTestViewContext } from "../testUtils.js";
7
+ import { buildDataFlow } from "../flowBuilder.js";
8
+ import { optimizeDataFlow } from "../../data/flowOptimizer.js";
9
+ import { syncFlowHandles } from "../../data/flowInit.js";
10
+
11
+ describe("SelectionRect", () => {
12
+ it("uses flow handles for dynamic data updates", () => {
13
+ const context = createTestViewContext();
14
+ const parent = new ConcatView(
15
+ { hconcat: [] },
16
+ context,
17
+ null,
18
+ null,
19
+ "p"
20
+ );
21
+
22
+ /** @type {import("../../spec/view.js").UnitSpec} */
23
+ const unitSpec = {
24
+ data: { values: [{ x: 0, y: 0 }] },
25
+ mark: "point",
26
+ encoding: {
27
+ x: { field: "x", type: "quantitative" },
28
+ y: { field: "y", type: "quantitative" },
29
+ },
30
+ };
31
+
32
+ const unitView = new UnitView(unitSpec, context, parent, parent, "u");
33
+
34
+ let selection = {
35
+ intervals: { x: [0, 1], y: [2, 3] },
36
+ };
37
+
38
+ /** @type {(listener: () => void) => void} */
39
+ const addListener = () => undefined;
40
+ /** @type {(listener: () => void) => void} */
41
+ const removeListener = () => undefined;
42
+ /** @type {() => void} */
43
+ const invalidate = () => undefined;
44
+
45
+ /** @type {import("../paramMediator.js").ExprRefFunction} */
46
+ const selectionExpr = Object.assign(() => selection, {
47
+ addListener,
48
+ removeListener,
49
+ invalidate,
50
+ identifier: () => "selection",
51
+ fields: [],
52
+ globals: [],
53
+ code: "selection",
54
+ });
55
+
56
+ const gridChild = /** @type {import("./gridChild.js").default} */ (
57
+ /** @type {unknown} */ ({
58
+ layoutParent: parent,
59
+ view: unitView,
60
+ })
61
+ );
62
+
63
+ const selectionRect = new SelectionRect(gridChild, selectionExpr);
64
+
65
+ const flow = buildDataFlow(selectionRect, context.dataFlow);
66
+ syncFlowHandles(selectionRect, optimizeDataFlow(flow));
67
+
68
+ const dataSource =
69
+ /** @type {import("../../data/sources/inlineSource.js").default} */ (
70
+ selectionRect.flowHandle?.dataSource
71
+ );
72
+ expect(dataSource).toBeDefined();
73
+
74
+ // Selection updates should push new interval data to the inline source.
75
+ const updateSpy = vi.spyOn(dataSource, "updateDynamicData");
76
+ selection = {
77
+ intervals: { x: [5, 6], y: [7, 8] },
78
+ };
79
+
80
+ selectionRect._selectionListener();
81
+
82
+ expect(updateSpy).toHaveBeenCalledTimes(1);
83
+ expect(updateSpy).toHaveBeenCalledWith([
84
+ { _x: 5, _x2: 6, _y: 7, _y2: 8 },
85
+ ]);
86
+ });
87
+ });
@@ -58,7 +58,7 @@ export function makeConstantExprRef(value: any): ExprRefFunction;
58
58
  * TODO: The proposed JavaScript signals may provide a better way to implement this.
59
59
  * https://github.com/proposal-signals/proposal-signals
60
60
  *
61
- * @typedef {import("../utils/expression.js").ExpressionFunction & { addListener: (listener: () => void) => void, invalidate: () => void, identifier: () => string}} ExprRefFunction
61
+ * @typedef {import("../utils/expression.js").ExpressionFunction & { addListener: (listener: () => void) => void, removeListener: (listener: () => void) => void, invalidate: () => void, identifier: () => string}} ExprRefFunction
62
62
  */
63
63
  export default class ParamMediator {
64
64
  /**
@@ -142,6 +142,7 @@ export default class ParamMediator {
142
142
  */
143
143
  export type ExprRefFunction = import("../utils/expression.js").ExpressionFunction & {
144
144
  addListener: (listener: () => void) => void;
145
+ removeListener: (listener: () => void) => void;
145
146
  invalidate: () => void;
146
147
  identifier: () => string;
147
148
  };
@@ -1 +1 @@
1
- {"version":3,"file":"paramMediator.d.ts","sourceRoot":"","sources":["../../../src/view/paramMediator.js"],"names":[],"mappings":"AAmVA;;;GAGG;AACH,6BAHW,GAAG,GACD,CAAC,IAAI,OAAO,sBAAsB,EAAE,OAAO,CAIvD;AAED;;;;;;;GAOG;AACH,+BAHa,CAAC,KADH,CAAC,GAAG,OAAO,sBAAsB,EAAE,OAAO,GAExC,CAAC,CAWb;AAED;;;GAGG;AACH,sFAFa,KAAK,IAAI,OAAO,sBAAsB,EAAE,iBAAiB,CAIrE;AAED;;;GAGG;AACH,uFAFa,KAAK,IAAI,OAAO,sBAAsB,EAAE,kBAAkB,CAItE;AAED;;;;;;;;;;GAUG;AACH,qCAF4E,CAAC,SAA/D,MAAM,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,sBAAsB,EAAE,OAAO,CAAE,iBAJhE,aAAa,SACb,CAAC,aACD,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,IAAI,GAuCjB,CAAC,CACtB;AAED;;;;;;GAMG;AACH,4CAHW,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;GAOG;AACH,2CAHW,GAAG,GACD,eAAe,CAW3B;AAtcD;;;;;;;;GAQG;AACH;IA2BI;;;;;OAKG;IACH,2BALW,MAAM,aAAa,EAU7B;IA7BD;;;OAGG;IACH,0BAHU,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAGvB;IA2Bf;;;OAGG;IACH,wEAzCqB,GAAG,KAAK,IAAI,CA2GhC;IAED;;;;;;;OAOG;IACH,eAFa,CAAC,aAJH,MAAM,gBACN,CAAC,YACD,OAAO,GACL,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAgC9B;IAED;;;OAGG;IACH,qBAFW,MAAM,WA1Ic,GAAG,KAAK,IAAI,CAkJ1C;IAED;;;OAGG;IACH,oBAFW,MAAM,OAIhB;IAED;;;OAGG;IACH,qBAFW,MAAM,OAKhB;IAED;;OAEG;IACH,oBACsB,WAAW,CAAC,MAAM,2CAAY,CAGnD;IAED;;;;OAIG;IACH,gCAHW,MAAM,GACJ,aAAa,CAQzB;IAID;;;;OAIG;IACH,uBAFW,MAAM,mBA4EhB;IAED;;;;OAIG;IACH,qBAFW,MAAM,OAKhB;IAED;;;;;OAKG;IACH,sBAFa,OAAO,CAiBnB;;CACJ;;;;;;;;8BA/TY,OAAO,wBAAwB,EAAE,kBAAkB,GAAG;IAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,MAAM,CAAA;CAAC"}
1
+ {"version":3,"file":"paramMediator.d.ts","sourceRoot":"","sources":["../../../src/view/paramMediator.js"],"names":[],"mappings":"AA8VA;;;GAGG;AACH,6BAHW,GAAG,GACD,CAAC,IAAI,OAAO,sBAAsB,EAAE,OAAO,CAIvD;AAED;;;;;;;GAOG;AACH,+BAHa,CAAC,KADH,CAAC,GAAG,OAAO,sBAAsB,EAAE,OAAO,GAExC,CAAC,CAWb;AAED;;;GAGG;AACH,sFAFa,KAAK,IAAI,OAAO,sBAAsB,EAAE,iBAAiB,CAIrE;AAED;;;GAGG;AACH,uFAFa,KAAK,IAAI,OAAO,sBAAsB,EAAE,kBAAkB,CAItE;AAED;;;;;;;;;;GAUG;AACH,qCAF4E,CAAC,SAA/D,MAAM,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,sBAAsB,EAAE,OAAO,CAAE,iBAJhE,aAAa,SACb,CAAC,aACD,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,IAAI,GAuCjB,CAAC,CACtB;AAED;;;;;;GAMG;AACH,4CAHW,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;GAOG;AACH,2CAHW,GAAG,GACD,eAAe,CAY3B;AAldD;;;;;;;;GAQG;AACH;IA2BI;;;;;OAKG;IACH,2BALW,MAAM,aAAa,EAU7B;IA7BD;;;OAGG;IACH,0BAHU,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAGvB;IA2Bf;;;OAGG;IACH,wEAzCqB,GAAG,KAAK,IAAI,CA2GhC;IAED;;;;;;;OAOG;IACH,eAFa,CAAC,aAJH,MAAM,gBACN,CAAC,YACD,OAAO,GACL,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAgC9B;IAED;;;OAGG;IACH,qBAFW,MAAM,WA1Ic,GAAG,KAAK,IAAI,CAkJ1C;IAED;;;OAGG;IACH,oBAFW,MAAM,OAIhB;IAED;;;OAGG;IACH,qBAFW,MAAM,OAKhB;IAED;;OAEG;IACH,oBACsB,WAAW,CAAC,MAAM,2CAAY,CAGnD;IAED;;;;OAIG;IACH,gCAHW,MAAM,GACJ,aAAa,CAQzB;IAID;;;;OAIG;IACH,uBAFW,MAAM,mBAuFhB;IAED;;;;OAIG;IACH,qBAFW,MAAM,OAKhB;IAED;;;;;OAKG;IACH,sBAFa,OAAO,CAiBnB;;CACJ;;;;;;;;8BA1UY,OAAO,wBAAwB,EAAE,kBAAkB,GAAG;IAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAAC,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,MAAM,CAAA;CAAC"}
@@ -16,7 +16,7 @@ import {
16
16
  * TODO: The proposed JavaScript signals may provide a better way to implement this.
17
17
  * https://github.com/proposal-signals/proposal-signals
18
18
  *
19
- * @typedef {import("../utils/expression.js").ExpressionFunction & { addListener: (listener: () => void) => void, invalidate: () => void, identifier: () => string}} ExprRefFunction
19
+ * @typedef {import("../utils/expression.js").ExpressionFunction & { addListener: (listener: () => void) => void, removeListener: (listener: () => void) => void, invalidate: () => void, identifier: () => string}} ExprRefFunction
20
20
  */
21
21
  export default class ParamMediator {
22
22
  /**
@@ -280,6 +280,16 @@ export default class ParamMediator {
280
280
  }
281
281
  };
282
282
 
283
+ /**
284
+ * @param {() => void} listener
285
+ */
286
+ fn.removeListener = (listener) => {
287
+ for (const [param, mediator] of mediatorsForParams) {
288
+ mediator.paramListeners.get(param)?.delete(listener);
289
+ }
290
+ myListeners.delete(listener);
291
+ };
292
+
283
293
  /**
284
294
  * Detach listeners. This must be called if the expression is no longer used.
285
295
  * TODO: What if the expression is used in multiple places?
@@ -290,6 +300,7 @@ export default class ParamMediator {
290
300
  mediator.paramListeners.get(param)?.delete(listener);
291
301
  }
292
302
  }
303
+ myListeners.clear();
293
304
  };
294
305
 
295
306
  // TODO: This should contain unique identifier for each parameter.
@@ -457,6 +468,7 @@ export function validateParameterName(name) {
457
468
  export function makeConstantExprRef(value) {
458
469
  return Object.assign(() => value, {
459
470
  addListener: () => /** @type {void} */ (undefined),
471
+ removeListener: () => /** @type {void} */ (undefined),
460
472
  invalidate: () => /** @type {void} */ (undefined),
461
473
  identifier: () => "constant",
462
474
  fields: [],
@@ -87,6 +87,28 @@ describe("Single-level ParamMediator", () => {
87
87
  expect(result).toBe(51);
88
88
  });
89
89
 
90
+ test("Expression removeListener detaches a listener", () => {
91
+ const pm = new ParamMediator();
92
+ const setter = pm.allocateSetter("foo", 42);
93
+ const expr = pm.createExpression("foo + 1");
94
+
95
+ let calls = 0;
96
+
97
+ const listener = () => {
98
+ calls++;
99
+ };
100
+
101
+ expr.addListener(listener);
102
+
103
+ setter(50);
104
+ expect(calls).toBe(1);
105
+
106
+ expr.removeListener(listener);
107
+
108
+ setter(60);
109
+ expect(calls).toBe(1);
110
+ });
111
+
90
112
  test("Expression parameter handles dependencies", () => {
91
113
  const pm = new ParamMediator();
92
114
  const setter = pm.registerParam({ name: "foo", value: 42 });
@@ -66,6 +66,11 @@ export default class ScaleResolution implements ScaleResolutionApi {
66
66
  * @param {ScaleResolutionMember} newMember
67
67
  */
68
68
  addMember(newMember: ScaleResolutionMember): void;
69
+ /**
70
+ * @param {UnitView} view
71
+ * @returns {boolean}
72
+ */
73
+ removeMembersByView(view: import("./unitView.js").default): boolean;
69
74
  /**
70
75
  * Extracts and unions the data domains of all participating views.
71
76
  *
@@ -1 +1 @@
1
- {"version":3,"file":"scaleResolution.d.ts","sourceRoot":"","sources":["../../../src/view/scaleResolution.js"],"names":[],"mappings":"AAm/BA;;;;;;;;;;GAUG;AACH,6CAFW,OAAO,WAAW,EAAE,OAAO,GAAG,OAAO,WAAW,EAAE,OAAO,EAAE,QA4BrE;AA3+BD,2BAA4B,cAAc,CAAC;AAC3C,sBAAuB,SAAS,CAAC;AACjC,sBAAuB,SAAS,CAAC;AACjC,oBAAqB,OAAO,CAAC;AAC7B,oBAAqB,OAAO,CAAC;AAE7B;;;;;;;;GAQG;AACH;;;;;;;GAOG;AACH;IA4CI;;OAEG;IACH,2DASC;IARG,8CAAsB;IACtB,yDAAyD;IACzD,SADW,qBAAqB,EAAE,CACjB;IACjB,0FAA0F;IAC1F,MADW,OAAO,oBAAoB,EAAE,IAAI,CAC5B;IAEhB,iEAAiE;IACjE,MADW,MAAM,CACI;IAWzB,2BAMC;IAED;;;;;;;OAOG;IACH,4KAEC;IAED;;;OAGG;IACH,+KAEC;IAcD;;;;;OAKG;IACH,qBAFW,qBAAqB,QAqD/B;IA8MD;;;;OAIG;IACH,+DAOC;IAED;;OAEG;IACH,oBA6CC;IAED;;OAEG;IACH;eApakC,OAAO,kBAAkB,EAAE,KAAK;MA4cjE;IAED,mBAEC;IAED;;OAEG;IACH,oBAFa,mFAA6B,CAOzC;IAED;;;;OAIG;IACH,oBAKC;IAED;;OAEG;IACH,sBAGC;IAUD;;;;;;;OAOG;IACH,kBALW,MAAM,eACN,MAAM,OACN,MAAM,GACJ,OAAO,CAmEnB;IAED;;;;;;OAMG;IACH,eAJW,mFAA6B,aAC7B,OAAO,GAAG,MAAM,iBA0D1B;IAED;;;;OAIG;IACH,qBAcC;IAED;;;;;OAKG;IACH,uBAOC;IAED;;;;;;;OAOG;IACH,wBAoBC;IAiED;;;OAGG;IACH,aAFa,OAAO,qBAAqB,EAAE,OAAO,CAajD;IAID;;;;;OAKG;IACH,uBAFW,MAAM,yDAUhB;IAED;;OAEG;IACH,iBAFW,MAAM,yDAKhB;IAED;;;OAGG;IACH,qBAHW,MAAM,+CAAmB,GACvB,MAAM,CAQlB;IAED;;;OAGG;IACH,8BAHW,kFAA4B,GAC1B,MAAM,EAAE,CAOpB;;CACJ;kCAr2B+B,CAAC,SAApB,6CAAkB;;;;UAGrB,OAAO,eAAe,EAAE,OAAO;aAC/B,CAAC;gBACD,OAAO,oBAAoB,EAAE,mBAAmB;sBAChD,CAAC,OAAO,+CAAkB,EAAE,IAAI,EAAE,OAAO,oBAAoB,EAAE,IAAI,kDAAgB"}
1
+ {"version":3,"file":"scaleResolution.d.ts","sourceRoot":"","sources":["../../../src/view/scaleResolution.js"],"names":[],"mappings":"AA6/BA;;;;;;;;;;GAUG;AACH,6CAFW,OAAO,WAAW,EAAE,OAAO,GAAG,OAAO,WAAW,EAAE,OAAO,EAAE,QA4BrE;AAr/BD,2BAA4B,cAAc,CAAC;AAC3C,sBAAuB,SAAS,CAAC;AACjC,sBAAuB,SAAS,CAAC;AACjC,oBAAqB,OAAO,CAAC;AAC7B,oBAAqB,OAAO,CAAC;AAE7B;;;;;;;;GAQG;AACH;;;;;;;GAOG;AACH;IA4CI;;OAEG;IACH,2DASC;IARG,8CAAsB;IACtB,yDAAyD;IACzD,SADW,qBAAqB,EAAE,CACjB;IACjB,0FAA0F;IAC1F,MADW,OAAO,oBAAoB,EAAE,IAAI,CAC5B;IAEhB,iEAAiE;IACjE,MADW,MAAM,CACI;IAWzB,2BAMC;IAED;;;;;;;OAOG;IACH,4KAEC;IAED;;;OAGG;IACH,+KAEC;IAcD;;;;;OAKG;IACH,qBAFW,qBAAqB,QAqD/B;IAED;;;OAGG;IACH,4DAFa,OAAO,CAMnB;IA8MD;;;;OAIG;IACH,+DAOC;IAED;;OAEG;IACH,oBA6CC;IAED;;OAEG;IACH;eA9akC,OAAO,kBAAkB,EAAE,KAAK;MAsdjE;IAED,mBAEC;IAED;;OAEG;IACH,oBAFa,mFAA6B,CAOzC;IAED;;;;OAIG;IACH,oBAKC;IAED;;OAEG;IACH,sBAGC;IAUD;;;;;;;OAOG;IACH,kBALW,MAAM,eACN,MAAM,OACN,MAAM,GACJ,OAAO,CAmEnB;IAED;;;;;;OAMG;IACH,eAJW,mFAA6B,aAC7B,OAAO,GAAG,MAAM,iBA0D1B;IAED;;;;OAIG;IACH,qBAcC;IAED;;;;;OAKG;IACH,uBAOC;IAED;;;;;;;OAOG;IACH,wBAoBC;IAiED;;;OAGG;IACH,aAFa,OAAO,qBAAqB,EAAE,OAAO,CAajD;IAID;;;;;OAKG;IACH,uBAFW,MAAM,yDAUhB;IAED;;OAEG;IACH,iBAFW,MAAM,yDAKhB;IAED;;;OAGG;IACH,qBAHW,MAAM,+CAAmB,GACvB,MAAM,CAQlB;IAED;;;OAGG;IACH,8BAHW,kFAA4B,GAC1B,MAAM,EAAE,CAOpB;;CACJ;kCA/2B+B,CAAC,SAApB,6CAAkB;;;;UAGrB,OAAO,eAAe,EAAE,OAAO;aAC/B,CAAC;gBACD,OAAO,oBAAoB,EAAE,mBAAmB;sBAChD,CAAC,OAAO,+CAAkB,EAAE,IAAI,EAAE,OAAO,oBAAoB,EAAE,IAAI,kDAAgB"}
@@ -231,6 +231,16 @@ export default class ScaleResolution {
231
231
  this.members.push(newMember);
232
232
  }
233
233
 
234
+ /**
235
+ * @param {UnitView} view
236
+ * @returns {boolean}
237
+ */
238
+ removeMembersByView(view) {
239
+ const before = this.members.length;
240
+ this.members = this.members.filter((member) => member.view !== view);
241
+ return this.members.length !== before;
242
+ }
243
+
234
244
  /**
235
245
  * Returns true if the domain has been defined explicitly, i.e. not extracted from the data.
236
246
  */
@@ -1 +1 @@
1
- {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../../src/view/testUtils.js"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,2DAHW,OAAO,kBAAkB,EAAE,kBAAkB,6CA+CvD;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;;;;;uBAhFpL,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,6CAwDvD;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;;;;;uBA5FpL,OAAO,iBAAiB,EAAE,QAAQ;;;;;0BAClC,OAAO,yBAAyB,EAAE,OAAO"}
@@ -6,12 +6,15 @@
6
6
  * @typedef {import("../types/viewContext.js").default} ViewContext
7
7
  */
8
8
 
9
- import { checkForDuplicateScaleNames, initializeData } from "./viewUtils.js";
9
+ import { checkForDuplicateScaleNames } from "./viewUtils.js";
10
+ import {
11
+ initializeViewSubtree,
12
+ loadViewSubtreeData,
13
+ } from "../data/flowInit.js";
10
14
  import DataFlow from "../data/dataFlow.js";
11
15
  import { VIEW_ROOT_NAME, ViewFactory } from "./viewFactory.js";
12
16
  import GenomeStore from "../genome/genomeStore.js";
13
17
  import BmFontManager from "../fonts/bmFontManager.js";
14
- import { reconfigureScales } from "./scaleResolution.js";
15
18
  import UnitView from "./unitView.js";
16
19
  import ContainerView from "./containerView.js";
17
20
 
@@ -56,6 +59,15 @@ export function createTestViewContext(viewFactoryOptions = {}) {
56
59
  genomeStore,
57
60
 
58
61
  fontManager: new BmFontManager(),
62
+ animator: /** @type {import("../utils/animator.js").default} */ (
63
+ /** @type {any} */ ({
64
+ requestRender: /** @type {() => void} */ (() => undefined),
65
+ requestTransition:
66
+ /** @type {(callback: () => void) => void} */ (
67
+ (callback) => callback()
68
+ ),
69
+ })
70
+ ),
59
71
 
60
72
  isViewConfiguredVisible: () => true,
61
73
 
@@ -99,7 +111,7 @@ export async function createAndInitialize(spec, viewClass) {
99
111
  });
100
112
  }
101
113
 
102
- await initializeData(view, view.context.dataFlow);
103
- reconfigureScales(view);
114
+ const { dataSources } = initializeViewSubtree(view, view.context.dataFlow);
115
+ await loadViewSubtreeData(view, dataSources);
104
116
  return view;
105
117
  }
@@ -1 +1 @@
1
- {"version":3,"file":"unitView.d.ts","sourceRoot":"","sources":["../../../src/view/unitView.js"],"names":[],"mappings":"AA4BA;;;;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,EAiCzC;IA5BG,yCAAgB;IAIZ,iDAAiD;IACjD,MADW,OAAO,kBAAkB,EAAE,OAAO,CACnB;IAkHlC,2DAIC;IAgBD;;;;;OAKG;IAEH,iEAsHC;IAED;;;;;OAKG;IACH,4IAEC;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;iBAragB,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,iEAsHC;IAwCD;;;;;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;iBAlgBgB,WAAW"}
@@ -25,6 +25,7 @@ import {
25
25
  updateMultiPointSelection,
26
26
  } from "../selection/selection.js";
27
27
  import { UNIQUE_ID_KEY } from "../data/transforms/identifier.js";
28
+ import { createEventFilterFunction } from "../utils/expression.js";
28
29
 
29
30
  /**
30
31
  *
@@ -87,14 +88,22 @@ export default class UnitView extends View {
87
88
  "zoomLevel",
88
89
  1.0
89
90
  );
90
- /** @type {import("../spec/channel.js").ChannelWithScale[]} */ ([
91
+
92
+ for (const channel of /** @type {import("../spec/channel.js").ChannelWithScale[]} */ ([
91
93
  "x",
92
94
  "y",
93
- ]).forEach((channel) =>
94
- this.getScaleResolution(channel)?.addEventListener("domain", () =>
95
- this.#zoomLevelSetter(Math.sqrt(this.getZoomLevel()))
96
- )
97
- );
95
+ ])) {
96
+ const resolution = this.getScaleResolution(channel);
97
+ if (resolution) {
98
+ const listener = () => {
99
+ this.#zoomLevelSetter(Math.sqrt(this.getZoomLevel()));
100
+ };
101
+ resolution.addEventListener("domain", listener);
102
+ this.registerDisposer(() =>
103
+ resolution.removeEventListener("domain", listener)
104
+ );
105
+ }
106
+ }
98
107
 
99
108
  this.needsAxes = { x: true, y: true };
100
109
 
@@ -108,6 +117,16 @@ export default class UnitView extends View {
108
117
  }
109
118
 
110
119
  const select = asSelectionConfig(param.select);
120
+ // Normalized config has eventConfig in "on"
121
+ const eventConfig =
122
+ /** @type {import("../spec/parameter.js").EventConfig} */ (
123
+ select.on
124
+ );
125
+
126
+ const clearEventConfig =
127
+ /** @type {import("../spec/parameter.js").EventConfig} */ (
128
+ select.clear
129
+ );
111
130
 
112
131
  if (isPointSelectionConfig(select)) {
113
132
  // Handle projection-free point selections
@@ -122,10 +141,17 @@ export default class UnitView extends View {
122
141
  return h?.mark?.unitView === this ? h.datum : null;
123
142
  };
124
143
 
144
+ const eventPredicate = eventConfig.filter
145
+ ? createEventFilterFunction(eventConfig.filter)
146
+ : () => true;
147
+
125
148
  const listener = (
126
149
  /** @type {any} */ _,
127
150
  /** @type {import("../utils/interactionEvent.js").default} */ event
128
151
  ) => {
152
+ if (!eventPredicate(event.proxiedMouseEvent)) {
153
+ return;
154
+ }
129
155
  const datum = getHoveredDatum();
130
156
  const id = datum ? datum[UNIQUE_ID_KEY] : none;
131
157
 
@@ -164,11 +190,36 @@ export default class UnitView extends View {
164
190
  };
165
191
 
166
192
  this.addInteractionEventListener(
167
- ["mouseover", "pointerover"].includes(select.on)
193
+ ["mouseover", "pointerover"].includes(eventConfig.type)
168
194
  ? "mousemove"
169
- : "click",
195
+ : eventConfig.type,
170
196
  listener
171
197
  );
198
+
199
+ if (clearEventConfig) {
200
+ const clearPredicate = clearEventConfig.filter
201
+ ? createEventFilterFunction(clearEventConfig.filter)
202
+ : () => true;
203
+
204
+ const clearListener = (
205
+ /** @type {any} */ _,
206
+ /** @type {import("../utils/interactionEvent.js").default} */ event
207
+ ) => {
208
+ if (!clearPredicate(event.proxiedMouseEvent)) {
209
+ return;
210
+ }
211
+ lastId = none;
212
+ const selection = select.toggle
213
+ ? createMultiPointSelection()
214
+ : createSinglePointSelection(null);
215
+ setter(selection);
216
+ };
217
+
218
+ this.addInteractionEventListener(
219
+ clearEventConfig.type,
220
+ clearListener
221
+ );
222
+ }
172
223
  }
173
224
  }
174
225
  }
@@ -337,6 +388,44 @@ export default class UnitView extends View {
337
388
  }
338
389
  }
339
390
 
391
+ /**
392
+ * @override
393
+ */
394
+ dispose() {
395
+ super.dispose();
396
+
397
+ this.#unresolve();
398
+ this.mark.dispose();
399
+ }
400
+
401
+ #unresolve() {
402
+ for (const view of this.getDataAncestors()) {
403
+ for (const [channel, resolution] of Object.entries(
404
+ view.resolutions.scale
405
+ )) {
406
+ if (
407
+ resolution &&
408
+ resolution.removeMembersByView(this) &&
409
+ resolution.members.length === 0
410
+ ) {
411
+ delete view.resolutions.scale[channel];
412
+ }
413
+ }
414
+
415
+ for (const [channel, resolution] of Object.entries(
416
+ view.resolutions.axis
417
+ )) {
418
+ if (
419
+ resolution &&
420
+ resolution.removeMembersByView(this) &&
421
+ resolution.members.length === 0
422
+ ) {
423
+ delete view.resolutions.axis[channel];
424
+ }
425
+ }
426
+ }
427
+ }
428
+
340
429
  /**
341
430
  * Returns an accessor that accesses a field or an evaluated expression,
342
431
  * if there is one.
@@ -344,7 +433,11 @@ export default class UnitView extends View {
344
433
  * @param {Channel} channel
345
434
  */
346
435
  getDataAccessor(channel) {
347
- return this.mark.encoders[channel]?.dataAccessor;
436
+ const encoders = this.mark.encoders;
437
+ if (!encoders) {
438
+ return undefined;
439
+ }
440
+ return encoders[channel]?.dataAccessor;
348
441
  }
349
442
 
350
443
  /**
@@ -367,7 +460,7 @@ export default class UnitView extends View {
367
460
  * Returns a collector that is associated with this view.
368
461
  */
369
462
  getCollector() {
370
- return this.context.dataFlow.findCollectorByKey(this);
463
+ return this.flowHandle?.collector;
371
464
  }
372
465
 
373
466
  /**
@@ -90,6 +90,10 @@ export default class View {
90
90
  */
91
91
  layersChildren?: boolean;
92
92
  };
93
+ /**
94
+ * @type {import("../data/flowHandle.js").FlowHandle | undefined}
95
+ */
96
+ flowHandle: import("../data/flowHandle.js").FlowHandle | undefined;
93
97
  /**
94
98
  * Whether GridView or equivalent should draw axis and grid lines for this view.
95
99
  * TODO: Use view options for this.
@@ -210,9 +214,21 @@ export default class View {
210
214
  */
211
215
  visit(visitor: Visitor): VisitResult;
212
216
  /**
213
- * Get all descendants of this view in depth-first order.
217
+ * Get this view and all descendants in depth-first order.
214
218
  */
215
219
  getDescendants(): View[];
220
+ /**
221
+ * Release resources owned by this view.
222
+ */
223
+ dispose(): void;
224
+ /**
225
+ * @param {() => void} disposer
226
+ */
227
+ registerDisposer(disposer: () => void): void;
228
+ /**
229
+ * Dispose this view and all descendants in post-order.
230
+ */
231
+ disposeSubtree(): void;
216
232
  /**
217
233
  * Called after all scales in the view hierarchy have been resolved.
218
234
  */
@@ -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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"}
@@ -86,6 +86,11 @@ export default class View {
86
86
  */
87
87
  opacityFunction = defaultOpacityFunction;
88
88
 
89
+ /**
90
+ * @type {(() => void)[]}
91
+ */
92
+ #disposers = [];
93
+
89
94
  /**
90
95
  * Coords of the view for each facet, recorded during the last layout rendering pass.
91
96
  * Most views have only one facet, so the map is usually of size 1.
@@ -136,6 +141,11 @@ export default class View {
136
141
  ...options,
137
142
  };
138
143
 
144
+ /**
145
+ * @type {import("../data/flowHandle.js").FlowHandle | undefined}
146
+ */
147
+ this.flowHandle = undefined;
148
+
139
149
  /**
140
150
  * Whether GridView or equivalent should draw axis and grid lines for this view.
141
151
  * TODO: Use view options for this.
@@ -497,7 +507,7 @@ export default class View {
497
507
  }
498
508
 
499
509
  /**
500
- * Get all descendants of this view in depth-first order.
510
+ * Get this view and all descendants in depth-first order.
501
511
  */
502
512
  getDescendants() {
503
513
  /** @type {View[]} */
@@ -508,6 +518,52 @@ export default class View {
508
518
  return descendants;
509
519
  }
510
520
 
521
+ /**
522
+ * Release resources owned by this view.
523
+ */
524
+ dispose() {
525
+ for (const disposer of this.#disposers) {
526
+ disposer();
527
+ }
528
+ this.#disposers.length = 0;
529
+
530
+ const handle = this.flowHandle;
531
+
532
+ if (handle?.collector) {
533
+ this.context.dataFlow.pruneCollectorBranch(handle.collector);
534
+ this.context.dataFlow.removeCollector(handle.collector);
535
+ }
536
+
537
+ if (
538
+ handle?.dataSource &&
539
+ handle.dataSource.view === this &&
540
+ !handle.dataSource.identifier
541
+ ) {
542
+ this.context.dataFlow.removeDataSource(handle.dataSource);
543
+ }
544
+
545
+ this.flowHandle = undefined;
546
+ }
547
+
548
+ /**
549
+ * @param {() => void} disposer
550
+ */
551
+ registerDisposer(disposer) {
552
+ this.#disposers.push(disposer);
553
+ }
554
+
555
+ /**
556
+ * Dispose this view and all descendants in post-order.
557
+ */
558
+ disposeSubtree() {
559
+ /** @type {Visitor} */
560
+ const visitor = () => undefined;
561
+ visitor.postOrder = (view) => {
562
+ view.dispose();
563
+ };
564
+ this.visit(visitor);
565
+ }
566
+
511
567
  /**
512
568
  * Called after all scales in the view hierarchy have been resolved.
513
569
  */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=viewDispose.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewDispose.test.d.ts","sourceRoot":"","sources":["../../../src/view/viewDispose.test.js"],"names":[],"mappings":""}