@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
@@ -1,189 +0,0 @@
1
- import clientPoint from "../point";
2
- import { html, render } from "lit-html";
3
- import { peek } from "../arrayUtils";
4
-
5
- export const SUPPRESS_TOOLTIP_CLASS_NAME = "gs-suppress-tooltip";
6
-
7
- export default class Tooltip {
8
- /**
9
- * @param {HTMLElement} container
10
- */
11
- constructor(container) {
12
- this.container = container;
13
-
14
- this.element = document.createElement("div");
15
- this.element.className = "tooltip";
16
- this._visible = true;
17
- this.container.appendChild(this.element);
18
-
19
- /** @type {any} */
20
- this._previousTooltipDatum = undefined;
21
-
22
- this.enabledStack = [true];
23
-
24
- this._penaltyUntil = 0;
25
- /** @type {[number, number]} */
26
- this._lastCoords = undefined;
27
-
28
- this._previousMove = 0;
29
-
30
- this.clear();
31
- }
32
-
33
- /**
34
- * @param {boolean} visible
35
- */
36
- set visible(visible) {
37
- if (visible != this._visible) {
38
- this.element.style.display = visible ? null : "none";
39
- this._visible = visible;
40
- }
41
- }
42
-
43
- get visible() {
44
- return this._visible;
45
- }
46
-
47
- get enabled() {
48
- return peek(this.enabledStack) ?? true;
49
- }
50
-
51
- /**
52
- * @param {boolean} enabled True if tooltip is enabled (allowed to be shown)
53
- */
54
- pushEnabledState(enabled) {
55
- this.enabledStack.push(enabled);
56
- if (!enabled) {
57
- this.visible = false;
58
- }
59
- }
60
-
61
- popEnabledState() {
62
- this.enabledStack.pop();
63
- }
64
-
65
- /**
66
- * @param {MouseEvent} mouseEvent
67
- */
68
- handleMouseMove(mouseEvent) {
69
- this.mouseCoords = clientPoint(this.container, mouseEvent);
70
-
71
- const now = performance.now();
72
-
73
- // Prevent the tooltip from flashing briefly before it becomes penalized
74
- // because of a quickly moving mouse pointer
75
- if (
76
- !this.visible &&
77
- !this._isPenalty() &&
78
- now - this._previousMove > 500
79
- ) {
80
- this._penaltyUntil = now + 70;
81
- }
82
-
83
- // Disable the tooltip for a while if the mouse is being moved very quickly.
84
- // Makes the tooltip less annoying.
85
- // TODO: Should calculate speed: pixels per millisecond or something
86
- if (
87
- this._lastCoords &&
88
- distance(this.mouseCoords, this._lastCoords) > 20
89
- ) {
90
- this._penaltyUntil = now + 400;
91
- }
92
-
93
- this._lastCoords = this.mouseCoords;
94
-
95
- if (this.visible) {
96
- this.updatePlacement();
97
- }
98
-
99
- this._previousMove = now;
100
- }
101
-
102
- updatePlacement() {
103
- /** Space between pointer and tooltip box */
104
- const spacing = 20;
105
-
106
- const [mouseX, mouseY] = this.mouseCoords;
107
-
108
- let x = mouseX + spacing;
109
- if (x > this.container.clientWidth - this.element.offsetWidth) {
110
- x = mouseX - spacing - this.element.offsetWidth;
111
- }
112
- this.element.style.left = x + "px";
113
-
114
- this.element.style.top =
115
- Math.min(
116
- mouseY + spacing,
117
- this.container.clientHeight - this.element.offsetHeight
118
- ) + "px";
119
- }
120
-
121
- /**
122
- * @param {string | import("lit").TemplateResult | HTMLElement} content
123
- */
124
- setContent(content) {
125
- if (!content || !this.enabled || this._isPenalty()) {
126
- if (this.visible) {
127
- render("", this.element);
128
- this.visible = false;
129
- }
130
- this._previousTooltipDatum = undefined;
131
- return;
132
- }
133
-
134
- render(content, this.element);
135
-
136
- this.visible = true;
137
-
138
- this.updatePlacement();
139
- }
140
-
141
- clear() {
142
- this._previousTooltipDatum = undefined;
143
- this.setContent(undefined);
144
- }
145
-
146
- /**
147
- * Updates the tooltip if the provided datum differs from the previous one.
148
- * Otherwise this is nop.
149
- *
150
- * @param {T} datum
151
- * @param {function(T):Promise<string | HTMLElement | import("lit").TemplateResult>} [converter]
152
- * @template T
153
- */
154
- updateWithDatum(datum, converter) {
155
- if (datum !== this._previousTooltipDatum) {
156
- this._previousTooltipDatum = datum;
157
- if (!converter) {
158
- converter = (d) =>
159
- Promise.resolve(html` ${JSON.stringify(d)} `);
160
- }
161
-
162
- converter(datum)
163
- .then((result) => this.setContent(result))
164
- .catch((error) => {
165
- if (error !== "debounced") {
166
- throw error;
167
- }
168
- });
169
- }
170
- }
171
-
172
- _isPenalty() {
173
- return this._penaltyUntil && this._penaltyUntil > performance.now();
174
- }
175
- }
176
-
177
- /**
178
- * Calculate euclidean distance
179
- *
180
- * @param {number[]} a
181
- * @param {number[]} b
182
- */
183
- function distance(a, b) {
184
- let sum = 0;
185
- for (let i = 0; i < a.length; i++) {
186
- sum += (a[i] - b[i]) ** 2;
187
- }
188
- return Math.sqrt(sum);
189
- }
package/src/utils/url.js DELETED
@@ -1,22 +0,0 @@
1
- const protoRe = /^([A-Za-z]+:)?\/\//;
2
-
3
- /**
4
- * Append a relative or absolute url to a base url.
5
- * The base part is omitted if the append part is absolute.
6
- *
7
- * @param {function():string} baseAccessor
8
- * @param {string} append
9
- */
10
- export function appendToBaseUrl(baseAccessor, append) {
11
- if (append && protoRe.test(append)) {
12
- return append;
13
- }
14
-
15
- const base = baseAccessor();
16
-
17
- if (base && append) {
18
- return base.endsWith("/") ? base + append : base + "/" + append;
19
- }
20
-
21
- return base ?? append;
22
- }
@@ -1,24 +0,0 @@
1
- import { isBoolean, isNumber, isString } from "vega-util";
2
-
3
- /** A set of typical NA values */
4
- export const NAs = new Set(["", "NA", ".", "-"]);
5
-
6
- /**
7
- * Tests whether the given array of strings can be interpreted as a numeric vector
8
- *
9
- * @param {string[]} values
10
- */
11
- export function inferNumeric(values) {
12
- return values
13
- .filter((value) => typeof value == "string")
14
- .filter((value) => !NAs.has(value))
15
- .every((value) => /^[+-]?\d+(\.\d*)?$/.test(value));
16
- }
17
-
18
- /**
19
- * @param {any} value
20
- * @returns {value is string | number | boolean}
21
- */
22
- export function isScalar(value) {
23
- return isString(value) || isNumber(value) || isBoolean(value);
24
- }
@@ -1,13 +0,0 @@
1
- import { expect, test } from "vitest";
2
- import * as vt from "./variableTools";
3
-
4
- test("InferNumerality", () => {
5
- expect(vt.inferNumeric(["0", "1", "2.2", "-4"])).toBeTruthy();
6
- expect(vt.inferNumeric(["0", ...vt.NAs.values()])).toBeTruthy();
7
- expect(vt.inferNumeric([])).toBeTruthy();
8
-
9
- expect(vt.inferNumeric(["0", "x"])).toBeFalsy();
10
- expect(vt.inferNumeric(["0", " "])).toBeFalsy();
11
- expect(vt.inferNumeric(["0", "1,2"])).toBeFalsy();
12
- expect(vt.inferNumeric(["0", "20x"])).toBeFalsy();
13
- });
@@ -1,140 +0,0 @@
1
- import { isString } from "vega-util";
2
- import {
3
- getChannelDefWithScale,
4
- getPrimaryChannel,
5
- isExprDef,
6
- isFieldDef,
7
- isSecondaryChannel,
8
- isValueDef,
9
- } from "../encoder/encoder";
10
- import { peek } from "../utils/arrayUtils";
11
- import coalesce from "../utils/coalesce";
12
-
13
- import mergeObjects from "../utils/mergeObjects";
14
- import { getCachedOrCall } from "../utils/propertyCacher";
15
-
16
- /**
17
- *
18
- * @typedef { import("./unitView").default} UnitView
19
- */
20
- export default class AxisResolution {
21
- /**
22
- * @param {import("../spec/channel").Channel} channel
23
- */
24
- constructor(channel) {
25
- this.channel = channel;
26
- /** @type {import("./scaleResolution").ResolutionMember<import("../spec/channel").PositionalChannel>[]} The involved views */
27
- this.members = [];
28
- }
29
-
30
- get scaleResolution() {
31
- return peek(this.members)?.view.getScaleResolution(this.channel);
32
- }
33
-
34
- /**
35
- * N.B. This is expected to be called in depth-first order, AFTER the
36
- * scales have been resolved.
37
- *
38
- * @param {UnitView} view
39
- * @param {import("../spec/channel").PositionalChannel} channel TODO: Do something for this
40
- */
41
- pushUnitView(view, channel) {
42
- const newScaleResolution = view.getScaleResolution(this.channel);
43
-
44
- if (!newScaleResolution) {
45
- throw new Error("Cannot find a scale resolution!");
46
- }
47
-
48
- if (
49
- this.scaleResolution &&
50
- newScaleResolution !== this.scaleResolution
51
- ) {
52
- throw new Error("Shared axes must have a shared scale!");
53
- }
54
-
55
- this.members.push({ view, channel });
56
- }
57
-
58
- getAxisProps() {
59
- return getCachedOrCall(this, "axisProps", () => {
60
- const propArray = this.members.map((member) => {
61
- const channelDef = member.view.mark.encoding[member.channel];
62
- return "axis" in channelDef && channelDef.axis;
63
- });
64
-
65
- if (
66
- propArray.length > 0 &&
67
- propArray.some((props) => props === null)
68
- ) {
69
- // No axis whatsoever is wanted
70
- return null;
71
- } else {
72
- return /** @type { import("../spec/axis").Axis} */ (
73
- mergeObjects(
74
- propArray.filter((props) => props !== undefined),
75
- "axis",
76
- ["title"]
77
- )
78
- );
79
- }
80
- });
81
- }
82
-
83
- getTitle() {
84
- /** @param {import("./scaleResolution").ResolutionMember} member} */
85
- const computeTitle = (member) => {
86
- const channelDef = getChannelDefWithScale(
87
- member.view,
88
- member.channel
89
- );
90
-
91
- if (isValueDef(channelDef)) {
92
- return undefined;
93
- }
94
-
95
- // Retain nulls as they indicate that no title should be shown
96
-
97
- return {
98
- member,
99
- explicitTitle: coalesce(
100
- channelDef.axis?.title,
101
- channelDef.title
102
- ),
103
- implicitTitle: coalesce(
104
- isFieldDef(channelDef) ? channelDef.field : undefined,
105
- isExprDef(channelDef) ? channelDef.expr : undefined
106
- ),
107
- };
108
- };
109
-
110
- const titles = this.members.map(computeTitle);
111
-
112
- // Skip implicit secondary channel titles if the primary channel has an explicit title
113
- const filteredTitles = titles.filter((title) => {
114
- if (
115
- isSecondaryChannel(title.member.channel) &&
116
- !title.explicitTitle
117
- ) {
118
- const primaryChannel = getPrimaryChannel(title.member.channel);
119
- return (
120
- titles.find(
121
- (title2) =>
122
- title2.member.view == title.member.view &&
123
- title2.member.channel == primaryChannel
124
- )?.explicitTitle === undefined
125
- );
126
- }
127
- return true;
128
- });
129
-
130
- const uniqueTitles = new Set(
131
- filteredTitles
132
- .map((title) =>
133
- coalesce(title.explicitTitle, title.implicitTitle)
134
- )
135
- .filter(isString)
136
- );
137
-
138
- return uniqueTitles.size ? [...uniqueTitles].join(", ") : null;
139
- }
140
- }
@@ -1,201 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
- import { createAndInitialize } from "./testUtils";
3
- import UnitView from "./unitView";
4
- import View from "./view";
5
-
6
- /** @type {import("../spec/view").LayerSpec} */
7
- const spec = {
8
- data: { values: [] },
9
- layer: [
10
- {
11
- mark: "point",
12
- encoding: {
13
- x: { field: "a", type: "quantitative" },
14
- y: {
15
- field: "a",
16
- type: "quantitative",
17
- scale: { domain: [1, 2] },
18
- },
19
- color: { value: "red" },
20
- },
21
- },
22
- {
23
- mark: "point",
24
- encoding: {
25
- x: { field: "a", type: "quantitative" },
26
- y: {
27
- field: "b",
28
- type: "quantitative",
29
- scale: { domain: [4, 5] },
30
- },
31
- color: { value: "green" },
32
- },
33
- },
34
- ],
35
- };
36
-
37
- describe("Axes resolve properly", () => {
38
- const sharedSpec = {
39
- ...spec,
40
- resolve: { scale: { y: "shared" }, axis: { y: "shared" } },
41
- };
42
-
43
- test("Independent axes are independent", async () => {
44
- const independentSpec = {
45
- ...spec,
46
- resolve: { scale: { y: "shared" }, axis: { y: "independent" } },
47
- };
48
-
49
- const view = await createAndInitialize(independentSpec, View);
50
- const [r0, r1] = [0, 1].map((i) =>
51
- view.children[i].getAxisResolution("y")
52
- );
53
-
54
- expect(r0).toBeDefined();
55
- expect(r1).toBeDefined();
56
- expect(r0).not.toBe(r1);
57
- });
58
-
59
- test("Shared axes have joined titles", async () => {
60
- const view = await createAndInitialize(sharedSpec, View);
61
- expect(view.children[0].getAxisResolution("y").getTitle()).toEqual(
62
- "a, b"
63
- );
64
- });
65
-
66
- test("Title is taken from axis title, encoding title, and field name, in that order.", async () => {
67
- let view = await createAndInitialize(
68
- {
69
- data: { values: [] },
70
- mark: "point",
71
- encoding: {
72
- x: { field: "a", type: "quantitative" },
73
- y: {
74
- field: "a",
75
- type: "quantitative",
76
- },
77
- },
78
- },
79
- UnitView
80
- );
81
- expect(view.getAxisResolution("y").getTitle()).toEqual("a");
82
-
83
- view = await createAndInitialize(
84
- {
85
- data: { values: [] },
86
- mark: "point",
87
- encoding: {
88
- x: { field: "a", type: "quantitative" },
89
- y: {
90
- field: "a",
91
- title: "x",
92
- type: "quantitative",
93
- },
94
- },
95
- },
96
- UnitView
97
- );
98
- expect(view.getAxisResolution("y").getTitle()).toEqual("x");
99
-
100
- view = await createAndInitialize(
101
- {
102
- data: { values: [] },
103
- mark: "point",
104
- encoding: {
105
- x: { field: "a", type: "quantitative" },
106
- y: {
107
- field: "a",
108
- title: "x",
109
- type: "quantitative",
110
- axis: {
111
- title: "z",
112
- },
113
- },
114
- },
115
- },
116
- UnitView
117
- );
118
- expect(view.getAxisResolution("y").getTitle()).toEqual("z");
119
- });
120
-
121
- test("Primary and secondary channels are included in the title", async () => {
122
- let view = await createAndInitialize(
123
- {
124
- data: { values: [] },
125
- mark: "rule",
126
- encoding: {
127
- x: { field: "a", type: "quantitative" },
128
- x2: { field: "b" },
129
- },
130
- },
131
- UnitView
132
- );
133
- expect(view.getAxisResolution("x").getTitle()).toEqual("a, b");
134
- });
135
-
136
- test("Secondary channel's field name is hidden if primary channel has an explicit title", async () => {
137
- let view = await createAndInitialize(
138
- {
139
- data: { values: [] },
140
- mark: "rule",
141
- encoding: {
142
- x: { field: "a", type: "quantitative", title: "foo" },
143
- x2: { field: "b" },
144
- },
145
- },
146
- UnitView
147
- );
148
- expect(view.getAxisResolution("x").getTitle()).toEqual("foo");
149
-
150
- let view2 = await createAndInitialize(
151
- {
152
- data: { values: [] },
153
- mark: "rule",
154
- encoding: {
155
- x: {
156
- field: "a",
157
- type: "quantitative",
158
- axis: { title: "foo" },
159
- },
160
- x2: { field: "b" },
161
- },
162
- },
163
- UnitView
164
- );
165
- expect(view2.getAxisResolution("x").getTitle()).toEqual("foo");
166
-
167
- let view3 = await createAndInitialize(
168
- {
169
- data: { values: [] },
170
- mark: "rule",
171
- encoding: {
172
- x: {
173
- field: "a",
174
- type: "quantitative",
175
- axis: { title: "foo" },
176
- },
177
- x2: { field: "b", title: "bar" },
178
- },
179
- },
180
- UnitView
181
- );
182
- expect(view3.getAxisResolution("x").getTitle()).toEqual("foo, bar");
183
-
184
- let view4 = await createAndInitialize(
185
- {
186
- data: { values: [] },
187
- mark: "rule",
188
- encoding: {
189
- x: {
190
- field: "a",
191
- type: "quantitative",
192
- title: null,
193
- },
194
- x2: { field: "b" },
195
- },
196
- },
197
- UnitView
198
- );
199
- expect(view4.getAxisResolution("x").getTitle()).toBeNull();
200
- });
201
- });