@genome-spy/core 0.66.1 → 0.68.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/dist/bundle/index.es.js +7669 -6115
  2. package/dist/bundle/index.js +114 -133
  3. package/dist/schema.json +534 -132
  4. package/dist/src/data/collector.d.ts +20 -0
  5. package/dist/src/data/collector.d.ts.map +1 -1
  6. package/dist/src/data/collector.js +148 -0
  7. package/dist/src/data/dataFlow.d.ts +6 -0
  8. package/dist/src/data/dataFlow.d.ts.map +1 -1
  9. package/dist/src/data/dataFlow.js +10 -0
  10. package/dist/src/data/flowHandle.d.ts +2 -0
  11. package/dist/src/data/flowHandle.d.ts.map +1 -1
  12. package/dist/src/data/flowHandle.js +1 -0
  13. package/dist/src/data/flowInit.d.ts +12 -4
  14. package/dist/src/data/flowInit.d.ts.map +1 -1
  15. package/dist/src/data/flowInit.js +115 -17
  16. package/dist/src/data/flowNode.d.ts +8 -0
  17. package/dist/src/data/flowNode.d.ts.map +1 -1
  18. package/dist/src/data/flowNode.js +18 -0
  19. package/dist/src/data/keyIndex.d.ts +18 -0
  20. package/dist/src/data/keyIndex.d.ts.map +1 -0
  21. package/dist/src/data/keyIndex.js +241 -0
  22. package/dist/src/data/keyIndex.test.d.ts +2 -0
  23. package/dist/src/data/keyIndex.test.d.ts.map +1 -0
  24. package/dist/src/data/sources/dataSource.d.ts.map +1 -1
  25. package/dist/src/data/sources/dataSource.js +5 -1
  26. package/dist/src/data/sources/dataSourceFactory.d.ts +14 -12
  27. package/dist/src/data/sources/dataSourceFactory.d.ts.map +1 -1
  28. package/dist/src/data/sources/dataSourceFactory.js +52 -16
  29. package/dist/src/data/sources/lazy/mockLazySource.d.ts +29 -0
  30. package/dist/src/data/sources/lazy/mockLazySource.d.ts.map +1 -0
  31. package/dist/src/data/sources/lazy/mockLazySource.js +44 -0
  32. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +22 -1
  33. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  34. package/dist/src/data/sources/lazy/singleAxisLazySource.js +34 -2
  35. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  36. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +15 -0
  37. package/dist/src/data/sources/lazy/tabixSource.d.ts.map +1 -1
  38. package/dist/src/data/sources/lazy/tabixSource.js +15 -5
  39. package/dist/src/data/transforms/stack.d.ts.map +1 -1
  40. package/dist/src/data/transforms/stack.js +1 -0
  41. package/dist/src/encoder/accessor.d.ts +43 -0
  42. package/dist/src/encoder/accessor.d.ts.map +1 -1
  43. package/dist/src/encoder/accessor.js +164 -0
  44. package/dist/src/encoder/encoder.d.ts +11 -2
  45. package/dist/src/encoder/encoder.d.ts.map +1 -1
  46. package/dist/src/encoder/encoder.js +24 -4
  47. package/dist/src/encoder/metadataChannels.d.ts +15 -0
  48. package/dist/src/encoder/metadataChannels.d.ts.map +1 -0
  49. package/dist/src/encoder/metadataChannels.js +65 -0
  50. package/dist/src/encoder/metadataChannels.test.d.ts +2 -0
  51. package/dist/src/encoder/metadataChannels.test.d.ts.map +1 -0
  52. package/dist/src/genome/scaleLocus.d.ts.map +1 -1
  53. package/dist/src/genome/scaleLocus.js +14 -1
  54. package/dist/src/genomeSpy/containerUi.d.ts +0 -1
  55. package/dist/src/genomeSpy/containerUi.d.ts.map +1 -1
  56. package/dist/src/genomeSpy/containerUi.js +0 -14
  57. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts +3 -7
  58. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts.map +1 -1
  59. package/dist/src/genomeSpy/loadingIndicatorManager.js +68 -20
  60. package/dist/src/genomeSpy/loadingStatusRegistry.d.ts +52 -0
  61. package/dist/src/genomeSpy/loadingStatusRegistry.d.ts.map +1 -0
  62. package/dist/src/genomeSpy/loadingStatusRegistry.js +86 -0
  63. package/dist/src/genomeSpy/viewContextFactory.d.ts.map +1 -1
  64. package/dist/src/genomeSpy/viewContextFactory.js +0 -1
  65. package/dist/src/genomeSpy/viewDataInit.d.ts +10 -0
  66. package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -1
  67. package/dist/src/genomeSpy/viewDataInit.js +166 -2
  68. package/dist/src/genomeSpy/viewDataInit.test.d.ts +2 -0
  69. package/dist/src/genomeSpy/viewDataInit.test.d.ts.map +1 -0
  70. package/dist/src/genomeSpy.d.ts +1 -2
  71. package/dist/src/genomeSpy.d.ts.map +1 -1
  72. package/dist/src/genomeSpy.js +69 -27
  73. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  74. package/dist/src/gl/dataToVertices.js +16 -4
  75. package/dist/src/marks/mark.d.ts.map +1 -1
  76. package/dist/src/marks/mark.js +18 -11
  77. package/dist/src/marks/markUtils.js +1 -1
  78. package/dist/src/scale/scale.d.ts +6 -1
  79. package/dist/src/scale/scale.d.ts.map +1 -1
  80. package/dist/src/scale/scale.js +83 -23
  81. package/dist/src/scales/axisResolution.d.ts.map +1 -1
  82. package/dist/src/scales/axisResolution.js +10 -0
  83. package/dist/src/scales/{scaleDomainAggregator.d.ts → domainPlanner.d.ts} +8 -5
  84. package/dist/src/scales/domainPlanner.d.ts.map +1 -0
  85. package/dist/src/scales/domainPlanner.js +285 -0
  86. package/dist/src/scales/domainPlanner.test.d.ts +2 -0
  87. package/dist/src/scales/domainPlanner.test.d.ts.map +1 -0
  88. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
  89. package/dist/src/scales/scaleInstanceManager.js +8 -4
  90. package/dist/src/scales/scaleInteractionController.d.ts +6 -0
  91. package/dist/src/scales/scaleInteractionController.d.ts.map +1 -1
  92. package/dist/src/scales/scaleInteractionController.js +41 -3
  93. package/dist/src/scales/scaleResolution.d.ts +19 -16
  94. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  95. package/dist/src/scales/scaleResolution.js +255 -70
  96. package/dist/src/scales/scaleResolution.test.d.ts.map +1 -1
  97. package/dist/src/selection/selection.d.ts +21 -0
  98. package/dist/src/selection/selection.d.ts.map +1 -1
  99. package/dist/src/selection/selection.js +82 -0
  100. package/dist/src/spec/channel.d.ts +52 -15
  101. package/dist/src/spec/data.d.ts +4 -0
  102. package/dist/src/spec/parameter.d.ts +16 -11
  103. package/dist/src/spec/testing.d.ts +12 -0
  104. package/dist/src/spec/testing.d.ts.map +1 -0
  105. package/dist/src/spec/testing.js +20 -0
  106. package/dist/src/spec/view.d.ts +45 -10
  107. package/dist/src/styles/genome-spy.css +3 -31
  108. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  109. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  110. package/dist/src/styles/genome-spy.css.js +0 -29
  111. package/dist/src/types/encoder.d.ts +37 -2
  112. package/dist/src/types/rendering.d.ts +4 -3
  113. package/dist/src/types/viewContext.d.ts +0 -14
  114. package/dist/src/utils/domainArray.d.ts.map +1 -1
  115. package/dist/src/utils/domainArray.js +3 -0
  116. package/dist/src/utils/indexer.d.ts +3 -0
  117. package/dist/src/utils/indexer.d.ts.map +1 -1
  118. package/dist/src/utils/indexer.js +3 -0
  119. package/dist/src/utils/throttle.d.ts +4 -1
  120. package/dist/src/utils/throttle.d.ts.map +1 -1
  121. package/dist/src/utils/throttle.js +54 -23
  122. package/dist/src/utils/throttle.test.d.ts +2 -0
  123. package/dist/src/utils/throttle.test.d.ts.map +1 -0
  124. package/dist/src/utils/transition.d.ts +21 -0
  125. package/dist/src/utils/transition.d.ts.map +1 -1
  126. package/dist/src/utils/transition.js +28 -0
  127. package/dist/src/utils/ui/tooltip.d.ts.map +1 -1
  128. package/dist/src/utils/ui/tooltip.js +7 -1
  129. package/dist/src/utils/ui/tooltip.test.d.ts +2 -0
  130. package/dist/src/utils/ui/tooltip.test.d.ts.map +1 -0
  131. package/dist/src/view/axisGridView.d.ts.map +1 -1
  132. package/dist/src/view/axisGridView.js +22 -5
  133. package/dist/src/view/axisView.d.ts.map +1 -1
  134. package/dist/src/view/axisView.js +20 -5
  135. package/dist/src/view/concatView.js +3 -3
  136. package/dist/src/view/containerMutationHelper.d.ts.map +1 -1
  137. package/dist/src/view/containerMutationHelper.js +6 -2
  138. package/dist/src/view/containerView.d.ts +9 -5
  139. package/dist/src/view/containerView.d.ts.map +1 -1
  140. package/dist/src/view/containerView.js +34 -9
  141. package/dist/src/view/dataReadiness.d.ts +46 -0
  142. package/dist/src/view/dataReadiness.d.ts.map +1 -0
  143. package/dist/src/view/dataReadiness.js +267 -0
  144. package/dist/src/view/dataReadiness.test.d.ts +2 -0
  145. package/dist/src/view/dataReadiness.test.d.ts.map +1 -0
  146. package/dist/src/view/facetView.d.ts.map +1 -1
  147. package/dist/src/view/facetView.js +7 -5
  148. package/dist/src/view/flowBuilder.d.ts +5 -3
  149. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  150. package/dist/src/view/flowBuilder.js +74 -7
  151. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  152. package/dist/src/view/gridView/gridChild.js +8 -0
  153. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  154. package/dist/src/view/gridView/gridView.js +119 -2
  155. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  156. package/dist/src/view/gridView/scrollbar.js +3 -0
  157. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  158. package/dist/src/view/gridView/selectionRect.js +20 -5
  159. package/dist/src/view/gridView/separatorView.d.ts +51 -0
  160. package/dist/src/view/gridView/separatorView.d.ts.map +1 -0
  161. package/dist/src/view/gridView/separatorView.js +275 -0
  162. package/dist/src/view/layerView.js +3 -3
  163. package/dist/src/view/layout/flexLayout.d.ts +0 -30
  164. package/dist/src/view/layout/flexLayout.d.ts.map +1 -1
  165. package/dist/src/view/layout/flexLayout.js +0 -86
  166. package/dist/src/view/paramMediator.d.ts +19 -0
  167. package/dist/src/view/paramMediator.d.ts.map +1 -1
  168. package/dist/src/view/paramMediator.js +86 -19
  169. package/dist/src/view/testUtils.d.ts.map +1 -1
  170. package/dist/src/view/testUtils.js +11 -1
  171. package/dist/src/view/unitView.d.ts +8 -13
  172. package/dist/src/view/unitView.d.ts.map +1 -1
  173. package/dist/src/view/unitView.js +127 -43
  174. package/dist/src/view/view.d.ts +34 -14
  175. package/dist/src/view/view.d.ts.map +1 -1
  176. package/dist/src/view/view.js +119 -9
  177. package/dist/src/view/viewFactory.d.ts.map +1 -1
  178. package/dist/src/view/viewFactory.js +20 -1
  179. package/dist/src/view/viewSelectors.d.ts +148 -0
  180. package/dist/src/view/viewSelectors.d.ts.map +1 -0
  181. package/dist/src/view/viewSelectors.js +773 -0
  182. package/dist/src/view/viewSelectors.test.d.ts +2 -0
  183. package/dist/src/view/viewSelectors.test.d.ts.map +1 -0
  184. package/dist/src/view/viewUtils.d.ts +0 -8
  185. package/dist/src/view/viewUtils.d.ts.map +1 -1
  186. package/dist/src/view/viewUtils.js +1 -21
  187. package/package.json +3 -3
  188. package/dist/src/scales/scaleDomainAggregator.d.ts.map +0 -1
  189. package/dist/src/scales/scaleDomainAggregator.js +0 -162
  190. package/dist/src/scales/scaleDomainAggregator.test.d.ts +0 -2
  191. package/dist/src/scales/scaleDomainAggregator.test.d.ts.map +0 -1
