@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
@@ -5,45 +5,67 @@ import SPINNER from "../img/90-ring-with-bg.svg";
5
5
  export default class LoadingIndicatorManager {
6
6
  /** @type {HTMLElement} */
7
7
  #loadingIndicatorsElement;
8
+
8
9
  /**
9
- * @type {Map<import("../view/view.js").default, { status: import("../types/viewContext.js").DataLoadingStatus, detail?: string }>}
10
+ * @type {import("./loadingStatusRegistry.js").default}
10
11
  */
11
- #loadingViews;
12
+ #loadingStatusRegistry;
13
+
14
+ /** @type {(() => void) | null} */
15
+ #unsubscribe = null;
12
16
 
13
17
  /**
14
18
  * @param {HTMLElement} loadingIndicatorsElement
19
+ * @param {import("./loadingStatusRegistry.js").default} loadingStatusRegistry
15
20
  */
16
- constructor(loadingIndicatorsElement) {
21
+ constructor(loadingIndicatorsElement, loadingStatusRegistry) {
17
22
  this.#loadingIndicatorsElement = loadingIndicatorsElement;
18
23
 
19
- /**
20
- * @type {Map<import("../view/view.js").default, { status: import("../types/viewContext.js").DataLoadingStatus, detail?: string }>}
21
- */
22
- this.#loadingViews = new Map();
23
- }
24
+ this.#loadingStatusRegistry = loadingStatusRegistry;
24
25
 
25
- /**
26
- * @param {import("../view/view.js").default} view
27
- * @param {import("../types/viewContext.js").DataLoadingStatus} status
28
- * @param {string} [detail]
29
- */
30
- setDataLoadingStatus(view, status, detail) {
31
- this.#loadingViews.set(view, { status, detail });
26
+ this.#unsubscribe = this.#loadingStatusRegistry.subscribe(() =>
27
+ this.updateLayout()
28
+ );
32
29
  this.updateLayout();
33
30
  }
34
31
 
32
+ destroy() {
33
+ if (this.#unsubscribe) {
34
+ this.#unsubscribe();
35
+ this.#unsubscribe = null;
36
+ }
37
+ }
38
+
35
39
  updateLayout() {
36
40
  /** @type {import("lit").TemplateResult[]} */
37
41
  const indicators = [];
38
42
 
39
- const isSomethingVisible = () =>
40
- [...this.#loadingViews.values()].some(
41
- (v) => v.status == "loading" || v.status == "error"
42
- );
43
+ const isSomethingVisible = () => {
44
+ for (const [, status] of this.#loadingStatusRegistry.entries()) {
45
+ if (status.status == "loading" || status.status == "error") {
46
+ return true;
47
+ }
48
+ }
49
+ return false;
50
+ };
51
+
52
+ /** @type {{ status: import("../types/viewContext.js").DataLoadingStatus, detail?: string } | undefined} */
53
+ let fallbackStatus;
54
+ let hasVisibleWithCoords = false;
55
+
56
+ for (const [view, status] of this.#loadingStatusRegistry.entries()) {
57
+ const isVisible =
58
+ status.status == "loading" || status.status == "error";
43
59
 
44
- for (const [view, status] of this.#loadingViews) {
45
60
  const c = view.coords;
61
+ if (!c && isVisible && !fallbackStatus) {
62
+ fallbackStatus = status;
63
+ }
46
64
  if (c) {
65
+ if (isVisible) {
66
+ hasVisibleWithCoords = true;
67
+ }
68
+
47
69
  const style = {
48
70
  left: `${c.x}px`,
49
71
  top: `${c.y}px`,
@@ -70,6 +92,32 @@ export default class LoadingIndicatorManager {
70
92
  }
71
93
  }
72
94
 
95
+ if (fallbackStatus && !hasVisibleWithCoords) {
96
+ const style = {
97
+ left: "0px",
98
+ top: "0px",
99
+ width: "100%",
100
+ height: "100%",
101
+ };
102
+ indicators.push(
103
+ html`<div style=${styleMap(style)}>
104
+ <div class=${fallbackStatus.status}>
105
+ ${fallbackStatus.status == "error"
106
+ ? html`<span
107
+ >Loading
108
+ failed${fallbackStatus.detail
109
+ ? html`: ${fallbackStatus.detail}`
110
+ : nothing}</span
111
+ >`
112
+ : html`
113
+ <img src="${SPINNER}" alt="" />
114
+ <span>Loading...</span>
115
+ `}
116
+ </div>
117
+ </div>`
118
+ );
119
+ }
120
+
73
121
  // Do some hacks to stop css animations of the loading indicators.
74
122
  // Otherwise they fire animation frames even when their opacity is zero.
75
123
  // TODO: Instead of this, replace the animated spinners with static images.
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @typedef {import("../view/view.js").default} View
3
+ * @typedef {import("../types/viewContext.js").DataLoadingStatus} DataLoadingStatus
4
+ * @typedef {{ status: DataLoadingStatus, detail?: string }} LoadingStatus
5
+ * @typedef {{ view: View, status: DataLoadingStatus, detail?: string }} LoadingStatusChange
6
+ */
7
+ /**
8
+ * Central registry for per-view loading status that decouples data sources
9
+ * from UI rendering. Consumers can subscribe to changes and query the current
10
+ * status map when needed (e.g., for overlay rendering).
11
+ */
12
+ export default class LoadingStatusRegistry {
13
+ /**
14
+ * @param {View} view
15
+ * @param {DataLoadingStatus} status
16
+ * @param {string} [detail]
17
+ */
18
+ set(view: View, status: DataLoadingStatus, detail?: string): void;
19
+ /**
20
+ * @param {View} view
21
+ */
22
+ delete(view: View): void;
23
+ /**
24
+ * @param {View} view
25
+ * @returns {LoadingStatus | undefined}
26
+ */
27
+ get(view: View): LoadingStatus | undefined;
28
+ /**
29
+ * @returns {IterableIterator<[View, LoadingStatus]>}
30
+ */
31
+ entries(): IterableIterator<[View, LoadingStatus]>;
32
+ /**
33
+ * Subscribe to status changes.
34
+ *
35
+ * @param {(change: LoadingStatusChange) => void} listener
36
+ * @returns {() => void} Unsubscribe callback
37
+ */
38
+ subscribe(listener: (change: LoadingStatusChange) => void): () => void;
39
+ #private;
40
+ }
41
+ export type View = import("../view/view.js").default;
42
+ export type DataLoadingStatus = import("../types/viewContext.js").DataLoadingStatus;
43
+ export type LoadingStatus = {
44
+ status: DataLoadingStatus;
45
+ detail?: string;
46
+ };
47
+ export type LoadingStatusChange = {
48
+ view: View;
49
+ status: DataLoadingStatus;
50
+ detail?: string;
51
+ };
52
+ //# sourceMappingURL=loadingStatusRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadingStatusRegistry.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/loadingStatusRegistry.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH;IAOI;;;;OAIG;IACH,UAJW,IAAI,UACJ,iBAAiB,WACjB,MAAM,QAahB;IAED;;OAEG;IACH,aAFW,IAAI,QAkBd;IAED;;;OAGG;IACH,UAHW,IAAI,GACF,aAAa,GAAG,SAAS,CAIrC;IAED;;OAEG;IACH,WAFa,gBAAgB,CAAC,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAInD;IAED;;;;;OAKG;IACH,oBAHW,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,GACnC,MAAM,IAAI,CAOtB;;CACJ;mBApFY,OAAO,iBAAiB,EAAE,OAAO;gCACjC,OAAO,yBAAyB,EAAE,iBAAiB;4BACnD;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE;kCAC9C;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * @typedef {import("../view/view.js").default} View
3
+ * @typedef {import("../types/viewContext.js").DataLoadingStatus} DataLoadingStatus
4
+ * @typedef {{ status: DataLoadingStatus, detail?: string }} LoadingStatus
5
+ * @typedef {{ view: View, status: DataLoadingStatus, detail?: string }} LoadingStatusChange
6
+ */
7
+
8
+ /**
9
+ * Central registry for per-view loading status that decouples data sources
10
+ * from UI rendering. Consumers can subscribe to changes and query the current
11
+ * status map when needed (e.g., for overlay rendering).
12
+ */
13
+ export default class LoadingStatusRegistry {
14
+ /** @type {Map<View, LoadingStatus>} */
15
+ #statuses = new Map();
16
+
17
+ /** @type {Set<(change: LoadingStatusChange) => void>} */
18
+ #listeners = new Set();
19
+
20
+ /**
21
+ * @param {View} view
22
+ * @param {DataLoadingStatus} status
23
+ * @param {string} [detail]
24
+ */
25
+ set(view, status, detail) {
26
+ if (!view) {
27
+ throw new Error("LoadingStatusRegistry.set requires a view.");
28
+ }
29
+
30
+ this.#statuses.set(view, { status, detail });
31
+
32
+ const change = { view, status, detail };
33
+ for (const listener of this.#listeners) {
34
+ listener(change);
35
+ }
36
+ }
37
+
38
+ /**
39
+ * @param {View} view
40
+ */
41
+ delete(view) {
42
+ const previous = this.#statuses.get(view);
43
+ if (!previous) {
44
+ return;
45
+ }
46
+
47
+ this.#statuses.delete(view);
48
+
49
+ const change = {
50
+ view,
51
+ status: previous.status,
52
+ detail: previous.detail,
53
+ };
54
+ for (const listener of this.#listeners) {
55
+ listener(change);
56
+ }
57
+ }
58
+
59
+ /**
60
+ * @param {View} view
61
+ * @returns {LoadingStatus | undefined}
62
+ */
63
+ get(view) {
64
+ return this.#statuses.get(view);
65
+ }
66
+
67
+ /**
68
+ * @returns {IterableIterator<[View, LoadingStatus]>}
69
+ */
70
+ entries() {
71
+ return this.#statuses.entries();
72
+ }
73
+
74
+ /**
75
+ * Subscribe to status changes.
76
+ *
77
+ * @param {(change: LoadingStatusChange) => void} listener
78
+ * @returns {() => void} Unsubscribe callback
79
+ */
80
+ subscribe(listener) {
81
+ this.#listeners.add(listener);
82
+ return () => {
83
+ this.#listeners.delete(listener);
84
+ };
85
+ }
86
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"viewContextFactory.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/viewContextFactory.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;GASG;AACH,2CALW,OAAO,CAAC,WAAW,CAAC,GAAG;IAC7B,6BAA6B,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,iBAAiB,EAAE,QAAQ,GAAG,OAAO,iBAAiB,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,OAAO,0BAA0B,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,OAAO,iBAAiB,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,iBAAiB,EAAE,QAAQ,KAAK,IAAI,KAAK,OAAO,CAAC,OAAO,iBAAiB,EAAE,OAAO,CAAC,CAAA;CACvX,GACS,WAAW,CAkEvB;0BA7EY,OAAO,yBAAyB,EAAE,OAAO"}
1
+ {"version":3,"file":"viewContextFactory.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/viewContextFactory.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;GASG;AACH,2CALW,OAAO,CAAC,WAAW,CAAC,GAAG;IAC7B,6BAA6B,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,iBAAiB,EAAE,QAAQ,GAAG,OAAO,iBAAiB,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,OAAO,0BAA0B,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,OAAO,iBAAiB,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,iBAAiB,EAAE,QAAQ,KAAK,IAAI,KAAK,OAAO,CAAC,OAAO,iBAAiB,EAAE,OAAO,CAAC,CAAA;CACvX,GACS,WAAW,CAiEvB;0BA5EY,OAAO,yBAAyB,EAAE,OAAO"}
@@ -58,7 +58,6 @@ export function createViewContext(options) {
58
58
  "updateTooltip",
59
59
  "getNamedDataFromProvider",
60
60
  "getCurrentHover",
61
- "setDataLoadingStatus",
62
61
  "addKeyboardListener",
63
62
  "addBroadcastListener",
64
63
  "removeBroadcastListener",
@@ -9,4 +9,14 @@
9
9
  * @returns {Promise<import("../data/dataFlow.js").default>}
10
10
  */
11
11
  export function initializeViewData(viewRoot: import("../view/view.js").default, dataFlow: import("../data/dataFlow.js").default, fontManager: import("../fonts/bmFontManager.js").default, onDataFlowBuilt: (dataFlow: import("../data/dataFlow.js").default) => void): Promise<import("../data/dataFlow.js").default>;
12
+ /**
13
+ * Initializes data flow and graphics for visible views that were previously
14
+ * skipped. Intended for view-visibility toggles.
15
+ *
16
+ * @param {import("../view/view.js").default} viewRoot
17
+ * @param {import("../data/dataFlow.js").default} dataFlow
18
+ * @param {import("../fonts/bmFontManager.js").default} fontManager
19
+ * @returns {Promise<import("../data/dataFlow.js").default>}
20
+ */
21
+ export function initializeVisibleViewData(viewRoot: import("../view/view.js").default, dataFlow: import("../data/dataFlow.js").default, fontManager: import("../fonts/bmFontManager.js").default): Promise<import("../data/dataFlow.js").default>;
12
22
  //# sourceMappingURL=viewDataInit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"viewDataInit.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/viewDataInit.js"],"names":[],"mappings":"AAMA;;;;;;;;;GASG;AACH,6CANW,OAAO,iBAAiB,EAAE,OAAO,YACjC,OAAO,qBAAqB,EAAE,OAAO,eACrC,OAAO,2BAA2B,EAAE,OAAO,mBAC3C,CAAC,QAAQ,EAAE,OAAO,qBAAqB,EAAE,OAAO,KAAK,IAAI,GACvD,OAAO,CAAC,OAAO,qBAAqB,EAAE,OAAO,CAAC,CA0B1D"}
1
+ {"version":3,"file":"viewDataInit.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/viewDataInit.js"],"names":[],"mappings":"AAOA;;;;;;;;;GASG;AACH,6CANW,OAAO,iBAAiB,EAAE,OAAO,YACjC,OAAO,qBAAqB,EAAE,OAAO,eACrC,OAAO,2BAA2B,EAAE,OAAO,mBAC3C,CAAC,QAAQ,EAAE,OAAO,qBAAqB,EAAE,OAAO,KAAK,IAAI,GACvD,OAAO,CAAC,OAAO,qBAAqB,EAAE,OAAO,CAAC,CAkC1D;AAED;;;;;;;;GAQG;AACH,oDALW,OAAO,iBAAiB,EAAE,OAAO,YACjC,OAAO,qBAAqB,EAAE,OAAO,eACrC,OAAO,2BAA2B,EAAE,OAAO,GACzC,OAAO,CAAC,OAAO,qBAAqB,EAAE,OAAO,CAAC,CA2E1D"}
@@ -3,6 +3,7 @@ import {
3
3
  loadViewSubtreeData,
4
4
  } from "../data/flowInit.js";
5
5
  import { finalizeSubtreeGraphics } from "../view/viewUtils.js";
6
+ import { VISIT_SKIP } from "../view/view.js";
6
7
 
7
8
  /**
8
9
  * Initializes the view data pipeline: builds the flow graph, awaits fonts,
@@ -20,9 +21,13 @@ export async function initializeViewData(
20
21
  fontManager,
21
22
  onDataFlowBuilt
22
23
  ) {
24
+ const visibilityPredicate = (
25
+ /** @type {import("../view/view.js").default} */ view
26
+ ) => view.isConfiguredVisible();
23
27
  const { dataFlow: builtDataFlow, graphicsPromises } = initializeViewSubtree(
24
28
  viewRoot,
25
- dataFlow
29
+ dataFlow,
30
+ visibilityPredicate
26
31
  );
27
32
  onDataFlowBuilt(builtDataFlow);
28
33
 
@@ -33,9 +38,168 @@ export async function initializeViewData(
33
38
  await fontManager.waitUntilReady();
34
39
 
35
40
  // Find all data sources and initiate loading.
36
- await loadViewSubtreeData(viewRoot, new Set(builtDataFlow.dataSources));
41
+ await loadViewSubtreeData(
42
+ viewRoot,
43
+ new Set(builtDataFlow.dataSources),
44
+ visibilityPredicate
45
+ );
46
+
47
+ await finalizeSubtreeGraphics(graphicsPromises);
48
+
49
+ return builtDataFlow;
50
+ }
51
+
52
+ /**
53
+ * Initializes data flow and graphics for visible views that were previously
54
+ * skipped. Intended for view-visibility toggles.
55
+ *
56
+ * @param {import("../view/view.js").default} viewRoot
57
+ * @param {import("../data/dataFlow.js").default} dataFlow
58
+ * @param {import("../fonts/bmFontManager.js").default} fontManager
59
+ * @returns {Promise<import("../data/dataFlow.js").default>}
60
+ */
61
+ export async function initializeVisibleViewData(
62
+ viewRoot,
63
+ dataFlow,
64
+ fontManager
65
+ ) {
66
+ // Initialize dataflow/graphics for views that have become visible since the
67
+ // initial load, while avoiding unnecessary data source reloads. If a view
68
+ // attaches downstream of an already completed collector, repropagate that
69
+ // collector instead of reloading the source.
70
+ const visibilityPredicate = (
71
+ /** @type {import("../view/view.js").default} */ view
72
+ ) => view.isConfiguredVisible();
73
+ const visibleViews = collectVisibleViews(viewRoot, visibilityPredicate);
74
+ const viewsToInitialize = visibleViews.filter(
75
+ (view) => view.getDataInitializationState() === "none"
76
+ );
77
+
78
+ if (viewsToInitialize.length === 0) {
79
+ return dataFlow;
80
+ }
81
+
82
+ const viewsToInitializeSet = new Set(viewsToInitialize);
83
+ const viewInitializationPredicate = (
84
+ /** @type {import("../view/view.js").default} */ view
85
+ ) => viewsToInitializeSet.has(view);
86
+
87
+ /** @type {Set<import("../data/collector.js").default>} */
88
+ const collectorsToRepropagate = new Set();
89
+ /** @type {import("../view/view.js").default[]} */
90
+ const viewsNeedingLoad = [];
91
+ for (const view of viewsToInitialize) {
92
+ if (view.spec.data) {
93
+ viewsNeedingLoad.push(view);
94
+ continue;
95
+ }
96
+ const collector = findCompletedAncestorCollector(view);
97
+ if (collector) {
98
+ collectorsToRepropagate.add(collector);
99
+ } else {
100
+ viewsNeedingLoad.push(view);
101
+ }
102
+ }
103
+
104
+ const { dataFlow: builtDataFlow, graphicsPromises } = initializeViewSubtree(
105
+ viewRoot,
106
+ dataFlow,
107
+ visibilityPredicate,
108
+ viewInitializationPredicate
109
+ );
110
+
111
+ await fontManager.waitUntilReady();
112
+
113
+ for (const collector of collectorsToRepropagate) {
114
+ collector.repropagate();
115
+ }
116
+
117
+ if (viewsNeedingLoad.length) {
118
+ const dataSourceRoots = collectDataSourceRoots(viewsNeedingLoad);
119
+ await Promise.all(
120
+ Array.from(dataSourceRoots.entries()).map(
121
+ ([subtreeRoot, dataSources]) =>
122
+ loadViewSubtreeData(subtreeRoot, dataSources, undefined, {
123
+ // If a source is already loading, schedule a reload so new branches
124
+ // added during lazy init receive a complete data propagation.
125
+ queueReload: true,
126
+ })
127
+ )
128
+ );
129
+ }
37
130
 
38
131
  await finalizeSubtreeGraphics(graphicsPromises);
39
132
 
40
133
  return builtDataFlow;
41
134
  }
135
+
136
+ /**
137
+ * @param {import("../view/view.js").default} viewRoot
138
+ * @param {(view: import("../view/view.js").default) => boolean} viewFilter
139
+ * @returns {import("../view/view.js").default[]}
140
+ */
141
+ function collectVisibleViews(viewRoot, viewFilter) {
142
+ /** @type {import("../view/view.js").default[]} */
143
+ const views = [];
144
+ viewRoot.visit((view) => {
145
+ if (!viewFilter(view)) {
146
+ return VISIT_SKIP;
147
+ }
148
+ views.push(view);
149
+ });
150
+ return views;
151
+ }
152
+
153
+ /**
154
+ * @param {import("../view/view.js").default[]} views
155
+ * @returns {Map<import("../view/view.js").default, Set<import("../data/sources/dataSource.js").default>>}
156
+ */
157
+ function collectDataSourceRoots(views) {
158
+ /** @type {Map<import("../view/view.js").default, Set<import("../data/sources/dataSource.js").default>>} */
159
+ const roots = new Map();
160
+
161
+ for (const view of views) {
162
+ let current = view;
163
+ while (current && !current.flowHandle?.dataSource) {
164
+ current = current.dataParent;
165
+ }
166
+
167
+ if (!current?.flowHandle?.dataSource) {
168
+ if (view.spec.data) {
169
+ throw new Error(
170
+ "No data source found for view " + view.getPathString()
171
+ );
172
+ }
173
+ // Some views are data-less (constants or references); they don't
174
+ // participate in data loading but still need graphics init.
175
+ continue;
176
+ }
177
+
178
+ let dataSources = roots.get(current);
179
+ if (!dataSources) {
180
+ dataSources = new Set();
181
+ roots.set(current, dataSources);
182
+ }
183
+ dataSources.add(current.flowHandle.dataSource);
184
+ }
185
+
186
+ return roots;
187
+ }
188
+
189
+ /**
190
+ * Finds the nearest completed collector in the dataParent chain.
191
+ *
192
+ * @param {import("../view/view.js").default} view
193
+ * @returns {import("../data/collector.js").default | undefined}
194
+ */
195
+ function findCompletedAncestorCollector(view) {
196
+ let current = view.dataParent;
197
+ while (current) {
198
+ const collector = current.flowHandle?.collector;
199
+ if (collector) {
200
+ return collector.completed ? collector : undefined;
201
+ }
202
+ current = current.dataParent;
203
+ }
204
+ return undefined;
205
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=viewDataInit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewDataInit.test.d.ts","sourceRoot":"","sources":["../../../src/genomeSpy/viewDataInit.test.js"],"names":[],"mappings":""}
@@ -66,8 +66,6 @@ export default class GenomeSpy {
66
66
  * @param {any} [payload]
67
67
  */
68
68
  broadcast(type: BroadcastEventType, payload?: any): void;
69
- loadingMessageElement: HTMLElement;
70
- loadingIndicatorsElement: HTMLElement;
71
69
  tooltip: import("./utils/ui/tooltip.js").default;
72
70
  /**
73
71
  * Unregisters all listeners, removes all created dom elements, removes all css classes from the container
@@ -78,6 +76,7 @@ export default class GenomeSpy {
78
76
  * @returns {Promise<boolean>} true if the launch was successful
79
77
  */
80
78
  launch(): Promise<boolean>;
79
+ initializeVisibleViewData(): Promise<void>;
81
80
  registerMouseEvents(): void;
82
81
  /**
83
82
  * This method should be called in a mouseMove handler. If not called, the
@@ -1 +1 @@
1
- {"version":3,"file":"genomeSpy.d.ts","sourceRoot":"","sources":["../../src/genomeSpy.js"],"names":[],"mappings":"AA0CA;IAkBI;;;;;OAKG;IAEH;;;;;OAKG;IACH,uBAJW,WAAW,qDAEX,OAAO,qBAAqB,EAAE,YAAY,EA0CpD;IAvCG,uBAA0B;IAC1B,oDAAsB;IAItB,sCAAsC;IACtC,wCAAgB;IAEhB,yBAAoC;IAEpC,4CAA4C;IAC5C,oBADW,CAAC,CAAS,IAAM,EAAN,MAAM,KAAE,MAAM,EAAE,CAAC,EAAE,CACZ;IAE5B,mBAAoD;IAEpD,0BAA0B;IAC1B,aADW,WAAW,CACM;IAE5B;;;;;OAKG;IACH,yBAFU,CAAC,IAAI,kCAAM,KAAK,OAAO,CAE8B;IAE/D,oFAAoF;IACpF,iBADW,MAAM,CAAC,MAAM,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC,CAK9E;IAED,mBAAmB;IACnB,2CAAyB;IAIzB,YAAkC;IAatC;;;OAGG;IACH,oCAFW,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,EAAE,QAIjC;IAED;;OAEG;IACH,+BAFW,MAAM,YAShB;IAED;;;;OAIG;IACH,sBAHW,MAAM,QACN,GAAG,EAAE,QAYf;IAED;;;OAGG;IACH,uBAHW,MAAM,YACN,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,QAI9B;IAED;;;OAGG;IACH,0BAHW,MAAM,YACN,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,QAI9B;IAED;;;;;OAKG;IACH,gBAHW,kBAAkB,YAClB,GAAG,QAMb;IAiEG,mCAAkD;IAKlD,sCAAwD;IACxD,iDAAsB;IAM1B;;OAEG;IACH,gBAmBC;IA8ID;;;OAGG;IACH,UAFa,OAAO,CAAC,OAAO,CAAC,CAgC5B;IAED,4BAEC;IAED;;;;;;;OAOG;IACH,cAFa,CAAC,SAFH,CAAC,cACD,CAAS,IAAC,EAAD,CAAC,KAAE,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAKlF;IAED;;;;;;;;OAQG;IACH,4BANW,MAAM,kBACN,MAAM,qBACN,MAAM,eACN,MAAM,UAuBhB;IAED;;;MAEC;IAED,sBAEC;IAED,kBAEC;IAED,iCAEC;IAED,iCASC;IAED,uFAWC;;CACJ;;;;iCAlgBY,eAAe,GAAG,QAAQ,GAAG,gBAAgB,GAAG,kBAAkB;4BAZnC,uBAAuB;qBAR9C,qBAAqB;wBAElB,yBAAyB;qBAL5B,oBAAoB"}
1
+ {"version":3,"file":"genomeSpy.d.ts","sourceRoot":"","sources":["../../src/genomeSpy.js"],"names":[],"mappings":"AA+CA;IAoBI;;;;;OAKG;IAEH;;;;;OAKG;IACH,uBAJW,WAAW,qDAEX,OAAO,qBAAqB,EAAE,YAAY,EA0CpD;IAvCG,uBAA0B;IAC1B,oDAAsB;IAItB,sCAAsC;IACtC,wCAAgB;IAEhB,yBAAoC;IAEpC,4CAA4C;IAC5C,oBADW,CAAC,CAAS,IAAM,EAAN,MAAM,KAAE,MAAM,EAAE,CAAC,EAAE,CACZ;IAE5B,mBAAoD;IAEpD,0BAA0B;IAC1B,aADW,WAAW,CACM;IAE5B;;;;;OAKG;IACH,yBAFU,CAAC,IAAI,kCAAM,KAAK,OAAO,CAE8B;IAE/D,oFAAoF;IACpF,iBADW,MAAM,CAAC,MAAM,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC,CAK9E;IAED,mBAAmB;IACnB,2CAAyB;IAIzB,YAAkC;IAatC;;;OAGG;IACH,oCAFW,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,EAAE,QAIjC;IAED;;OAEG;IACH,+BAFW,MAAM,YAShB;IAED;;;;OAIG;IACH,sBAHW,MAAM,QACN,GAAG,EAAE,QAYf;IAED;;;OAGG;IACH,uBAHW,MAAM,YACN,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,QAI9B;IAED;;;OAGG;IACH,0BAHW,MAAM,YACN,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,QAI9B;IAED;;;;;OAKG;IACH,gBAHW,kBAAkB,YAClB,GAAG,QAMb;IA4DG,iDAAsB;IAQ1B;;OAEG;IACH,gBAqBC;IAyJD;;;OAGG;IACH,UAFa,OAAO,CAAC,OAAO,CAAC,CAyC5B;IAED,2CAiBC;IAED,4BAEC;IAED;;;;;;;OAOG;IACH,cAFa,CAAC,SAFH,CAAC,cACD,CAAS,IAAC,EAAD,CAAC,KAAE,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAKlF;IAED;;;;;;;;OAQG;IACH,4BANW,MAAM,kBACN,MAAM,qBACN,MAAM,eACN,MAAM,UAuBhB;IAED;;;MAEC;IAED,sBAEC;IAED,kBAEC;IAED,iCAEC;IAED,iCAYC;IAED,uFAWC;;CACJ;;;;iCAviBY,eAAe,GAAG,QAAQ,GAAG,gBAAgB,GAAG,kBAAkB;4BAbnC,uBAAuB;qBAR9C,qBAAqB;wBAElB,yBAAyB;qBAL5B,oBAAoB"}