@genome-spy/core 0.29.0 → 0.30.2

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 (234) hide show
  1. package/dist/index.es.js +16373 -0
  2. package/dist/index.js +43 -43
  3. package/package.json +10 -7
  4. package/src/data/collector.js +0 -183
  5. package/src/data/collector.test.js +0 -84
  6. package/src/data/dataFlow.js +0 -148
  7. package/src/data/dataFlow.test.js +0 -5
  8. package/src/data/facetNode.js +0 -17
  9. package/src/data/flow.test.js +0 -72
  10. package/src/data/flowBatch.d.ts +0 -40
  11. package/src/data/flowNode.js +0 -283
  12. package/src/data/flowNode.test.js +0 -50
  13. package/src/data/flowOptimizer.js +0 -123
  14. package/src/data/flowOptimizer.test.js +0 -193
  15. package/src/data/flowTestUtils.js +0 -63
  16. package/src/data/formats/fasta.js +0 -32
  17. package/src/data/formats/fasta.test.js +0 -27
  18. package/src/data/sources/dataSource.js +0 -22
  19. package/src/data/sources/dataSourceFactory.js +0 -24
  20. package/src/data/sources/dataUtils.js +0 -78
  21. package/src/data/sources/dynamicCallbackSource.js +0 -57
  22. package/src/data/sources/dynamicSource.js +0 -37
  23. package/src/data/sources/inlineSource.js +0 -67
  24. package/src/data/sources/inlineSource.test.js +0 -56
  25. package/src/data/sources/namedSource.js +0 -79
  26. package/src/data/sources/sequenceSource.js +0 -46
  27. package/src/data/sources/sequenceSource.test.js +0 -46
  28. package/src/data/sources/urlSource.js +0 -74
  29. package/src/data/transforms/aggregate.js +0 -70
  30. package/src/data/transforms/clone.js +0 -40
  31. package/src/data/transforms/clone.test.js +0 -11
  32. package/src/data/transforms/coverage.js +0 -187
  33. package/src/data/transforms/coverage.test.js +0 -123
  34. package/src/data/transforms/filter.js +0 -37
  35. package/src/data/transforms/filter.test.js +0 -18
  36. package/src/data/transforms/filterScoredLabels.js +0 -134
  37. package/src/data/transforms/flattenCompressedExons.js +0 -57
  38. package/src/data/transforms/flattenDelimited.js +0 -74
  39. package/src/data/transforms/flattenDelimited.test.js +0 -87
  40. package/src/data/transforms/flattenSequence.js +0 -39
  41. package/src/data/transforms/flattenSequence.test.js +0 -34
  42. package/src/data/transforms/formula.js +0 -39
  43. package/src/data/transforms/formula.test.js +0 -19
  44. package/src/data/transforms/identifier.js +0 -108
  45. package/src/data/transforms/identifier.test.js +0 -83
  46. package/src/data/transforms/linearizeGenomicCoordinate.js +0 -101
  47. package/src/data/transforms/measureText.js +0 -44
  48. package/src/data/transforms/pileup.js +0 -128
  49. package/src/data/transforms/pileup.test.js +0 -70
  50. package/src/data/transforms/project.js +0 -41
  51. package/src/data/transforms/project.test.js +0 -32
  52. package/src/data/transforms/regexExtract.js +0 -61
  53. package/src/data/transforms/regexExtract.test.js +0 -67
  54. package/src/data/transforms/regexFold.js +0 -141
  55. package/src/data/transforms/regexFold.test.js +0 -160
  56. package/src/data/transforms/sample.js +0 -101
  57. package/src/data/transforms/sample.test.js +0 -38
  58. package/src/data/transforms/stack.js +0 -137
  59. package/src/data/transforms/stack.test.js +0 -91
  60. package/src/data/transforms/transformFactory.js +0 -60
  61. package/src/embedApi.d.ts +0 -67
  62. package/src/encoder/accessor.js +0 -82
  63. package/src/encoder/accessor.test.js +0 -47
  64. package/src/encoder/encoder.js +0 -394
  65. package/src/encoder/encoder.test.js +0 -98
  66. package/src/fonts/Lato-Regular.json +0 -1267
  67. package/src/fonts/Lato-Regular.png +0 -0
  68. package/src/fonts/OFL.txt +0 -93
  69. package/src/fonts/README.md +0 -3
  70. package/src/fonts/bmFont.d.ts +0 -58
  71. package/src/fonts/bmFontManager.js +0 -357
  72. package/src/fonts/bmFontMetrics.js +0 -108
  73. package/src/genome/genome.js +0 -317
  74. package/src/genome/genome.test.js +0 -188
  75. package/src/genome/genomeStore.js +0 -54
  76. package/src/genome/locusFormat.js +0 -31
  77. package/src/genome/scaleIndex.d.ts +0 -38
  78. package/src/genome/scaleIndex.js +0 -166
  79. package/src/genome/scaleIndex.test.js +0 -78
  80. package/src/genome/scaleLocus.d.ts +0 -11
  81. package/src/genome/scaleLocus.js +0 -108
  82. package/src/genome/scaleLocus.test.js +0 -4
  83. package/src/genomeSpy.js +0 -784
  84. package/src/gl/arrayBuilder.js +0 -199
  85. package/src/gl/dataToVertices.js +0 -636
  86. package/src/gl/includes/common.glsl +0 -63
  87. package/src/gl/includes/picking.fragment.glsl +0 -1
  88. package/src/gl/includes/picking.vertex.glsl +0 -27
  89. package/src/gl/includes/sampleFacet.glsl +0 -107
  90. package/src/gl/includes/scales.glsl +0 -112
  91. package/src/gl/link.fragment.glsl +0 -18
  92. package/src/gl/link.vertex.glsl +0 -111
  93. package/src/gl/point.fragment.glsl +0 -123
  94. package/src/gl/point.vertex.glsl +0 -129
  95. package/src/gl/rect.fragment.glsl +0 -51
  96. package/src/gl/rect.vertex.glsl +0 -114
  97. package/src/gl/rule.fragment.glsl +0 -52
  98. package/src/gl/rule.vertex.glsl +0 -89
  99. package/src/gl/text.fragment.glsl +0 -31
  100. package/src/gl/text.vertex.glsl +0 -246
  101. package/src/gl/webGLHelper.js +0 -489
  102. package/src/img/bowtie.svg +0 -1
  103. package/src/img/genomespy-favicon.svg +0 -34
  104. package/src/index.html +0 -11
  105. package/src/index.js +0 -128
  106. package/src/marks/link.js +0 -175
  107. package/src/marks/mark.js +0 -975
  108. package/src/marks/markUtils.js +0 -125
  109. package/src/marks/pointMark.js +0 -251
  110. package/src/marks/rectMark.js +0 -241
  111. package/src/marks/rule.js +0 -250
  112. package/src/marks/text.js +0 -278
  113. package/src/node_modules/.vitest/results.json +0 -1
  114. package/src/scale/colorUtils.js +0 -184
  115. package/src/scale/glslScaleGenerator.js +0 -488
  116. package/src/scale/scale.js +0 -451
  117. package/src/scale/scale.test.js +0 -324
  118. package/src/scale/ticks.js +0 -203
  119. package/src/scale/ticks.test.js +0 -40
  120. package/src/singlePageApp.js +0 -13
  121. package/src/spec/axis.d.ts +0 -296
  122. package/src/spec/channel.d.ts +0 -430
  123. package/src/spec/data.d.ts +0 -196
  124. package/src/spec/font.d.ts +0 -15
  125. package/src/spec/genome.d.ts +0 -35
  126. package/src/spec/mark.d.ts +0 -429
  127. package/src/spec/root.d.ts +0 -17
  128. package/src/spec/sampleView.d.ts +0 -180
  129. package/src/spec/scale.d.ts +0 -273
  130. package/src/spec/title.d.ts +0 -102
  131. package/src/spec/tooltip.d.ts +0 -9
  132. package/src/spec/transform.d.ts +0 -479
  133. package/src/spec/view.d.ts +0 -201
  134. package/src/styles/genome-spy.scss +0 -153
  135. package/src/tooltip/dataTooltipHandler.js +0 -64
  136. package/src/tooltip/refseqGeneTooltipHandler.js +0 -78
  137. package/src/tooltip/tooltipHandler.ts +0 -12
  138. package/src/types/filetypes.d.ts +0 -14
  139. package/src/types/flatqueue.d.ts +0 -53
  140. package/src/types/glsl.d.ts +0 -4
  141. package/src/types/internmap.d.ts +0 -22
  142. package/src/types/object.d.ts +0 -21
  143. package/src/types/vega-loader.d.ts +0 -1
  144. package/src/types/vega-scale.d.ts +0 -60
  145. package/src/utils/addBaseUrl.js +0 -19
  146. package/src/utils/addBaseUrl.test.js +0 -22
  147. package/src/utils/animator.js +0 -83
  148. package/src/utils/arrayUtils.js +0 -61
  149. package/src/utils/binnedIndex.js +0 -167
  150. package/src/utils/binnedIndex.test.js +0 -155
  151. package/src/utils/clamp.js +0 -8
  152. package/src/utils/cloner.js +0 -34
  153. package/src/utils/cloner.test.js +0 -24
  154. package/src/utils/coalesce.js +0 -11
  155. package/src/utils/coalesce.test.js +0 -16
  156. package/src/utils/concatIterables.js +0 -26
  157. package/src/utils/concatIterables.test.js +0 -8
  158. package/src/utils/debounce.js +0 -37
  159. package/src/utils/domainArray.js +0 -216
  160. package/src/utils/domainArray.test.js +0 -130
  161. package/src/utils/eerp.js +0 -13
  162. package/src/utils/expression.js +0 -32
  163. package/src/utils/field.js +0 -28
  164. package/src/utils/formatObject.js +0 -31
  165. package/src/utils/indexer.js +0 -43
  166. package/src/utils/indexer.test.js +0 -47
  167. package/src/utils/inertia.js +0 -124
  168. package/src/utils/interactionEvent.js +0 -33
  169. package/src/utils/iterateNestedMaps.js +0 -21
  170. package/src/utils/iterateNestedMaps.test.js +0 -33
  171. package/src/utils/kWayMerge.js +0 -42
  172. package/src/utils/kWayMerge.test.js +0 -26
  173. package/src/utils/layout/flexLayout.js +0 -368
  174. package/src/utils/layout/flexLayout.test.js +0 -311
  175. package/src/utils/layout/grid.js +0 -95
  176. package/src/utils/layout/grid.test.js +0 -71
  177. package/src/utils/layout/padding.js +0 -120
  178. package/src/utils/layout/point.js +0 -23
  179. package/src/utils/layout/rectangle.js +0 -288
  180. package/src/utils/layout/rectangle.test.js +0 -172
  181. package/src/utils/mergeObjects.js +0 -99
  182. package/src/utils/mergeObjects.test.js +0 -42
  183. package/src/utils/numberExtractor.js +0 -24
  184. package/src/utils/numberExtractor.test.js +0 -6
  185. package/src/utils/point.js +0 -14
  186. package/src/utils/propertyCacher.js +0 -70
  187. package/src/utils/propertyCacher.test.js +0 -85
  188. package/src/utils/propertyCoalescer.js +0 -42
  189. package/src/utils/propertyCoalescer.test.js +0 -22
  190. package/src/utils/reservationMap.js +0 -103
  191. package/src/utils/reservationMap.test.js +0 -20
  192. package/src/utils/scaleNull.js +0 -19
  193. package/src/utils/setOperations.js +0 -75
  194. package/src/utils/smoothstep.js +0 -10
  195. package/src/utils/throttle.js +0 -34
  196. package/src/utils/topK.js +0 -76
  197. package/src/utils/topK.test.js +0 -64
  198. package/src/utils/transition.js +0 -74
  199. package/src/utils/ui/tooltip.js +0 -189
  200. package/src/utils/url.js +0 -22
  201. package/src/utils/variableTools.js +0 -24
  202. package/src/utils/variableTools.test.js +0 -13
  203. package/src/view/axisResolution.js +0 -140
  204. package/src/view/axisResolution.test.js +0 -201
  205. package/src/view/axisView.js +0 -747
  206. package/src/view/concatView.js +0 -45
  207. package/src/view/containerView.js +0 -159
  208. package/src/view/facetView.js +0 -491
  209. package/src/view/flowBuilder.js +0 -367
  210. package/src/view/flowBuilder.test.js +0 -125
  211. package/src/view/gridView.js +0 -786
  212. package/src/view/implicitRootView.js +0 -14
  213. package/src/view/importView.js +0 -19
  214. package/src/view/layerView.js +0 -74
  215. package/src/view/rendering.d.ts +0 -44
  216. package/src/view/renderingContext/compositeViewRenderingContext.js +0 -51
  217. package/src/view/renderingContext/deferredViewRenderingContext.js +0 -176
  218. package/src/view/renderingContext/layoutRecorderViewRenderingContext.js +0 -128
  219. package/src/view/renderingContext/simpleViewRenderingContext.js +0 -64
  220. package/src/view/renderingContext/svgViewRenderingContext.js +0 -125
  221. package/src/view/renderingContext/viewRenderingContext.js +0 -41
  222. package/src/view/scaleResolution.js +0 -791
  223. package/src/view/scaleResolution.test.js +0 -572
  224. package/src/view/scaleResolutionApi.d.ts +0 -40
  225. package/src/view/testUtils.js +0 -51
  226. package/src/view/title.js +0 -165
  227. package/src/view/unitView.js +0 -382
  228. package/src/view/view.js +0 -612
  229. package/src/view/view.test.js +0 -214
  230. package/src/view/viewContext.d.ts +0 -62
  231. package/src/view/viewFactory.js +0 -181
  232. package/src/view/viewFactory.test.js +0 -17
  233. package/src/view/viewUtils.js +0 -327
  234. package/src/view/zoom.js +0 -89