@@ -83,6 +83,7 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
83
83
 
84
84
  this.#lastDomain = [0, 0];
85
85
  this.#lastQuantizedInterval = [0, 0];
86
+ this._lastLoadedDomain = undefined;
86
87
 
87
88
  this.onDomainChanged(domain);
88
89
  }
@@ -97,6 +98,19 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
97
98
  // Override me if needed
98
99
  }
99
100
 
101
+ /**
102
+ * @param {import("../../flowNode.js").Datum[][]} chunks
103
+ * @protected
104
+ */
105
+ publishData(chunks) {
106
+ // Preserve window coverage; base publishData would overwrite it with the current scale domain.
107
+ const loadedDomain = this._lastLoadedDomain;
108
+ super.publishData(chunks);
109
+ if (loadedDomain) {
110
+ this._lastLoadedDomain = loadedDomain;
111
+ }
112
+ }
113
+
100
114
  /**
101
115
  * Splits the interval into discrete chromosomal intervals – one for each chromosome –
102
116
  * and loads the data for each of them. Handles abort signals and errors.
@@ -134,6 +148,7 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
134
148
 
135
149
  if (!signal.aborted) {
136
150
  this.setLoadingStatus("complete");
151
+ this._lastLoadedDomain = Array.from(interval);
137
152
  return resultByChrom;
138
153
  }
139
154
  } catch (e) {
@@ -1 +1 @@
1
- {"version":3,"file":"tabixSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/tabixSource.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH,iCAHa,CAAC;IAOV;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,SAAS,QACzC,OAAO,uBAAuB,EAAE,OAAO,EAkDjD;IAnCG,kDAAgC;IAQhC,iCA0BE;IAqCN;;;OAGG;IACH,gCAHW,MAAM,iBAKhB;IAED;;;;;OAKG;IACH,gCAHW,MAAM,EAAE,GACN,CAAC,EAAE,CAKf;;CACJ;qCApHoC,+BAA+B"}
1
+ {"version":3,"file":"tabixSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/tabixSource.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH,iCAHa,CAAC;IAOV;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,SAAS,QACzC,OAAO,uBAAuB,EAAE,OAAO,EA4DjD;IA7CG,kDAAgC;IAQhC,iCAoCE;IAqCN;;;OAGG;IACH,gCAHW,MAAM,iBAKhB;IAED;;;;;OAKG;IACH,gCAHW,MAAM,EAAE,GACN,CAAC,EAAE,CAKf;;CACJ;qCA9HoC,+BAA+B"}
@@ -34,7 +34,7 @@ export default class TabixSource extends SingleAxisWindowedSource {
34
34
 
35
35
  this.setupDebouncing(this.params);
36
36
 
37
- this.initializedPromise = new Promise((resolve) => {
37
+ this.initializedPromise = new Promise((resolve, reject) => {
38
38
  Promise.all([
39
39
  import("@gmod/tabix"),
40
40
  import("generic-filehandle2"),
@@ -55,10 +55,20 @@ export default class TabixSource extends SingleAxisWindowedSource {
55
55
  : undefined,
56
56
  });
57
57
 
58
- const header = await this.#tbiIndex.getHeader();
59
- await this._handleHeader(header);
60
-
61
- resolve();
58
+ try {
59
+ this.setLoadingStatus("loading");
60
+ const header = await this.#tbiIndex.getHeader();
61
+ await this._handleHeader(header);
62
+ this.setLoadingStatus("complete");
63
+ resolve();
64
+ } catch (e) {
65
+ this.load();
66
+ this.setLoadingStatus(
67
+ "error",
68
+ `${this.params.url}: ${e.message}`
69
+ );
70
+ reject(e);
71
+ }
62
72
  });
63
73
  });
64
74
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../../../src/data/transforms/stack.js"],"names":[],"mappings":"AAMA;IAKI;;OAEG;IACH,oBAFW,OAAO,yBAAyB,EAAE,WAAW,EAQvD;IAJG,sDAAoB;IAEpB,oBAAoB;IACpB,QADW,GAAG,EAAE,CACA;CAmHvB;sBAlIqB,gBAAgB"}
1
+ {"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../../../src/data/transforms/stack.js"],"names":[],"mappings":"AAMA;IAKI;;OAEG;IACH,oBAFW,OAAO,yBAAyB,EAAE,WAAW,EAQvD;IAJG,sDAAoB;IAEpB,oBAAoB;IACpB,QADW,GAAG,EAAE,CACA;CAoHvB;sBAnIqB,gBAAgB"}
@@ -21,6 +21,7 @@ export default class StackTransform extends Transform {
21
21
  }
22
22
 
23
23
  reset() {
24
+ super.reset();
24
25
  this.buffer = [];
25
26
  }
26
27
 
@@ -15,4 +15,47 @@ export function createAccessor(channel: import("../spec/channel.js").Channel, ch
15
15
  * @param {import("../view/paramMediator.js").default} paramMediator
16
16
  */
