@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
@@ -1,6 +1,16 @@
1
1
  #!/bin/sh
2
- echo "const css = \`" > genome-spy.css.js
3
- sass genome-spy.scss >> genome-spy.css.js
4
- echo "\`;" >> genome-spy.css.js
5
- echo "export default css;" >> genome-spy.css.js
2
+ # Build helper: minify genome-spy.css (strip leading whitespace) and embed into a JS module
6
3
 
4
+ CSS_IN=genome-spy.css
5
+ JS_OUT=genome-spy.css.js
6
+
7
+ if [ ! -f "$CSS_IN" ]; then
8
+ echo "Missing $CSS_IN in $(pwd)"
9
+ exit 1
10
+ fi
11
+
12
+
13
+ echo "const css = \`" > "$JS_OUT"
14
+ sed -E 's/^[[:space:]]+//' "$CSS_IN" >> "$JS_OUT"
15
+ echo "\`;" >> "$JS_OUT"
16
+ echo "export default css;" >> "$JS_OUT"
@@ -22,7 +22,7 @@ export type DataLoadingStatus = "loading" | "complete" | "error";
22
22
  * ViewContext provides essential data and interfaces to View classes.
23
23
  */
24
24
  export default interface ViewContext {
25
- dataFlow: DataFlow<View>;
25
+ dataFlow: DataFlow;
26
26
  glHelper: WebGLHelper;
27
27
  animator: Animator;
28
28
  genomeStore?: GenomeStore;
@@ -10,6 +10,11 @@
10
10
  * @returns {ExpressionFunction}
11
11
  */
12
12
  export default function createFunction(expr: string, globalObject?: {}): ExpressionFunction;
13
+ /**
14
+ * @param {string} expr
15
+ * @returns {(event: UIEvent) => boolean}
16
+ */
17
+ export function createEventFilterFunction(expr: string): (event: UIEvent) => boolean;
13
18
  export type ExpressionProps = {
14
19
  fields: string[];
15
20
  globals: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../../src/utils/expression.js"],"names":[],"mappings":"AAuEA;;;;;;;;;;GAUG;AACH,6CAHW,MAAM,sBACJ,kBAAkB,CAgC9B;;YAvCU,MAAM,EAAE;aACR,MAAM,EAAE;UACR,MAAM;;iCAEH,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,qBAAqB,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,eAAe"}
1
+ {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../../src/utils/expression.js"],"names":[],"mappings":"AAuEA;;;;;;;;;;GAUG;AACH,6CAHW,MAAM,sBACJ,kBAAkB,CAgC9B;AAQD;;;GAGG;AACH,gDAHW,MAAM,GACJ,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CA2BvC;;YA5EU,MAAM,EAAE;aACR,MAAM,EAAE;UACR,MAAM;;iCAEH,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,qBAAqB,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,eAAe"}
@@ -111,3 +111,40 @@ export default function createFunction(expr, globalObject = {}) {
111
111
  throw new Error(`Invalid expression: ${expr}, ${e.message}`);
112
112
  }
113
113
  }
114
+
115
+ const eventFilterCg = codegenExpression({
116
+ forbidden: [],
117
+ allowed: ["event"],
118
+ globalvar: "globalObject",
119
+ });
120
+
121
+ /**
122
+ * @param {string} expr
123
+ * @returns {(event: UIEvent) => boolean}
124
+ */
125
+ export function createEventFilterFunction(expr) {
126
+ try {
127
+ const parsed = parseExpression(expr);
128
+ const generatedCode = eventFilterCg(parsed);
129
+
130
+ // eslint-disable-next-line no-new-func
131
+ const fn = Function(
132
+ "event",
133
+ "globalObject",
134
+ `"use strict";
135
+ try {
136
+ return !!(${generatedCode.code});
137
+ } catch (e) {
138
+ throw new Error("Error evaluating expression: " + ${JSON.stringify(
139
+ expr
140
+ )} + ", " + e.message, e);
141
+ }`
142
+ );
143
+
144
+ return /** @type {(event: UIEvent) => boolean} */ (
145
+ /** @type {any} */ (fn)
146
+ );
147
+ } catch (e) {
148
+ throw new Error(`Invalid expression: ${expr}, ${e.message}`);
149
+ }
150
+ }
@@ -1,3 +1,12 @@
1
+ /**
2
+ * Create a safe proxy for an event-like object that exposes only primitive
3
+ * (string, number, boolean, bigint, symbol, undefined) properties and null.
4
+ *
5
+ * @param {T} target The event-like object to wrap.
6
+ * @returns {T} A proxy exposing only primitive properties.
7
+ * @template T
8
+ */
9
+ export function createPrimitiveEventProxy<T>(target: T): T;
1
10
  /**
2
11
  * This class wraps a MouseEvent (or similar) and allows for
3
12
  * its propagation through the view hierarchy in a similar manner
@@ -5,7 +14,6 @@
5
14
  */
6
15
  export default class InteractionEvent {
7
16
  /**
8
- *
9
17
  * @param {import("../view/layout/point.js").default} point Event coordinates
10
18
  * inside the visualization canvas.
11
19
  * @param {UIEvent} uiEvent The event to be wrapped
@@ -21,7 +29,16 @@ export default class InteractionEvent {
21
29
  */
22
30
  target: import("../view/view.js").default;
23
31
  stopPropagation(): void;
32
+ /**
33
+ * The event type string of the underlying UI event (e.g. "click", "keydown").
34
+ *
35
+ * This getter proxies and returns the `type` property from the internal `UIEvent` instance (`this.uiEvent`).
36
+ *
37
+ * @returns {string} The UI event type.
38
+ */
24
39
  get type(): string;
40
+ get proxiedMouseEvent(): MouseEvent;
25
41
  get mouseEvent(): MouseEvent;
42
+ #private;
26
43
  }
27
44
  //# sourceMappingURL=interactionEvent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interactionEvent.d.ts","sourceRoot":"","sources":["../../../src/utils/interactionEvent.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH;IACI;;;;;OAKG;IACH,mBAJW,OAAO,yBAAyB,EAAE,OAAO,WAEzC,OAAO,EAajB;IAVG,iDAAkB;IAClB,iBAAsB;IACtB,iBAAoB;IAEpB;;;;OAIG;IACH,QAFU,OAAO,iBAAiB,EAAE,OAAO,CAEpB;IAG3B,wBAEC;IAED,mBAEC;IAED,6BAMC;CACJ"}
1
+ {"version":3,"file":"interactionEvent.d.ts","sourceRoot":"","sources":["../../../src/utils/interactionEvent.js"],"names":[],"mappings":"AA6DA;;;;;;;GAOG;AACH,0CAFa,CAAC,UAFH,CAAC,GACC,CAAC,CA0Eb;AA5ID;;;;GAIG;AACH;IAII;;;;OAIG;IACH,mBAJW,OAAO,yBAAyB,EAAE,OAAO,WAEzC,OAAO,EAajB;IAVG,iDAAkB;IAClB,iBAAsB;IACtB,iBAAoB;IAEpB;;;;OAIG;IACH,QAFU,OAAO,iBAAiB,EAAE,OAAO,CAEpB;IAG3B,wBAEC;IAED;;;;;;OAMG;IACH,YAFa,MAAM,CAIlB;IAED,oCAQC;IAED,6BAMC;;CACJ"}
@@ -4,8 +4,10 @@
4
4
  * as in the DOM.
5
5
  */
6
6
  export default class InteractionEvent {
7
+ /** @type {MouseEvent} */
8
+ #primitiveMouseEventProxy;
9
+
7
10
  /**
8
- *
9
11
  * @param {import("../view/layout/point.js").default} point Event coordinates
10
12
  * inside the visualization canvas.
11
13
  * @param {UIEvent} uiEvent The event to be wrapped
@@ -27,10 +29,27 @@ export default class InteractionEvent {
27
29
  this.stopped = true;
28
30
  }
29
31
 
32
+ /**
33
+ * The event type string of the underlying UI event (e.g. "click", "keydown").
34
+ *
35
+ * This getter proxies and returns the `type` property from the internal `UIEvent` instance (`this.uiEvent`).
36
+ *
37
+ * @returns {string} The UI event type.
38
+ */
30
39
  get type() {
31
40
  return this.uiEvent.type;
32
41
  }
33
42
 
43
+ get proxiedMouseEvent() {
44
+ if (!this.#primitiveMouseEventProxy) {
45
+ this.#primitiveMouseEventProxy = createPrimitiveEventProxy(
46
+ this.mouseEvent
47
+ );
48
+ }
49
+
50
+ return this.#primitiveMouseEventProxy;
51
+ }
52
+
34
53
  get mouseEvent() {
35
54
  if (this.uiEvent instanceof MouseEvent) {
36
55
  return this.uiEvent;
@@ -39,3 +58,84 @@ export default class InteractionEvent {
39
58
  }
40
59
  }
41
60
  }
61
+
62
+ /**
63
+ * Create a safe proxy for an event-like object that exposes only primitive
64
+ * (string, number, boolean, bigint, symbol, undefined) properties and null.
65
+ *
66
+ * @param {T} target The event-like object to wrap.
67
+ * @returns {T} A proxy exposing only primitive properties.
68
+ * @template T
69
+ */
70
+ export function createPrimitiveEventProxy(target) {
71
+ /**
72
+ * @param {any} v
73
+ * @returns {boolean}
74
+ */
75
+ const isPrimitiveOrNull = (v) =>
76
+ v === null || (typeof v !== "object" && typeof v !== "function");
77
+
78
+ /** @type {ProxyHandler<any>} */
79
+ const handler = {
80
+ /**
81
+ * @param {any} target
82
+ * @param {PropertyKey} prop
83
+ * @param {any} receiver
84
+ */
85
+ get(target, prop, receiver) {
86
+ const value = Reflect.get(target, prop, target);
87
+ if (!isPrimitiveOrNull(value)) {
88
+ throw new Error(
89
+ `Access to non-primitive property "${String(prop)}" is not allowed.`
90
+ );
91
+ }
92
+ return value;
93
+ },
94
+
95
+ getPrototypeOf() {
96
+ return null;
97
+ },
98
+
99
+ /**
100
+ * @param {any} target
101
+ * @returns {ArrayLike<string|symbol>}
102
+ */
103
+ ownKeys(target) {
104
+ const keys = Reflect.ownKeys(target).filter((k) =>
105
+ isPrimitiveOrNull(target[k])
106
+ );
107
+ return keys.map((k) => (typeof k === "symbol" ? k : String(k)));
108
+ },
109
+
110
+ /**
111
+ * @param {any} target
112
+ * @param {PropertyKey} prop
113
+ * @returns {PropertyDescriptor|undefined}
114
+ */
115
+ getOwnPropertyDescriptor(target, prop) {
116
+ const desc = Reflect.getOwnPropertyDescriptor(target, prop);
117
+ if (!desc) return undefined;
118
+ // hide accessor properties (getters/setters)
119
+ if ("get" in desc || "set" in desc) return undefined;
120
+ if (!isPrimitiveOrNull(desc.value)) return undefined;
121
+ // Preserve configurability/enumerability/writability to satisfy proxy invariants
122
+ return {
123
+ value: desc.value,
124
+ writable: !!desc.writable,
125
+ enumerable: !!desc.enumerable,
126
+ configurable: !!desc.configurable,
127
+ };
128
+ },
129
+
130
+ /**
131
+ * @param {any} target
132
+ * @param {PropertyKey} prop
133
+ * @returns {boolean} */
134
+ has(target, prop) {
135
+ if (!(prop in target)) return false;
136
+ return isPrimitiveOrNull(target[prop]);
137
+ },
138
+ };
139
+
140
+ return new Proxy(target, handler);
141
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=interactionEvent.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactionEvent.test.d.ts","sourceRoot":"","sources":["../../../src/utils/interactionEvent.test.js"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { createPrimitiveEventProxy } from "./interactionEvent.js";
3
+
4
+ describe("createPrimitiveEventProxy", () => {
5
+ it("exposes primitive properties and hides non-primitives", () => {
6
+ const mock = {
7
+ type: "click",
8
+ clientX: 42,
9
+ meta: { foo: "bar" },
10
+ nested: { a: 1 },
11
+ };
12
+
13
+ /** @type {any} */
14
+ const proxy = createPrimitiveEventProxy(mock);
15
+
16
+ // allowed primitives
17
+ expect(proxy.type).toBe("click");
18
+ expect(proxy.clientX).toBe(42);
19
+
20
+ // non-primitive access throws
21
+ expect(() => proxy.meta).toThrow(/non-primitive/);
22
+
23
+ // keys enumeration hides non-primitives
24
+ const keys = Object.keys(proxy);
25
+ expect(keys).toContain("type");
26
+ expect(keys).not.toContain("meta");
27
+
28
+ // `in` operator respects the policy
29
+ expect("type" in proxy).toBe(true);
30
+ expect("meta" in proxy).toBe(false);
31
+
32
+ // prototype is hidden
33
+ expect(Object.getPrototypeOf(proxy)).toBeNull();
34
+ });
35
+ });
@@ -26,6 +26,11 @@ export default class AxisResolution {
26
26
  * @param {AxisResolutionMember} newMember
27
27
  */
28
28
  addMember(newMember: AxisResolutionMember): void;
29
+ /**
30
+ * @param {UnitView} view
31
+ * @returns {boolean}
32
+ */
33
+ removeMembersByView(view: import("./unitView.js").default): boolean;
29
34
  getAxisProps(): import("../spec/axis.js").GenomeAxis;
30
35
  getTitle(): string;
31
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"axisResolution.d.ts","sourceRoot":"","sources":["../../../src/view/axisResolution.js"],"names":[],"mappings":"AAeA;;;;;;;GAOG;AACH;IACI;;;OAGG;IAEH;;OAEG;IACH,qBAFW,OAAO,oBAAoB,EAAE,wBAAwB,EAM/D;IAHG,+DAAsB;IACtB,wDAAwD;IACxD,SADW,oBAAoB,EAAE,CAChB;IAGrB,8DAEC;IAED;;;;;OAKG;IACH,qBAFW,oBAAoB,QAwB9B;IAED,qDAuBC;IAED,mBAyDC;CACJ;iCA3I6D,CAAC,SAAlD,OAAQ,oBAAoB,EAAE,iBAAkB;UAGnD,OAAO,eAAe,EAAE,OAAO;aAC/B,CAAC;gBACD,OAAO,oBAAoB,EAAE,mBAAmB"}
1
+ {"version":3,"file":"axisResolution.d.ts","sourceRoot":"","sources":["../../../src/view/axisResolution.js"],"names":[],"mappings":"AAeA;;;;;;;GAOG;AACH;IACI;;;OAGG;IAEH;;OAEG;IACH,qBAFW,OAAO,oBAAoB,EAAE,wBAAwB,EAM/D;IAHG,+DAAsB;IACtB,wDAAwD;IACxD,SADW,oBAAoB,EAAE,CAChB;IAGrB,8DAEC;IAED;;;;;OAKG;IACH,qBAFW,oBAAoB,QAyB9B;IAED;;;OAGG;IACH,4DAFa,OAAO,CAUnB;IAED,qDAuBC;IAED,mBAyDC;CACJ;iCA1J6D,CAAC,SAAlD,OAAQ,oBAAoB,EAAE,iBAAkB;UAGnD,OAAO,eAAe,EAAE,OAAO;aAC/B,CAAC;gBACD,OAAO,oBAAoB,EAAE,mBAAmB"}
@@ -11,7 +11,7 @@ import { peek } from "../utils/arrayUtils.js";
11
11
  import coalesce from "../utils/coalesce.js";
12
12
 
13
13
  import mergeObjects from "../utils/mergeObjects.js";
14
- import { getCachedOrCall } from "../utils/propertyCacher.js";
14
+ import { getCachedOrCall, invalidate } from "../utils/propertyCacher.js";
15
15
 
16
16
  /**
17
17
  * @template {import("../spec/channel.js").PositionalChannel}[T=PositionalChannel]
@@ -68,6 +68,21 @@ export default class AxisResolution {
68
68
  }
69
69
 
70
70
  this.members.push(newMember);
71
+ invalidate(this, "axisProps");
72
+ }
73
+
74
+ /**
75
+ * @param {UnitView} view
76
+ * @returns {boolean}
77
+ */
78
+ removeMembersByView(view) {
79
+ const before = this.members.length;
80
+ this.members = this.members.filter((member) => member.view !== view);
81
+ if (this.members.length !== before) {
82
+ invalidate(this, "axisProps");
83
+ return true;
84
+ }
85
+ return false;
71
86
  }
72
87
 
73
88
  getAxisProps() {
@@ -48,7 +48,7 @@ export default class FacetView extends ContainerView {
48
48
  getAccessor(channel: "row" | "column"): any;
49
49
  updateFacets(): void;
50
50
  updateLabels(): void;
51
- getFacetGroups(): any[];
51
+ getFacetGroups(): string[] | number[] | boolean[];
52
52
  /**
53
53
  * @param {import("./renderingContext/viewRenderingContext.js").default} context
54
54
  * @param {import("./layout/rectangle.js").default} coords
@@ -1 +1 @@
1
- {"version":3,"file":"facetView.d.ts","sourceRoot":"","sources":["../../../src/view/facetView.js"],"names":[],"mappings":"AAmDA;;;;;;;;;;;;;;GAcG;AACH;IACI;;;;;;;OAOG;IACH;;;;;;OAMG;IACH,kBALW,OAAO,gBAAgB,EAAE,SAAS,WAClC,OAAO,gBAAgB,EAAE,WAAW,UACpC,aAAa,QACb,MAAM,EA8BhB;IAzBG,UAAgB;IAEhB,WAEC;IAED;;;;OAIG;IACH,aAFU,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAYvC;IAED,oDAAoD;IACpD,kBADY,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,CACa;IA2BjE,sBAIC;IAED;;;OAGG;IACH,qBAFW,KAAK,GAAG,QAAQ,OAwB1B;IAED,qBAyCC;IAED,qBASC;IA6BD,wBAgBC;IAOD;;;;OAIG;IACH,gBAJW,OAAO,4CAA4C,EAAE,OAAO,UAC5D,OAAO,uBAAuB,EAAE,OAAO,YACvC,OAAO,WAAW,EAAE,gBAAgB,QA2L9C;IA3KO,wBAA0B;CA4KrC;2BA/bY,QAAQ,GAAG,KAAK;;;;;;aA4CnB,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE;;;0BA1Df,oBAAoB;qBACzB,eAAe"}
1
+ {"version":3,"file":"facetView.d.ts","sourceRoot":"","sources":["../../../src/view/facetView.js"],"names":[],"mappings":"AAmDA;;;;;;;;;;;;;;GAcG;AACH;IACI;;;;;;;OAOG;IACH;;;;;;OAMG;IACH,kBALW,OAAO,gBAAgB,EAAE,SAAS,WAClC,OAAO,gBAAgB,EAAE,WAAW,UACpC,aAAa,QACb,MAAM,EA8BhB;IAzBG,UAAgB;IAEhB,WAEC;IAED;;;;OAIG;IACH,aAFU,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAYvC;IAED,oDAAoD;IACpD,kBADY,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,CACa;IA4BjE,sBAIC;IAED;;;OAGG;IACH,qBAFW,KAAK,GAAG,QAAQ,OAwB1B;IAED,qBAyCC;IAED,qBASC;IA6BD,kDAgBC;IAOD;;;;OAIG;IACH,gBAJW,OAAO,4CAA4C,EAAE,OAAO,UAC5D,OAAO,uBAAuB,EAAE,OAAO,YACvC,OAAO,WAAW,EAAE,gBAAgB,QA2L9C;IA3KO,wBAA0B;CA4KrC;2BAhcY,QAAQ,GAAG,KAAK;;;;;;aA4CnB,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE;;;0BA1Df,oBAAoB;qBACzB,eAAe"}
@@ -129,6 +129,7 @@ export default class FacetView extends ContainerView {
129
129
  throw new Error("Not my child!");
130
130
  }
131
131
 
132
+ child.disposeSubtree();
132
133
  this.child = /** @type {UnitView | LayerView | DecoratorView} */ (
133
134
  replacement
134
135
  );
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * @param {View} root
3
- * @param {DataFlow<View>} [existingFlow] Add data flow
3
+ * @param {DataFlow} [existingFlow] Add data flow
4
4
  * graphs to an existing DataFlow object.
5
5
  */
6
- export function buildDataFlow(root: import("./view.js").default, existingFlow?: DataFlow<import("./view.js").default>): DataFlow<import("./view.js").default>;
6
+ export function buildDataFlow(root: import("./view.js").default, existingFlow?: DataFlow): DataFlow;
7
7
  /**
8
8
  * Changes the ChromPos channelDefs into FieldDefs and returns
9
9
  * LinearizeGenomicCoordinate transform(s) that should be inserted into
@@ -1 +1 @@
1
- {"version":3,"file":"flowBuilder.d.ts","sourceRoot":"","sources":["../../../src/view/flowBuilder.js"],"names":[],"mappings":"AAwBA;;;;GAIG;AACH,gFAHW,QAAQ,6BAAM,yCAkMxB;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;qBA5ZoB,qBAAqB;sBANpB,sBAAsB"}
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"}
@@ -24,7 +24,7 @@ import { nodesToTreesWithAccessor, visitTree } from "../utils/trees.js";
24
24
 
25
25
  /**
26
26
  * @param {View} root
27
- * @param {DataFlow<View>} [existingFlow] Add data flow
27
+ * @param {DataFlow} [existingFlow] Add data flow
28
28
  * graphs to an existing DataFlow object.
29
29
  */
30
30
  export function buildDataFlow(root, existingFlow) {
@@ -41,7 +41,7 @@ export function buildDataFlow(root, existingFlow) {
41
41
  /** @type {FlowNode} */
42
42
  let currentNode;
43
43
 
44
- /** @type {DataFlow<View>} */
44
+ /** @type {DataFlow} */
45
45
  const dataFlow = existingFlow ?? new DataFlow();
46
46
 
47
47
  /** @type {(function():void)[]} */
@@ -122,6 +122,15 @@ export function buildDataFlow(root, existingFlow) {
122
122
  /** @param {View} view */
123
123
  const processView = (view) => {
124
124
  if (view.spec.data) {
125
+ const previousDataSource = view.flowHandle?.dataSource;
126
+ if (
127
+ previousDataSource &&
128
+ previousDataSource.view === view &&
129
+ !previousDataSource.identifier
130
+ ) {
131
+ dataFlow.removeDataSource(previousDataSource);
132
+ }
133
+
125
134
  const dataSource = isNamedData(view.spec.data)
126
135
  ? new NamedSource(
127
136
  view.spec.data,
@@ -132,7 +141,9 @@ export function buildDataFlow(root, existingFlow) {
132
141
 
133
142
  currentNode = dataSource;
134
143
  nodeStack.push(dataSource);
135
- dataFlow.addDataSource(dataSource, view);
144
+ dataFlow.addDataSource(dataSource);
145
+ view.flowHandle ??= {};
146
+ view.flowHandle.dataSource = dataSource;
136
147
  }
137
148
 
138
149
  if (view.spec.transform) {
@@ -186,7 +197,13 @@ export function buildDataFlow(root, existingFlow) {
186
197
  });
187
198
 
188
199
  appendNode(collector);
189
- dataFlow.addCollector(collector, view);
200
+ const previousCollector = view.flowHandle?.collector;
201
+ if (previousCollector) {
202
+ dataFlow.removeCollector(previousCollector);
203
+ }
204
+ dataFlow.addCollector(collector);
205
+ view.flowHandle ??= {};
206
+ view.flowHandle.collector = collector;
190
207
  }
191
208
  };
192
209
 
@@ -1 +1 @@
1
- {"version":3,"file":"gridView.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/gridView.js"],"names":[],"mappings":"AAqyBA;;GAEG;AACH,+EAUC;AAED;;;;;GAKG;AACH,4CAJW,OAAO,wBAAwB,EAAE,OAAO,UACxC,OAAO,oBAAoB,EAAE,UAAU,YACvC,QAAQ,aAmBlB;AAxzBD;;;;;;;;;;;;;;;GAeG;AACH;IA6BI;;;;;;;;;OASG;IACH,kBARW,OAAO,oBAAoB,EAAE,aAAa,WAC1C,OAAO,4BAA4B,EAAE,OAAO,gBAC5C,aAAa,kDAEb,MAAM,WACN,MAAM,YACN,OAAO,YAAY,EAAE,WAAW,EAoB1C;IARG,iDAAgB;IAOhB,uBAA0B;IAG9B;;OAEG;IACH,sDAIC;IAeD;;OAEG;IACH,mBAFW,8BAAM,QAOhB;IAqBD;;OAEG;IACH,+CAEC;IAED,yBAEC;IAED;;OAEG;IACH,wCAmCC;;CAwkBJ;qBA9vB0D,gBAAgB;sBADrD,wBAAwB;0BAEpB,qBAAqB"}
1
+ {"version":3,"file":"gridView.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/gridView.js"],"names":[],"mappings":"AAkzBA;;GAEG;AACH,+EAUC;AAED;;;;;GAKG;AACH,4CAJW,OAAO,wBAAwB,EAAE,OAAO,UACxC,OAAO,oBAAoB,EAAE,UAAU,YACvC,QAAQ,aAmBlB;AAr0BD;;;;;;;;;;;;;;;GAeG;AACH;IA6BI;;;;;;;;;OASG;IACH,kBARW,OAAO,oBAAoB,EAAE,aAAa,WAC1C,OAAO,4BAA4B,EAAE,OAAO,gBAC5C,aAAa,kDAEb,MAAM,WACN,MAAM,YACN,OAAO,YAAY,EAAE,WAAW,EAoB1C;IARG,iDAAgB;IAOhB,uBAA0B;IAG9B;;OAEG;IACH,sDAIC;IAeD;;OAEG;IACH,mBAFW,8BAAM,QAUhB;IA+BD;;OAEG;IACH,+CAEC;IAED,yBAEC;IAED;;OAEG;IACH,wCAmCC;;CAwkBJ;qBA3wB0D,gBAAgB;sBADrD,wBAAwB;0BAEpB,qBAAqB"}
@@ -118,6 +118,9 @@ export default class GridView extends ContainerView {
118
118
  * @param {View[]} views
119
119
  */
120
120
  setChildren(views) {
121
+ for (const gridChild of this.#children) {
122
+ this.#disposeGridChild(gridChild);
123
+ }
121
124
  this.#children = [];
122
125
  for (const view of views) {
123
126
  this.appendChild(view);
@@ -133,6 +136,7 @@ export default class GridView extends ContainerView {
133
136
  (gridChild) => gridChild.view == child
134
137
  );
135
138
  if (i >= 0) {
139
+ this.#disposeGridChild(this.#children[i]);
136
140
  this.#children[i] = new GridChild(
137
141
  replacement,
138
142
  this,
@@ -143,6 +147,15 @@ export default class GridView extends ContainerView {
143
147
  }
144
148
  }
145
149
 
150
+ /**
151
+ * @param {GridChild} gridChild
152
+ */
153
+ #disposeGridChild(gridChild) {
154
+ for (const view of gridChild.getChildren()) {
155
+ view.disposeSubtree();
156
+ }
157
+ }
158
+
146
159
  /**
147
160
  * Read-only view to children
148
161
  */
@@ -1,14 +1,18 @@
1
1
  export default class SelectionRect extends LayerView {
2
- /**
3
- * @typedef {import("../../spec/channel.js").PrimaryPositionalChannel} PrimaryPositionalChannel
4
- * @typedef {import("../../types/selectionTypes.js").IntervalSelection} IntervalSelection
5
- */
6
2
  /**
7
3
  * @param {import("./gridChild.js").default} gridChild
8
4
  * @param {import("../paramMediator.js").ExprRefFunction} selectionExpr
9
5
  * @param {import("../../spec/parameter.js").BrushConfig} [brushConfig]
10
6
  */
11
7
  constructor(gridChild: import("./gridChild.js").default, selectionExpr: import("../paramMediator.js").ExprRefFunction, brushConfig?: import("../../spec/parameter.js").BrushConfig);
8
+ /**
9
+ * @typedef {import("../../spec/channel.js").PrimaryPositionalChannel} PrimaryPositionalChannel
10
+ * @typedef {import("../../types/selectionTypes.js").IntervalSelection} IntervalSelection
11
+ */
12
+ /** @type {import("../paramMediator.js").ExprRefFunction} */
13
+ _selectionExpr: import("../paramMediator.js").ExprRefFunction;
14
+ /** @type {() => void} */
15
+ _selectionListener: () => void;
12
16
  }
13
17
  import LayerView from "../layerView.js";
14
18
  //# sourceMappingURL=selectionRect.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"selectionRect.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/selectionRect.js"],"names":[],"mappings":"AAGA;IACI;;;OAGG;IAEH;;;;OAIG;IACH,uBAJW,OAAO,gBAAgB,EAAE,OAAO,iBAChC,OAAO,qBAAqB,EAAE,eAAe,gBAC7C,OAAO,yBAAyB,EAAE,WAAW,EA0IvD;CACJ;sBAtJqB,iBAAiB"}
1
+ {"version":3,"file":"selectionRect.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/selectionRect.js"],"names":[],"mappings":"AAGA;IAYI;;;;OAIG;IACH,uBAJW,OAAO,gBAAgB,EAAE,OAAO,iBAChC,OAAO,qBAAqB,EAAE,eAAe,gBAC7C,OAAO,yBAAyB,EAAE,WAAW,EAqJvD;IAnKD;;;OAGG;IAEH,4DAA4D;IAC5D,gBADW,OAAO,qBAAqB,EAAE,eAAe,CACzC;IAEf,yBAAyB;IACzB,oBADW,MAAM,IAAI,CACF;CAmKtB;sBA/KqB,iBAAiB"}
@@ -7,6 +7,12 @@ export default class SelectionRect extends LayerView {
7
7
  * @typedef {import("../../types/selectionTypes.js").IntervalSelection} IntervalSelection
8
8
  */
9
9
 
10
+ /** @type {import("../paramMediator.js").ExprRefFunction} */
11
+ _selectionExpr;
12
+
13
+ /** @type {() => void} */
14
+ _selectionListener;
15
+
10
16
  /**
11
17
  * @param {import("./gridChild.js").default} gridChild
12
18
  * @param {import("../paramMediator.js").ExprRefFunction} selectionExpr
@@ -135,7 +141,10 @@ export default class SelectionRect extends LayerView {
135
141
  }
136
142
  );
137
143
 
138
- selectionExpr.addListener(() => {
144
+ /** @type {import("../paramMediator.js").ExprRefFunction} */
145
+ this._selectionExpr = selectionExpr;
146
+
147
+ this._selectionListener = () => {
139
148
  const selection =
140
149
  /** @type {import("../../types/selectionTypes.js").IntervalSelection} */ (
141
150
  selectionExpr()
@@ -143,11 +152,27 @@ export default class SelectionRect extends LayerView {
143
152
 
144
153
  const datasource =
145
154
  /** @type {import("../../data/sources/inlineSource.js").default} */ (
146
- this.context.dataFlow.findDataSourceByKey(this)
155
+ this.flowHandle?.dataSource
147
156
  );
148
157
 
158
+ if (!datasource) {
159
+ throw new Error(
160
+ "Cannot find selection rect data source handle!"
161
+ );
162
+ }
163
+
149
164
  datasource.updateDynamicData(selectionToData(selection));
150
- });
165
+ };
166
+
167
+ selectionExpr.addListener(this._selectionListener);
168
+ }
169
+
170
+ /**
171
+ * @override
172
+ */
173
+ dispose() {
174
+ this._selectionExpr.removeListener(this._selectionListener);
175
+ super.dispose();
151
176
  }
152
177
  }
153
178
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=selectionRect.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectionRect.test.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/selectionRect.test.js"],"names":[],"mappings":""}