package/src/view/view.js DELETED
@@ -1,612 +0,0 @@
1
- import {
2
- parseSizeDef,
3
- FlexDimensions,
4
- ZERO_FLEXDIMENSIONS,
5
- } from "../utils/layout/flexLayout";
6
- import Padding from "../utils/layout/padding";
7
- import {
8
- getCachedOrCall,
9
- initPropertyCache,
10
- invalidatePrefix,
11
- } from "../utils/propertyCacher";
12
- import { isNumber, isString, span } from "vega-util";
13
- import { scaleLog } from "d3-scale";
14
- import { isFieldDef, getPrimaryChannel } from "../encoder/encoder";
15
- import { appendToBaseUrl } from "../utils/url";
16
- import { isDiscrete, bandSpace } from "vega-scale";
17
- import { peek } from "../utils/arrayUtils";
18
-
19
- // TODO: View classes have too many responsibilities. Come up with a way
20
- // to separate the concerns. However, most concerns are tightly tied to
21
- // the hierarchy, which makes the separation quite tricky.
22
- // Separation of concerns would also make the code more easily testable.
23
-
24
- /** Skip children */
25
- export const VISIT_SKIP = "VISIT_SKIP";
26
- /** Stop further visits */
27
- export const VISIT_STOP = "VISIT_STOP";
28
-
29
- /** @type {function(number):number} */
30
- const defaultOpacityFunction = (parentOpacity) => parentOpacity;
31
-
32
- /**
33
- * @typedef {import("../spec/channel").Channel} Channel
34
- * @typedef {import("../spec/channel").ChannelDef} ChannelDef
35
- * @typedef {import("../spec/view").ViewSpec} ViewSpec
36
- * @typedef {import("./viewUtils").ViewContext} ViewContext
37
- * @typedef {import("../utils/layout/flexLayout").SizeDef} SizeDef
38
- * @typedef {import("../utils/layout/flexLayout").LocSize} LocSize
39
- *
40
- * @typedef {import("../spec/view").ResolutionTarget} ResolutionTarget
41
- * @typedef {import("./scaleResolution").default} ScaleResolution
42
- * @typedef {import("./axisResolution").default} AxisResolution
43
- *
44
- * @typedef {VISIT_SKIP|VISIT_STOP|void} VisitResult
45
- *
46
- * @callback VisitorCallback
47
- * @param {View} view
48
- * @returns {VisitResult}
49
- *
50
- * @typedef {VisitorCallback & {
51
- * postOrder?: function(View):void,
52
- * beforeChildren?: function(View):void,
53
- * afterChildren?: function(View):void}
54
- * } Visitor
55
- *
56
- * @typedef {object} BroadcastMessage
57
- * @prop {string} type Broadcast type
58
- * @prop {any} [payload] Anything
59
- *
60
- * @typedef {import("./rendering").RenderingOptions} RenderingOptions
61
- *
62
- * @callback InteractionEventListener
63
- * @param {import("../utils/layout/rectangle").default} coords
64
- * Coordinates of the view
65
- * @param {import("../utils/interactionEvent").default} event
66
- */
67
- export default class View {
68
- /**
69
- *
70
- * @param {ViewSpec} spec
71
- * @param {ViewContext} context
72
- * @param {import("./containerView").default} parent
73
- * @param {string} name
74
- */
75
- constructor(spec, context, parent, name) {
76
- this.context = context;
77
- this.parent = parent;
78
- this.name = spec.name || name;
79
- this.spec = spec;
80
-
81
- this.resolutions = {
82
- /**
83
- * Channel-specific scale resolutions
84
- * @type {Partial<Record<Channel, import("./scaleResolution").default>>}
85
- */
86
- scale: {},
87
- /**
88
- * Channel-specific axis resolutions
89
- * @type {Partial<Record<import("../spec/channel").PrimaryPositionalChannel, import("./axisResolution").default>>}
90
- */
91
- axis: {},
92
- };
93
-
94
- /** @type {Record<string, (function(BroadcastMessage):void)[]>} */
95
- this._broadcastHandlers = {};
96
-
97
- /** @type {Record<string, InteractionEventListener[]>} */
98
- this._capturingInteractionEventListeners = {};
99
- /** @type {Record<string, InteractionEventListener[]>} */
100
- this._nonCapturingInteractionEventListeners = {};
101
-
102
- initPropertyCache(this);
103
-
104
- /** @type {function(number):number} */
105
- this.opacityFunction = defaultOpacityFunction;
106
-
107
- /**
108
- * Don't inherit encodings from parent.
109
- * TODO: Make configurable through spec. Allow more fine-grained control.
110
- */
111
- this.blockEncodingInheritance = false;
112
- }
113
-
114
- getPadding() {
115
- return this._cache("size/padding", () =>
116
- Padding.createFromConfig(this.spec.padding)
117
- );
118
- }
119
-
120
- /**
121
- * Returns a padding that indicates how much axes and titles extend over the plot area.
122
- *
123
- * @returns {Padding}
124
- */
125
- getOverhang() {
126
- return Padding.zero();
127
- }
128
-
129
- /**
130
- * Returns the configured size, if present. Otherwise a computed or default
131
- * height is returned.
132
- *
133
- * @returns {FlexDimensions}
134
- */
135
- getSize() {
136
- return this._cache("size/size", () =>
137
- this.isVisible()
138
- ? this.getSizeFromSpec().addPadding(this.getPadding())
139
- : ZERO_FLEXDIMENSIONS
140
- );
141
- }
142
-
143
- /**
144
- * @return {FlexDimensions}
145
- */
146
- getSizeFromSpec() {
147
- /**
148
- * @param {"width" | "height"} dimension
149
- * @return {SizeDef}
150
- */
151
- const handleSize = (dimension) => {
152
- let value = this.spec[dimension];
153
-
154
- if (isStepSize(value)) {
155
- const stepSize = value.step;
156
-
157
- const scale = this.getScaleResolution(
158
- dimension == "width" ? "x" : "y"
159
- )?.getScale();
160
-
161
- if (scale) {
162
- // Note: this and all ancestral views need to be refreshed when the domain is changed.
163
- let steps = 0;
164
- if (isDiscrete(scale.type)) {
165
- steps = scale.domain().length;
166
- } else if (["locus", "index"].includes(scale.type)) {
167
- const domain = scale.domain();
168
- steps = peek(domain) - domain[0];
169
- } else {
170
- throw new Error(
171
- `Cannot use step-based size with "${scale.type}" scale!`
172
- );
173
- }
174
-
175
- // TODO: Type guards maybe?
176
- const _scale =
177
- /** @type {import("d3-scale").ScaleBand<any> | import("../genome/scaleLocus").ScaleLocus | import("../genome/scaleIndex").ScaleIndex} */ (
178
- scale
179
- );
180
-
181
- steps = bandSpace(
182
- steps,
183
- _scale.paddingInner(),
184
- _scale.paddingOuter()
185
- );
186
-
187
- return { px: steps * stepSize, grow: 0 };
188
- } else {
189
- throw new Error(
190
- "Cannot use 'step' size with missing scale!"
191
- );
192
- }
193
- } else {
194
- return (value && parseSizeDef(value)) ?? { px: 0, grow: 1 };
195
- }
196
- };
197
-
198
- return this._cache(
199
- "size/sizeFromSpec",
200
- () => new FlexDimensions(handleSize("width"), handleSize("height"))
201
- );
202
- }
203
-
204
- isVisible() {
205
- return this.context.isViewVisible(this);
206
- }
207
-
208
- isVisibleInSpec() {
209
- return this.spec.visible ?? true;
210
- }
211
-
212
- /**
213
- * Returns the effective opacity of this view, e.g., view's opacity multiplied
214
- * by opacities of its ancestors.
215
- *
216
- * TODO: This methods makes sense only in Unit and Layer views.
217
- *
218
- * @returns {number}
219
- */
220
- getEffectiveOpacity() {
221
- return this.opacityFunction(this.parent?.getEffectiveOpacity() ?? 1.0);
222
- }
223
-
224
- getPathString() {
225
- return [...this.getAncestors()]
226
- .map((v) => v.name)
227
- .reverse()
228
- .join("/");
229
- }
230
-
231
- *getAncestors() {
232
- // eslint-disable-next-line consistent-this
233
- let view = /** @type {View} */ (this);
234
- do {
235
- yield view;
236
- view = view.parent;
237
- } while (view);
238
- }
239
-
240
- /**
241
- * Handles a broadcast message that is intended for the whole view hierarchy.
242
- *
243
- * @param {BroadcastMessage} message
244
- */
245
- handleBroadcast(message) {
246
- // TODO: message types should be constants
247
- for (const handler of this._broadcastHandlers[message.type] || []) {
248
- handler(message);
249
- }
250
- }
251
-
252
- /**
253
- *
254
- * @param {string} type
255
- * @param {function(BroadcastMessage):void} handler
256
- */
257
- _addBroadcastHandler(type, handler) {
258
- let handlers = this._broadcastHandlers[type];
259
- if (!handlers) {
260
- handlers = [];
261
- this._broadcastHandlers[type] = handlers;
262
- }
263
- handlers.push(handler);
264
- }
265
-
266
- /**
267
- * Handles an interactionEvent
268
- *
269
- * @param {import("../utils/layout/rectangle").default} coords
270
- * Coordinates of the view
271
- * @param {import("../utils/interactionEvent").default} event
272
- * @param {boolean} capturing
273
- */
274
- handleInteractionEvent(coords, event, capturing) {
275
- const listenersByType = capturing
276
- ? this._capturingInteractionEventListeners
277
- : this._nonCapturingInteractionEventListeners;
278
- for (const listener of listenersByType[event.type] || []) {
279
- listener(coords, event);
280
- }
281
- }
282
-
283
- /**
284
- * Add an "interaction" event listener that mimics DOM's event model inside
285
- * the view hierarchy.
286
- *
287
- * This is intended for GenomeSpy's internal use. It allows the views to handle
288
- * low level interactions such as dragging, wheeling, etc.
289
- *
290
- * @param {string} type
291
- * @param {InteractionEventListener} listener
292
- * @param {boolean} [useCapture]
293
- */
294
- addInteractionEventListener(type, listener, useCapture) {
295
- const listenersByType = useCapture
296
- ? this._capturingInteractionEventListeners
297
- : this._nonCapturingInteractionEventListeners;
298
- let listeners = listenersByType[type];
299
- if (!listeners) {
300
- listeners = [];
301
- listenersByType[type] = listeners;
302
- }
303
-
304
- listeners.push(listener);
305
- }
306
-
307
- /**
308
- * Visits child views in depth-first order. Visitor's return value
309
- * controls the traversal.
310
- *
311
- * @param {Visitor} visitor
312
- * @returns {VisitResult}
313
- *
314
- */
315
- visit(visitor) {
316
- try {
317
- const result = visitor(this);
318
-
319
- if (visitor.postOrder) {
320
- visitor.postOrder(this);
321
- }
322
-
323
- if (result !== VISIT_STOP) {
324
- return result;
325
- }
326
- } catch (e) {
327
- // Augment the exception with the view
328
- e.view = this;
329
- throw e;
330
- }
331
- }
332
-
333
- /**
334
- * Called after all scales in the view hierarchy have been resolved.
335
- */
336
- onScalesResolved() {
337
- // Only set the opacity function once. The idea is to allow custom functions
338
- // and prevent accidental overwrites.
339
- if (
340
- !this.opacityFunction ||
341
- this.opacityFunction === defaultOpacityFunction
342
- ) {
343
- this.opacityFunction = createViewOpacityFunction(this);
344
- }
345
- }
346
-
347
- /**
348
- * ViewRenderingContext calls this method once for each view during each rendering
349
- * pass. The order is depth first, pre order.
350
- */
351
- onBeforeRender() {
352
- //
353
- }
354
-
355
- /**
356
- * Recursively traverses the view hierarchy, computes the view coordinates,
357
- * and coordinates the mark rendering.
358
- *
359
- * @param {import("./renderingContext/viewRenderingContext").default} context
360
- * @param {import("../utils/layout/rectangle").default} coords The coordinate rectangle that the parent computed
361
- * for the child that is being visited.
362
- * @param {RenderingOptions} [options]
363
- */
364
- render(context, coords, options = {}) {
365
- // override
366
- }
367
-
368
- /**
369
- * Returns the encodings specified in this view combined with the inherited
370
- * encodings. However, this does not contain any defaults or inferred/adjusted/fixed
371
- * encodings. Those are available in Mark's encoding property.
372
- *
373
- * @return {import("../spec/channel").Encoding}
374
- */
375
- getEncoding() {
376
- const pe =
377
- this.parent && !this.blockEncodingInheritance
378
- ? this.parent.getEncoding()
379
- : {};
380
- const te = this.spec.encoding || {};
381
-
382
- /** @type {import("../spec/channel").Encoding} */
383
- const combined = {
384
- ...pe,
385
- ...te,
386
- };
387
-
388
- for (const [channel, channelDef] of Object.entries(combined)) {
389
- if (channelDef === null) {
390
- // Prevent propagation
391
- delete combined[channel];
392
- }
393
- }
394
-
395
- return combined;
396
- }
397
-
398
- /**
399
- * @param {View} [whoIsAsking] Passed to the immediate parent. Allows for
400
- * selectively breaking the inheritance.
401
- * @return {function(object):any}
402
- */
403
- getFacetAccessor(whoIsAsking) {
404
- if (this.parent) {
405
- return this.parent.getFacetAccessor(this);
406
- }
407
- }
408
-
409
- /**
410
- * Returns the fields that should be used for partitioning the data for facets.
411
- *
412
- * @param {View} [whoIsAsking]
413
- * @returns {string[]}
414
- */
415
- getFacetFields(whoIsAsking) {
416
- const sampleFieldDef = this.getEncoding().sample;
417
- if (isFieldDef(sampleFieldDef)) {
418
- return [sampleFieldDef.field];
419
- } else {
420
- return this.parent?.getFacetFields(this);
421
- }
422
- }
423
-
424
- /**
425
- * Returns a texture that has a mapping for the sample locations. This is implemented
426
- * only in the SampleView of GenomeSpy App.
427
- *
428
- * @returns {WebGLTexture}
429
- */
430
- getSampleFacetTexture() {
431
- return undefined;
432
- }
433
-
434
- /**
435
- *
436
- * @param {Channel} channel
437
- * @param {ResolutionTarget} type
438
- * @returns {ScaleResolution | AxisResolution}
439
- */
440
- _getResolution(channel, type) {
441
- channel = getPrimaryChannel(channel);
442
-
443
- /** @type {import("./view").default } */
444
- // eslint-disable-next-line consistent-this
445
- let view = this;
446
- do {
447
- const resolution = view.resolutions[type][channel];
448
- if (resolution) {
449
- return resolution;
450
- }
451
- view = view.parent;
452
- } while (view);
453
- }
454
-
455
- /**
456
- * @param {Channel} channel
457
- */
458
- getScaleResolution(channel) {
459
- return /** @type {ScaleResolution} */ (
460
- this._getResolution(channel, "scale")
461
- );
462
- }
463
-
464
- /**
465
- * @param {Channel} channel
466
- */
467
- getAxisResolution(channel) {
468
- return /** @type {AxisResolution} */ (
469
- this._getResolution(channel, "axis")
470
- );
471
- }
472
-
473
- /**
474
- * @returns {string}
475
- */
476
- getBaseUrl() {
477
- return appendToBaseUrl(
478
- () => this.parent?.getBaseUrl(),
479
- this.spec.baseUrl
480
- );
481
- }
482
-
483
- /**
484
- * @returns {import("../data/sources/dataSource").default}
485
- */
486
- getDynamicDataSource() {
487
- throw new Error("The view does not provide dynamic data!");
488
- }
489
-
490
- /**
491
- * Returns `true` if this view and its children supports picking.
492
- */
493
- isPickingSupported() {
494
- return true;
495
- }
496
-
497
- getTitleText() {
498
- const title = this.spec.title;
499
- if (title) {
500
- return isString(title) ? title : title.text;
501
- }
502
- }
503
-
504
- /**
505
- * @param {any} key string
506
- * @param {function(key?):T} callable A function that produces a value to be cached
507
- * @returns {T}
508
- * @template T
509
- */
510
- _cache(key, callable) {
511
- return getCachedOrCall(this, key, callable);
512
- }
513
-
514
- /**
515
- *
516
- * @param {string} key
517
- * @param {"self" | "progeny" | "ancestors"} [direction]
518
- */
519
- _invalidateCacheByPrefix(key, direction = "self") {
520
- switch (direction) {
521
- case "self":
522
- invalidatePrefix(this, key);
523
- break;
524
- case "ancestors":
525
- for (const view of this.getAncestors()) {
526
- invalidatePrefix(view, key);
527
- }
528
- break;
529
- case "progeny":
530
- this.visit((view) => invalidatePrefix(view, key));
531
- break;
532
- default:
533
- }
534
- }
535
-
536
- invalidateSizeCache() {
537
- this._invalidateCacheByPrefix("size/", "ancestors");
538
- }
539
-
540
- /**
541
- * Broadcasts a message to views that include the given (x, y) point.
542
- * This is mainly intended for mouse events.
543
- *
544
- * @param {import("../utils/interactionEvent").default} event
545
- */
546
- propagateInteractionEvent(event) {
547
- // Subclasses must implement proper handling
548
- }
549
- }
550
-
551
- /**
552
- *
553
- * @param {any} opacity
554
- * @returns {opacity is import("../spec/view").DynamicOpacity}
555
- */
556
- function isDynamicOpacity(opacity) {
557
- return "unitsPerPixel" in opacity;
558
- }
559
-
560
- /**
561
- *
562
- * @param {View} view
563
- * @returns {function(number):number}
564
- */
565
- function createViewOpacityFunction(view) {
566
- const opacityDef = view.spec.opacity;
567
-
568
- if (opacityDef !== undefined) {
569
- if (isNumber(opacityDef)) {
570
- return (parentOpacity) => parentOpacity * opacityDef;
571
- } else if (isDynamicOpacity(opacityDef)) {
572
- /** @type {function(Channel):any} */
573
- const getScale = (channel) => {
574
- const scale = view.getScaleResolution(channel)?.getScale();
575
- // Only works on linear scales
576
- if (["linear", "index", "locus"].includes(scale?.type)) {
577
- return scale;
578
- }
579
- };
580
-
581
- const scale = opacityDef.channel
582
- ? getScale(opacityDef.channel)
583
- : getScale("x") || getScale("y");
584
-
585
- if (!scale) {
586
- throw new Error(
587
- "Cannot find a resolved quantitative scale for dynamic opacity!"
588
- );
589
- }
590
-
591
- const interpolate = scaleLog()
592
- .domain(opacityDef.unitsPerPixel)
593
- .range(opacityDef.values)
594
- .clamp(true);
595
-
596
- return (parentOpacity) => {
597
- const rangeSpan = 1000; //TODO: span(scale.range());
598
- const unitsPerPixel = span(scale.domain()) / rangeSpan;
599
-
600
- return interpolate(unitsPerPixel) * parentOpacity;
601
- };
602
- }
603
- }
604
- return (parentOpacity) => parentOpacity;
605
- }
606
-
607
- /**
608
- *
609
- * @param {any} size
610
- * @return {size is import("../spec/view").Step}
611
- */
612
- export const isStepSize = (size) => !!size?.step;