17
17
  export function createConditionalAccessors(channel: import("../spec/channel.js").Channel, channelDef: import("../spec/channel.js").ChannelDef, paramMediator: import("../view/paramMediator.js").default): import("../types/encoder.js").Accessor<import("../spec/channel.js").Scalar>[];
18
+ /**
19
+ * @param {import("../types/encoder.js").Accessor} accessor
20
+ * @returns {accessor is import("../types/encoder.js").ScaleAccessor}
21
+ */
22
+ export function isScaleAccessor(accessor: import("../types/encoder.js").Accessor): accessor is import("../types/encoder.js").ScaleAccessor;
23
+ /**
24
+ * Builds domain key strings in the format:
25
+ * - domainKeyBase: <scaleChannel>|<kind>|<value>
26
+ * - domainKey: <type>|<domainKeyBase>
27
+ *
28
+ * @param {object} options
29
+ * @param {import("../spec/channel.js").ChannelWithScale} options.scaleChannel
30
+ * @param {DomainKeySource} options.source
31
+ * @param {import("../spec/channel.js").Type} [options.type]
32
+ * @returns {{ domainKeyBase: string, domainKey?: string }}
33
+ */
34
+ export function buildDomainKey({ scaleChannel, source, type }: {
35
+ scaleChannel: import("../spec/channel.js").ChannelWithScale;
36
+ source: DomainKeySource;
37
+ type?: import("../spec/channel.js").Type;
38
+ }): {
39
+ domainKeyBase: string;
40
+ domainKey?: string;
41
+ };
42
+ /**
43
+ * @param {import("../types/encoder.js").ScaleAccessor} accessor
44
+ * @param {import("../spec/channel.js").Type} type
45
+ * @returns {string}
46
+ */
47
+ export function getAccessorDomainKey(accessor: import("../types/encoder.js").ScaleAccessor, type: import("../spec/channel.js").Type): string;
48
+ export type DomainKeySource = {
49
+ kind: "field";
50
+ value: string;
51
+ } | {
52
+ kind: "expr";
53
+ value: string;
54
+ } | {
55
+ kind: "datum";
56
+ value: import("../spec/channel.js").Scalar | import("../spec/parameter.js").ExprRef;
57
+ } | {
58
+ kind: "value";
59
+ value: import("../spec/channel.js").Scalar | import("../spec/parameter.js").ExprRef;
60
+ };
18
61
  //# sourceMappingURL=accessor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"accessor.d.ts","sourceRoot":"","sources":["../../../src/encoder/accessor.js"],"names":[],"mappings":"AAaA;;;;;GAKG;AACH,wCALW,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,oBAAoB,EAAE,UAAU,GAAG,OAAO,oBAAoB,EAAE,WAAW,CAAC,OAAO,oBAAoB,EAAE,UAAU,CAAC,iBAC3H,OAAO,0BAA0B,EAAE,OAAO,GACxC,OAAO,qBAAqB,EAAE,QAAQ,CA+FlD;AAED;;;;;;;;GAQG;AACH,oDAJW,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,oBAAoB,EAAE,UAAU,iBACvC,OAAO,0BAA0B,EAAE,OAAO,iFAgCpD"}
1
+ {"version":3,"file":"accessor.d.ts","sourceRoot":"","sources":["../../../src/encoder/accessor.js"],"names":[],"mappings":"AAaA;;;;;GAKG;AACH,wCALW,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,oBAAoB,EAAE,UAAU,GAAG,OAAO,oBAAoB,EAAE,WAAW,CAAC,OAAO,oBAAoB,EAAE,UAAU,CAAC,iBAC3H,OAAO,0BAA0B,EAAE,OAAO,GACxC,OAAO,qBAAqB,EAAE,QAAQ,CAmHlD;AAED;;;;;;;;GAQG;AACH,oDAJW,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,oBAAoB,EAAE,UAAU,iBACvC,OAAO,0BAA0B,EAAE,OAAO,iFAgCpD;AAED;;;GAGG;AACH,0CAHW,OAAO,qBAAqB,EAAE,QAAQ,GACpC,QAAQ,IAAI,OAAO,qBAAqB,EAAE,aAAa,CAInE;AA6DD;;;;;;;;;;GAUG;AACH,+DALG;IAA+D,YAAY,EAAnE,OAAO,oBAAoB,EAAE,gBAAgB;IACpB,MAAM,EAA/B,eAAe;IAC6B,IAAI,GAAhD,OAAO,oBAAoB,EAAE,IAAI;CACzC,GAAU;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAYzD;AAED;;;;GAIG;AACH,+CAJW,OAAO,qBAAqB,EAAE,aAAa,QAC3C,OAAO,oBAAoB,EAAE,IAAI,GAC/B,MAAM,CAgBlB;8BApGY;IACN,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACjB,GAAG;IACA,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB,GAAG;IACA,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,oBAAoB,EAAE,MAAM,GAAG,OAAO,sBAAsB,EAAE,OAAO,CAAC;CACvF,GAAG;IACA,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,oBAAoB,EAAE,MAAM,GAAG,OAAO,sBAAsB,EAAE,OAAO,CAAC;CACvF"}
@@ -38,6 +38,7 @@ export function createAccessor(channel, channelDef, paramMediator) {
38
38
  a.constant = a.fields.length === 0;
39
39
  a.channelDef = channelDef;
40
40
  a.channel = channel;
41
+ a.sourceKey = buildAccessorSourceKey(channelDef);
41
42
 
42
43
  a.scaleChannel =
43
44
  ((isChannelDefWithScale(channelDef) &&
@@ -45,6 +46,13 @@ export function createAccessor(channel, channelDef, paramMediator) {
45
46
  (isChannelWithScale(channel) && channel)) ||
46
47
  undefined;
47
48
 
49
+ if (a.scaleChannel !== undefined) {
50
+ a.domainKeyBase = buildDomainKey({
51
+ scaleChannel: a.scaleChannel,
52
+ source: getDomainKeySource(channelDef),
53
+ }).domainKeyBase;
54
+ }
55
+
48
56
  if ("param" in channelDef) {
49
57
  // TODO: Figure out how to fix it. Interval selection depends on FIELDS!
50
58
  /*
@@ -62,6 +70,18 @@ export function createAccessor(channel, channelDef, paramMediator) {
62
70
  a.predicate.empty = false;
63
71
  }
64
72
 
73
+ a.equals = (other) => {
74
+ if (!other) {
75
+ return false;
76
+ } else {
77
+ return (
78
+ a === other ||
79
+ (a.sourceKey !== undefined &&
80
+ a.sourceKey === other.sourceKey)
81
+ );
82
+ }
83
+ };
84
+
65
85
  a.asNumberAccessor = () =>
66
86
  /** @type {import("../types/encoder.js").Accessor<number>} */ (a);
67
87
 
@@ -152,3 +172,147 @@ export function createConditionalAccessors(channel, channelDef, paramMediator) {
152
172
  }
153
173
  return conditionalAccessors;
154
174
  }
175
+
176
+ /**
177
+ * @param {import("../types/encoder.js").Accessor} accessor
178
+ * @returns {accessor is import("../types/encoder.js").ScaleAccessor}
179
+ */
180
+ export function isScaleAccessor(accessor) {
181
+ return accessor.scaleChannel !== undefined;
182
+ }
183
+
184
+ /**
185
+ * @typedef {{
186
+ * kind: "field",
187
+ * value: string,
188
+ * } | {
189
+ * kind: "expr",
190
+ * value: string,
191
+ * } | {
192
+ * kind: "datum",
193
+ * value: import("../spec/channel.js").Scalar | import("../spec/parameter.js").ExprRef,
194
+ * } | {
195
+ * kind: "value",
196
+ * value: import("../spec/channel.js").Scalar | import("../spec/parameter.js").ExprRef,
197
+ * }} DomainKeySource
198
+ */
199
+
200
+ /**
201
+ * @param {import("../spec/channel.js").ChannelDef} channelDef
202
+ * @returns {DomainKeySource}
203
+ */
204
+ function getDomainKeySource(channelDef) {
205
+ if (isFieldDef(channelDef)) {
206
+ return { kind: "field", value: channelDef.field };
207
+ }
208
+
209
+ if (isExprDef(channelDef)) {
210
+ return { kind: "expr", value: channelDef.expr };
211
+ }
212
+
213
+ if (isDatumDef(channelDef)) {
214
+ return { kind: "datum", value: channelDef.datum };
215
+ }
216
+
217
+ if (isValueDef(channelDef)) {
218
+ return { kind: "value", value: channelDef.value };
219
+ }
220
+
221
+ throw new Error(
222
+ "Cannot derive a domain key from channel definition: " +
223
+ JSON.stringify(channelDef)
224
+ );
225
+ }
226
+
227
+ /**
228
+ * Builds a key for accessor equality. This is a structural heuristic based on
229
+ * the data source definition and ignores channel, predicate, and scale.
230
+ *
231
+ * @param {import("../spec/channel.js").ChannelDef} channelDef
232
+ * @returns {string}
233
+ */
234
+ function buildAccessorSourceKey(channelDef) {
235
+ const source = getDomainKeySource(channelDef);
236
+ if (source.kind === "datum" || source.kind === "value") {
237
+ return "constant|" + stringifyDomainValue(source.value);
238
+ }
239
+
240
+ return source.kind + "|" + stringifyDomainSource(source);
241
+ }
242
+
243
+ /**
244
+ * Builds domain key strings in the format:
245
+ * - domainKeyBase: <scaleChannel>|<kind>|<value>
246
+ * - domainKey: <type>|<domainKeyBase>
247
+ *
248
+ * @param {object} options
249
+ * @param {import("../spec/channel.js").ChannelWithScale} options.scaleChannel
250
+ * @param {DomainKeySource} options.source
251
+ * @param {import("../spec/channel.js").Type} [options.type]
252
+ * @returns {{ domainKeyBase: string, domainKey?: string }}
253
+ */
254
+ export function buildDomainKey({ scaleChannel, source, type }) {
255
+ if (!scaleChannel) {
256
+ throw new Error("Cannot build a domain key without a scale channel.");
257
+ }
258
+
259
+ const domainKeyBase =
260
+ scaleChannel + "|" + source.kind + "|" + stringifyDomainSource(source);
261
+ const domainKey = type ? type + "|" + domainKeyBase : undefined;
262
+
263
+ return { domainKeyBase, domainKey };
264
+ }
265
+
266
+ /**
267
+ * @param {import("../types/encoder.js").ScaleAccessor} accessor
268
+ * @param {import("../spec/channel.js").Type} type
269
+ * @returns {string}
270
+ */
271
+ export function getAccessorDomainKey(accessor, type) {
272
+ const { domainKey, domainKeyBase } = buildDomainKey({
273
+ scaleChannel: accessor.scaleChannel,
274
+ source: getDomainKeySource(accessor.channelDef),
275
+ type,
276
+ });
277
+ if (!domainKey) {
278
+ throw new Error(
279
+ "Cannot finalize a domain key without a resolved type."
280
+ );
281
+ }
282
+ accessor.domainKeyBase = domainKeyBase;
283
+ accessor.domainKey = domainKey;
284
+ return domainKey;
285
+ }
286
+
287
+ /**
288
+ * @param {DomainKeySource} source
289
+ * @returns {string}
290
+ */
291
+ function stringifyDomainSource(source) {
292
+ switch (source.kind) {
293
+ case "field":
294
+ case "expr":
295
+ return source.value;
296
+ case "datum":
297
+ case "value":
298
+ return stringifyDomainValue(source.value);
299
+ default:
300
+ throw new Error("Unknown domain key source.");
301
+ }
302
+ }
303
+
304
+ /**
305
+ * @param {import("../spec/channel.js").Scalar | import("../spec/parameter.js").ExprRef} value
306
+ * @returns {string}
307
+ */
308
+ function stringifyDomainValue(value) {
309
+ if (isExprRef(value)) {
310
+ return "expr:" + value.expr;
311
+ }
312
+
313
+ if (value === undefined) {
314
+ return "undefined";
315
+ }
316
+
317
+ return JSON.stringify(value);
318
+ }
@@ -8,6 +8,15 @@
8
8
  * @returns {Partial<Record<Channel, Encoder>>}
9
9
  */
10
10
  export default function createEncoders(unitView: import("../view/unitView.js").default, encoding: import("../spec/channel.js").Encoding): Partial<Record<import("../spec/channel.js").Channel, import("../types/encoder.js").Encoder>>;
11
+ /**
12
+ * Channels that are present in encoding but are not direct mark properties.
13
+ * Keep this centralized so metadata channels (for example tooltip) can reuse
14
+ * the same handling path.
15
+ *
16
+ * @param {import("../spec/channel.js").Channel} channel
17
+ * @returns {boolean}
18
+ */
19
+ export function isNonMarkPropertyChannel(channel: import("../spec/channel.js").Channel): boolean;
11
20
  /**
12
21
  * @param {import("../types/encoder.js").Accessor[]} accessors
13
22
  * @param {(channel: import("../spec/channel.js").ChannelWithScale) => import("../types/encoder.js").VegaScale} scaleSource
@@ -45,12 +54,12 @@ export function isChannelDefWithScale(channelDef: import("../spec/channel.js").C
45
54
  /**
46
55
  * @param {import("../spec/channel.js").ChannelDef} channelDef
47
56
  */
48
- export function findChannelDefWithScale(channelDef: import("../spec/channel.js").ChannelDef): import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, string> | import("../spec/channel.js").PositionFieldDef | import("../spec/channel.js").PositionDatumDef | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, number> | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").FieldDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").DatumDef<import("../spec/parameter.js").ExprRef | import("../spec/channel.js").Scalar> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").ValueDefBase<string | import("../spec/parameter.js").ExprRef> & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").ValueDefBase<number | import("../spec/parameter.js").ExprRef> & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>);
57
+ export function findChannelDefWithScale(channelDef: import("../spec/channel.js").ChannelDef): import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, string> | import("../spec/channel.js").PositionFieldDef | import("../spec/channel.js").PositionDatumDef | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, number> | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").FieldDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").DatumDef<import("../spec/parameter.js").ExprRef | import("../spec/channel.js").Scalar> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").DomainContributionMixins) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").ValueDefBase<string | import("../spec/parameter.js").ExprRef> & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").DomainContributionMixins) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").ValueDefBase<number | import("../spec/parameter.js").ExprRef> & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").DomainContributionMixins);
49
58
  /**
50
59
  * @param {import("../view/unitView.js").default} view
51
60
  * @param {import("../spec/channel.js").Channel} channel
52
61
  */
53
- export function getChannelDefWithScale(view: import("../view/unitView.js").default, channel: import("../spec/channel.js").Channel): import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, string> | import("../spec/channel.js").PositionFieldDef | import("../spec/channel.js").PositionDatumDef | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, number> | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").TypeForShape>, string> | (import("../spec/channel.js").FieldDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").DatumDef<import("../spec/parameter.js").ExprRef | import("../spec/channel.js").Scalar> & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ChromPosDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").TypeMixins<"locus"> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").XIndexDef);
62
+ export function getChannelDefWithScale(view: import("../view/unitView.js").default, channel: import("../spec/channel.js").Channel): import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, string> | import("../spec/channel.js").PositionFieldDef | import("../spec/channel.js").PositionDatumDef | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, number> | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").TypeForShape>, string> | (import("../spec/channel.js").FieldDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").DatumDef<import("../spec/parameter.js").ExprRef | import("../spec/channel.js").Scalar> & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ChromPosDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").TypeMixins<"locus"> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").XIndexDef);
54
63
  /**
55
64
  * @param {import("../spec/channel.js").ChannelDef} channelDef
56
65
  * @returns {channelDef is import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>}
@@ -1 +1 @@
1
- {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/encoder/encoder.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/encoder/encoder.js"],"names":[],"mappings":"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"}
@@ -82,10 +82,18 @@ export default function createEncoders(unitView, encoding) {
82
82
  continue;
83
83
  }
84
84
 
85
- encoders[channel] = createSimpleOrConditionalEncoder(
85
+ /** @type {Channel} */
86
+ const typedChannel = /** @type {Channel} */ (channel);
87
+ if (isNonMarkPropertyChannel(typedChannel)) {
88
+ continue;
89
+ }
90
+
91
+ const typedChannelDef =
92
+ /** @type {import("../spec/channel.js").ChannelDef} */ (channelDef);
93
+ encoders[typedChannel] = createSimpleOrConditionalEncoder(
86
94
  createConditionalAccessors(
87
- channel,
88
- channelDef,
95
+ typedChannel,
96
+ typedChannelDef,
89
97
  unitView.paramMediator
90
98
  ),
91
99
  scaleSource
@@ -95,6 +103,18 @@ export default function createEncoders(unitView, encoding) {
95
103
  return encoders;
96
104
  }
97
105
 
106
+ /**
107
+ * Channels that are present in encoding but are not direct mark properties.
108
+ * Keep this centralized so metadata channels (for example tooltip) can reuse
109
+ * the same handling path.
110
+ *
111
+ * @param {import("../spec/channel.js").Channel} channel
112
+ * @returns {boolean}
113
+ */
114
+ export function isNonMarkPropertyChannel(channel) {
115
+ return channel === "key" || channel === "search";
116
+ }
117
+
98
118
  /**
99
119
  * @param {import("../types/encoder.js").Accessor[]} accessors
100
120
  * @param {(channel: import("../spec/channel.js").ChannelWithScale) => import("../types/encoder.js").VegaScale} scaleSource
@@ -237,7 +257,7 @@ export function findChannelDefWithScale(channelDef) {
237
257
  */
238
258
  export function getChannelDefWithScale(view, channel) {
239
259
  const channelDef = view.mark.encoding[channel];
240
- if (isChannelDefWithScale(channelDef)) {
260
+ if (!Array.isArray(channelDef) && isChannelDefWithScale(channelDef)) {
241
261
  return channelDef;
242
262
  } else {
243
263
  throw new Error("Not a channel def with scale!");
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Returns key fields used for point selections, if configured.
3
+ *
4
+ * @param {import("../spec/channel.js").Encoding} encoding
5
+ * @returns {string[] | undefined}
6
+ */
7
+ export function getEncodingKeyFields(encoding: import("../spec/channel.js").Encoding): string[] | undefined;
8
+ /**
9
+ * Returns search fields configured in encoding.search, if any.
10
+ *
11
+ * @param {import("../spec/channel.js").Encoding} encoding
12
+ * @returns {string[] | undefined}
13
+ */
14
+ export function getEncodingSearchFields(encoding: import("../spec/channel.js").Encoding): string[] | undefined;
15
+ //# sourceMappingURL=metadataChannels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadataChannels.d.ts","sourceRoot":"","sources":["../../../src/encoder/metadataChannels.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,+CAHW,OAAO,oBAAoB,EAAE,QAAQ,GACnC,MAAM,EAAE,GAAG,SAAS,CAIhC;AAED;;;;;GAKG;AACH,kDAHW,OAAO,oBAAoB,EAAE,QAAQ,GACnC,MAAM,EAAE,GAAG,SAAS,CAIhC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Returns key fields used for point selections, if configured.
3
+ *
4
+ * @param {import("../spec/channel.js").Encoding} encoding
5
+ * @returns {string[] | undefined}
6
+ */
7
+ export function getEncodingKeyFields(encoding) {
8
+ return getNormalizedFieldsFromChannel(encoding?.key, "key");
9
+ }
10
+
11
+ /**
12
+ * Returns search fields configured in encoding.search, if any.
13
+ *
14
+ * @param {import("../spec/channel.js").Encoding} encoding
15
+ * @returns {string[] | undefined}
16
+ */
17
+ export function getEncodingSearchFields(encoding) {
18
+ return getNormalizedFieldsFromChannel(encoding?.search, "search");
19
+ }
20
+
21
+ /**
22
+ * @param {import("../spec/channel.js").FieldDefWithoutScale | import("../spec/channel.js").FieldDefWithoutScale[] | undefined} channelDef
23
+ * @param {"key" | "search"} channelName
24
+ * @returns {string[] | undefined}
25
+ */
26
+ function getNormalizedFieldsFromChannel(channelDef, channelName) {
27
+ if (!channelDef) {
28
+ return;
29
+ }
30
+
31
+ const definitions = Array.isArray(channelDef) ? channelDef : [channelDef];
32
+ if (definitions.length === 0) {
33
+ throw new Error(
34
+ "The " + channelName + " channel array must not be empty."
35
+ );
36
+ }
37
+
38
+ /** @type {string[]} */
39
+ const fields = [];
40
+ for (const definition of definitions) {
41
+ if (
42
+ !definition ||
43
+ typeof definition !== "object" ||
44
+ !("field" in definition)
45
+ ) {
46
+ throw new Error(
47
+ "The " +
48
+ channelName +
49
+ " channel must be a field definition or an array of field definitions."
50
+ );
51
+ }
52
+
53
+ const fieldName = definition.field;
54
+ if (typeof fieldName !== "string") {
55
+ throw new Error(
56
+ "The " +
57
+ channelName +
58
+ " channel field definition must include a string field name."
59
+ );
60
+ }
61
+ fields.push(fieldName);
62
+ }
63
+
64
+ return fields;
65
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=metadataChannels.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadataChannels.test.d.ts","sourceRoot":"","sources":["../../../src/encoder/metadataChannels.test.js"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"scaleLocus.d.ts","sourceRoot":"","sources":["../../../src/genome/scaleLocus.js"],"names":[],"mappings":"AAMA,2EAyFC;;AASD;;;;GAIG;AACH,8CAJW,OAAO,aAAa,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,OAAO,aAAa,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,SAC5F,MAAM,GACJ,MAAM,GAAG,OAAO,aAAa,EAAE,gBAAgB,CAK3D;AAED;;;;GAIG;AACH,gDAJW,OAAO,aAAa,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,OAAO,aAAa,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,WAC5F,MAAM,GAAG,OAAO,aAAa,EAAE,gBAAgB,GAC7C,MAAM,CAQlB;AAED;;;;GAIG;AACH,mDAJW,OAAO,aAAa,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,OAAO,aAAa,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,YAC5F,OAAO,kBAAkB,EAAE,YAAY,GAAG,OAAO,kBAAkB,EAAE,aAAa,GAChF,MAAM,EAAE,CAQpB;AAED;;;;GAIG;AACH,iDAJW,OAAO,aAAa,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,OAAO,aAAa,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,YAC5F,OAAO,kBAAkB,EAAE,YAAY,GAAG,OAAO,kBAAkB,EAAE,aAAa,GAChF,OAAO,kBAAkB,EAAE,YAAY,GAAG,OAAO,kBAAkB,EAAE,aAAa,CAO9F;AAED;;;GAGG;AACH,+CAHW,OAAO,aAAa,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,OAAO,aAAa,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,GAC1F,MAAM,EAAE,CAQpB"}
1
+ {"version":3,"file":"scaleLocus.d.ts","sourceRoot":"","sources":["../../../src/genome/scaleLocus.js"],"names":[],"mappings":"AAMA,2EAsGC;;AASD;;;;GAIG;AACH,8CAJW,OAAO,aAAa,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,OAAO,aAAa,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,SAC5F,MAAM,GACJ,MAAM,GAAG,OAAO,aAAa,EAAE,gBAAgB,CAK3D;AAED;;;;GAIG;AACH,gDAJW,OAAO,aAAa,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,OAAO,aAAa,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,WAC5F,MAAM,GAAG,OAAO,aAAa,EAAE,gBAAgB,GAC7C,MAAM,CAQlB;AAED;;;;GAIG;AACH,mDAJW,OAAO,aAAa,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,OAAO,aAAa,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,YAC5F,OAAO,kBAAkB,EAAE,YAAY,GAAG,OAAO,kBAAkB,EAAE,aAAa,GAChF,MAAM,EAAE,CAQpB;AAED;;;;GAIG;AACH,iDAJW,OAAO,aAAa,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,OAAO,aAAa,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,YAC5F,OAAO,kBAAkB,EAAE,YAAY,GAAG,OAAO,kBAAkB,EAAE,aAAa,GAChF,OAAO,kBAAkB,EAAE,YAAY,GAAG,OAAO,kBAAkB,EAAE,aAAa,CAO9F;AAED;;;GAGG;AACH,+CAHW,OAAO,aAAa,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,OAAO,aAAa,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,GAC1F,MAAM,EAAE,CAQpB"}
@@ -90,7 +90,20 @@ export default function scaleLocus() {
90
90
 
91
91
  const originalCopy = scale.copy;
92
92
 
93
- scale.copy = () => originalCopy().genome(genome);
93
+ scale.copy = () => {
94
+ const copied = originalCopy();
95
+ let copiedGenome = genome;
96
+ // @ts-expect-error
97
+ copied.genome = function (_) {
98
+ if (arguments.length) {
99
+ copiedGenome = _;
100
+ return copied;
101
+ } else {
102
+ return copiedGenome;
103
+ }
104
+ };
105
+ return copied.genome(genome);
106
+ };
94
107
 
95
108
  return scale;
96
109
  }
@@ -3,7 +3,6 @@
3
3
  */
4
4
  export function createContainerUi(container: HTMLElement): {
5
5
  canvasWrapper: HTMLElement;
6
- loadingMessageElement: HTMLElement;
7
6
  loadingIndicatorsElement: HTMLElement;
8
7
  tooltip: Tooltip;
9
8
  styleElement: HTMLStyleElement;
@@ -1 +1 @@
1
- {"version":3,"file":"containerUi.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/containerUi.js"],"names":[],"mappings":"AAGA;;GAEG;AACH,6CAFW,WAAW;;;;;;EA2CrB;AAED;;;GAGG;AACH,4CAHW,WAAW,WACX,MAAM,QAUhB;oBA5DmB,wBAAwB"}
1
+ {"version":3,"file":"containerUi.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/containerUi.js"],"names":[],"mappings":"AAGA;;GAEG;AACH,6CAFW,WAAW;;;;;EA6BrB;AAED;;;GAGG;AACH,4CAHW,WAAW,WACX,MAAM,QAUhB;oBA9CmB,wBAAwB"}
@@ -18,12 +18,6 @@ export function createContainerUi(container) {
18
18
 
19
19
  canvasWrapper.classList.add("loading");
20
20
 
21
- const loadingMessageElement = element("div", {
22
- class: "loading-message",
23
- innerHTML: `<div class="message">Loading<span class="ellipsis">...</span></div>`,
24
- });
25
- canvasWrapper.appendChild(loadingMessageElement);
26
-
27
21
  const loadingIndicatorsElement = element("div", {
28
22
  class: "loading-indicators",
29
23
  });
@@ -31,16 +25,8 @@ export function createContainerUi(container) {
31
25
 
32
26
  const tooltip = new Tooltip(container);
33
27
 
34
- loadingMessageElement
35
- .querySelector(".message")
36
- .addEventListener("transitionend", () => {
37
- /** @type {HTMLElement} */ (loadingMessageElement).style.display =
38
- "none";
39
- });
40
-
41
28
  return {
42
29
  canvasWrapper,
43
- loadingMessageElement,
44
30
  loadingIndicatorsElement,
45
31
  tooltip,
46
32
  styleElement,
@@ -1,14 +1,10 @@
1
1
  export default class LoadingIndicatorManager {
2
2
  /**
3
3
  * @param {HTMLElement} loadingIndicatorsElement
4
+ * @param {import("./loadingStatusRegistry.js").default} loadingStatusRegistry
4
5
  */
5
- constructor(loadingIndicatorsElement: HTMLElement);
6
- /**
7
- * @param {import("../view/view.js").default} view
8
- * @param {import("../types/viewContext.js").DataLoadingStatus} status
9
- * @param {string} [detail]
10
- */
11
- setDataLoadingStatus(view: import("../view/view.js").default, status: import("../types/viewContext.js").DataLoadingStatus, detail?: string): void;
6
+ constructor(loadingIndicatorsElement: HTMLElement, loadingStatusRegistry: import("./loadingStatusRegistry.js").default);
7
+ destroy(): void;
12
8
  updateLayout(): void;
13
9
  #private;
14
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"loadingIndicatorManager.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/loadingIndicatorManager.js"],"names":[],"mappings":"AAIA;IAQI;;OAEG;IACH,sCAFW,WAAW,EASrB;IAED;;;;OAIG;IACH,2BAJW,OAAO,iBAAiB,EAAE,OAAO,UACjC,OAAO,yBAAyB,EAAE,iBAAiB,WACnD,MAAM,QAKhB;IAED,qBAwDC;;CACJ"}
1
+ {"version":3,"file":"loadingIndicatorManager.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/loadingIndicatorManager.js"],"names":[],"mappings":"AAIA;IAYI;;;OAGG;IACH,sCAHW,WAAW,yBACX,OAAO,4BAA4B,EAAE,OAAO,EAWtD;IAED,gBAKC;IAED,qBAoGC;;CACJ"}