@genome-spy/core 0.14.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 (226) hide show
  1. package/dist/index.js +224 -0
  2. package/dist/style.css +1 -0
  3. package/package.json +54 -0
  4. package/src/data/collector.js +178 -0
  5. package/src/data/collector.test.js +82 -0
  6. package/src/data/dataFlow.js +109 -0
  7. package/src/data/dataFlow.test.js +3 -0
  8. package/src/data/facetNode.js +17 -0
  9. package/src/data/flow.test.js +71 -0
  10. package/src/data/flowBatch.d.ts +40 -0
  11. package/src/data/flowNode.js +283 -0
  12. package/src/data/flowNode.test.js +49 -0
  13. package/src/data/flowOptimizer.js +117 -0
  14. package/src/data/flowOptimizer.test.js +192 -0
  15. package/src/data/flowTestUtils.js +63 -0
  16. package/src/data/formats/fasta.js +32 -0
  17. package/src/data/formats/fasta.test.js +26 -0
  18. package/src/data/sources/dataSource.js +22 -0
  19. package/src/data/sources/dataSourceFactory.js +24 -0
  20. package/src/data/sources/dataUtils.js +31 -0
  21. package/src/data/sources/dynamicCallbackSource.js +56 -0
  22. package/src/data/sources/dynamicSource.js +36 -0
  23. package/src/data/sources/inlineSource.js +69 -0
  24. package/src/data/sources/inlineSource.test.js +55 -0
  25. package/src/data/sources/namedSource.js +74 -0
  26. package/src/data/sources/sequenceSource.js +46 -0
  27. package/src/data/sources/sequenceSource.test.js +45 -0
  28. package/src/data/sources/urlSource.js +74 -0
  29. package/src/data/transforms/aggregate.js +69 -0
  30. package/src/data/transforms/clone.js +40 -0
  31. package/src/data/transforms/clone.test.js +10 -0
  32. package/src/data/transforms/coverage.js +187 -0
  33. package/src/data/transforms/coverage.test.js +122 -0
  34. package/src/data/transforms/filter.js +37 -0
  35. package/src/data/transforms/filter.test.js +17 -0
  36. package/src/data/transforms/filterScoredLabels.js +134 -0
  37. package/src/data/transforms/flattenCompressedExons.js +57 -0
  38. package/src/data/transforms/flattenDelimited.js +68 -0
  39. package/src/data/transforms/flattenDelimited.test.js +86 -0
  40. package/src/data/transforms/flattenSequence.js +39 -0
  41. package/src/data/transforms/flattenSequence.test.js +33 -0
  42. package/src/data/transforms/formula.js +39 -0
  43. package/src/data/transforms/formula.test.js +18 -0
  44. package/src/data/transforms/identifier.js +108 -0
  45. package/src/data/transforms/identifier.test.js +82 -0
  46. package/src/data/transforms/linearizeGenomicCoordinate.js +101 -0
  47. package/src/data/transforms/measureText.js +44 -0
  48. package/src/data/transforms/pileup.js +128 -0
  49. package/src/data/transforms/pileup.test.js +69 -0
  50. package/src/data/transforms/project.js +41 -0
  51. package/src/data/transforms/project.test.js +31 -0
  52. package/src/data/transforms/regexExtract.js +61 -0
  53. package/src/data/transforms/regexExtract.test.js +66 -0
  54. package/src/data/transforms/regexFold.js +141 -0
  55. package/src/data/transforms/regexFold.test.js +159 -0
  56. package/src/data/transforms/sample.js +101 -0
  57. package/src/data/transforms/sample.test.js +37 -0
  58. package/src/data/transforms/stack.js +137 -0
  59. package/src/data/transforms/stack.test.js +90 -0
  60. package/src/data/transforms/transformFactory.js +60 -0
  61. package/src/encoder/accessor.js +82 -0
  62. package/src/encoder/accessor.test.js +46 -0
  63. package/src/encoder/encoder.js +369 -0
  64. package/src/encoder/encoder.test.js +97 -0
  65. package/src/fonts/Lato-Regular.json +1267 -0
  66. package/src/fonts/Lato-Regular.png +0 -0
  67. package/src/fonts/OFL.txt +93 -0
  68. package/src/fonts/README.md +3 -0
  69. package/src/fonts/bmFont.d.ts +58 -0
  70. package/src/fonts/bmFontManager.js +357 -0
  71. package/src/fonts/bmFontMetrics.js +108 -0
  72. package/src/genome/genome.js +305 -0
  73. package/src/genome/genome.test.js +152 -0
  74. package/src/genome/genomeStore.js +54 -0
  75. package/src/genome/locusFormat.js +31 -0
  76. package/src/genome/scaleIndex.js +199 -0
  77. package/src/genome/scaleIndex.test.js +61 -0
  78. package/src/genome/scaleLocus.js +112 -0
  79. package/src/genome/scaleLocus.test.js +3 -0
  80. package/src/genomeSpy.js +753 -0
  81. package/src/gl/arrayBuilder.js +199 -0
  82. package/src/gl/dataToVertices.js +621 -0
  83. package/src/gl/includes/common.glsl +63 -0
  84. package/src/gl/includes/fp64-arithmetic.glsl +187 -0
  85. package/src/gl/includes/fp64-utils.js +132 -0
  86. package/src/gl/includes/picking.fragment.glsl +3 -0
  87. package/src/gl/includes/picking.vertex.glsl +29 -0
  88. package/src/gl/includes/sampleFacet.glsl +107 -0
  89. package/src/gl/includes/scales.glsl +79 -0
  90. package/src/gl/includes/scales_fp64.glsl +30 -0
  91. package/src/gl/link.fragment.glsl +18 -0
  92. package/src/gl/link.vertex.glsl +111 -0
  93. package/src/gl/point.fragment.glsl +123 -0
  94. package/src/gl/point.vertex.glsl +128 -0
  95. package/src/gl/rect.fragment.glsl +51 -0
  96. package/src/gl/rect.vertex.glsl +114 -0
  97. package/src/gl/rule.fragment.glsl +52 -0
  98. package/src/gl/rule.vertex.glsl +89 -0
  99. package/src/gl/text.fragment.glsl +31 -0
  100. package/src/gl/text.vertex.glsl +246 -0
  101. package/src/gl/webGLHelper.js +490 -0
  102. package/src/img/bowtie.svg +1 -0
  103. package/src/img/genomespy-favicon.svg +34 -0
  104. package/src/index.html +11 -0
  105. package/src/index.js +151 -0
  106. package/src/marks/link.js +189 -0
  107. package/src/marks/mark.js +867 -0
  108. package/src/marks/markUtils.js +109 -0
  109. package/src/marks/pointMark.js +279 -0
  110. package/src/marks/rectMark.js +236 -0
  111. package/src/marks/rule.js +231 -0
  112. package/src/marks/text.js +274 -0
  113. package/src/options.d.ts +9 -0
  114. package/src/scale/colorUtils.js +184 -0
  115. package/src/scale/glslScaleGenerator.js +462 -0
  116. package/src/scale/scale.js +441 -0
  117. package/src/scale/scale.test.js +323 -0
  118. package/src/scale/ticks.js +198 -0
  119. package/src/scale/ticks.test.js +39 -0
  120. package/src/singlePageApp.js +13 -0
  121. package/src/spec/axis.d.ts +296 -0
  122. package/src/spec/channel.d.ts +127 -0
  123. package/src/spec/data.d.ts +185 -0
  124. package/src/spec/font.d.ts +15 -0
  125. package/src/spec/genome.d.ts +35 -0
  126. package/src/spec/mark.d.ts +432 -0
  127. package/src/spec/root.d.ts +22 -0
  128. package/src/spec/scale.d.ts +265 -0
  129. package/src/spec/tooltip.d.ts +9 -0
  130. package/src/spec/transform.d.ts +479 -0
  131. package/src/spec/view.d.ts +215 -0
  132. package/src/styles/genome-spy.scss +153 -0
  133. package/src/tooltip/dataTooltipHandler.js +59 -0
  134. package/src/tooltip/refseqGeneTooltipHandler.js +77 -0
  135. package/src/tooltip/tooltipHandler.ts +12 -0
  136. package/src/types/filetypes.d.ts +4 -0
  137. package/src/types/flatqueue.d.ts +53 -0
  138. package/src/types/glsl.d.ts +4 -0
  139. package/src/types/object.d.ts +21 -0
  140. package/src/types/vega-scale.d.ts +60 -0
  141. package/src/utils/animator.js +83 -0
  142. package/src/utils/arrayUtils.js +55 -0
  143. package/src/utils/binnedRangeIndex.js +83 -0
  144. package/src/utils/clamp.js +8 -0
  145. package/src/utils/cloner.js +32 -0
  146. package/src/utils/cloner.test.js +23 -0
  147. package/src/utils/coalesce.js +11 -0
  148. package/src/utils/coalesce.test.js +15 -0
  149. package/src/utils/concatIterables.js +26 -0
  150. package/src/utils/concatIterables.test.js +7 -0
  151. package/src/utils/debounce.js +37 -0
  152. package/src/utils/domainArray.js +224 -0
  153. package/src/utils/domainArray.test.js +129 -0
  154. package/src/utils/eerp.js +13 -0
  155. package/src/utils/expression.js +32 -0
  156. package/src/utils/field.js +28 -0
  157. package/src/utils/fisheye.js +60 -0
  158. package/src/utils/formatObject.js +31 -0
  159. package/src/utils/html.js +23 -0
  160. package/src/utils/html.test.js +13 -0
  161. package/src/utils/indexer.js +43 -0
  162. package/src/utils/indexer.test.js +46 -0
  163. package/src/utils/inertia.js +124 -0
  164. package/src/utils/interactionEvent.js +33 -0
  165. package/src/utils/iterateNestedMaps.js +21 -0
  166. package/src/utils/iterateNestedMaps.test.js +32 -0
  167. package/src/utils/kWayMerge.js +42 -0
  168. package/src/utils/kWayMerge.test.js +25 -0
  169. package/src/utils/layout/flexLayout.js +336 -0
  170. package/src/utils/layout/flexLayout.test.js +296 -0
  171. package/src/utils/layout/padding.js +107 -0
  172. package/src/utils/layout/point.js +23 -0
  173. package/src/utils/layout/rectangle.js +282 -0
  174. package/src/utils/layout/rectangle.test.js +171 -0
  175. package/src/utils/mergeObjects.js +99 -0
  176. package/src/utils/mergeObjects.test.js +41 -0
  177. package/src/utils/numberExtractor.js +24 -0
  178. package/src/utils/numberExtractor.test.js +5 -0
  179. package/src/utils/point.js +14 -0
  180. package/src/utils/propertyCacher.js +70 -0
  181. package/src/utils/propertyCacher.test.js +84 -0
  182. package/src/utils/propertyCoalescer.js +37 -0
  183. package/src/utils/propertyCoalescer.test.js +21 -0
  184. package/src/utils/reservationMap.js +103 -0
  185. package/src/utils/reservationMap.test.js +19 -0
  186. package/src/utils/scaleNull.js +19 -0
  187. package/src/utils/setOperations.js +75 -0
  188. package/src/utils/smoothstep.js +10 -0
  189. package/src/utils/throttle.js +34 -0
  190. package/src/utils/topK.js +76 -0
  191. package/src/utils/topK.test.js +63 -0
  192. package/src/utils/transition.js +74 -0
  193. package/src/utils/ui/tooltip.js +189 -0
  194. package/src/utils/url.js +22 -0
  195. package/src/utils/variableTools.js +24 -0
  196. package/src/utils/variableTools.test.js +12 -0
  197. package/src/view/axisResolution.js +135 -0
  198. package/src/view/axisResolution.test.js +200 -0
  199. package/src/view/axisView.js +746 -0
  200. package/src/view/channel.js +5 -0
  201. package/src/view/concatView.js +296 -0
  202. package/src/view/containerView.js +141 -0
  203. package/src/view/decoratorView.js +510 -0
  204. package/src/view/facetView.js +488 -0
  205. package/src/view/flowBuilder.js +362 -0
  206. package/src/view/flowBuilder.test.js +124 -0
  207. package/src/view/importView.js +19 -0
  208. package/src/view/layerView.js +60 -0
  209. package/src/view/rendering.d.ts +44 -0
  210. package/src/view/renderingContext/compositeViewRenderingContext.js +51 -0
  211. package/src/view/renderingContext/deferredViewRenderingContext.js +174 -0
  212. package/src/view/renderingContext/layoutRecorderViewRenderingContext.js +128 -0
  213. package/src/view/renderingContext/simpleViewRenderingContext.js +62 -0
  214. package/src/view/renderingContext/svgViewRenderingContext.js +121 -0
  215. package/src/view/renderingContext/viewRenderingContext.js +41 -0
  216. package/src/view/scaleResolution.js +756 -0
  217. package/src/view/scaleResolution.test.js +571 -0
  218. package/src/view/scaleResolutionApi.d.ts +40 -0
  219. package/src/view/testUtils.js +48 -0
  220. package/src/view/unitView.js +368 -0
  221. package/src/view/view.js +589 -0
  222. package/src/view/view.test.js +213 -0
  223. package/src/view/viewContext.d.ts +57 -0
  224. package/src/view/viewFactory.js +179 -0
  225. package/src/view/viewFactory.test.js +16 -0
  226. package/src/view/viewUtils.js +420 -0
@@ -0,0 +1,323 @@
1
+ /*!
2
+ * Adapted from vega-encode:
3
+ * https://github.com/vega/vega/blob/master/packages/vega-encode/test/scale-test.js
4
+ *
5
+ * Copyright (c) 2015-2018, University of Washington Interactive Data Lab
6
+ * All rights reserved.
7
+ *
8
+ * BSD-3-Clause License: https://github.com/vega/vega-lite/blob/master/LICENSE
9
+ */
10
+
11
+ /* eslint-disable */
12
+
13
+ import * as util from "vega-util";
14
+ import * as vs from "vega-scale";
15
+ import createScale from "./scale";
16
+
17
+ // Suppress warnings by default
18
+ const scale = (params, logger) =>
19
+ createScale(params, logger || { warn: () => {} });
20
+
21
+ test("Scale respects domain configuration", function () {
22
+ var s,
23
+ params = {
24
+ type: "linear",
25
+ domain: [1, 9.5],
26
+ };
27
+
28
+ // test zero inclusion
29
+ s = scale(params);
30
+ expect(s.domain()).toEqual([0, 9.5]);
31
+ s = scale(util.extend({ zero: true }, params));
32
+ expect(s.domain()).toEqual([0, 9.5]);
33
+ s = scale(util.extend({ zero: false }, params));
34
+ expect(s.domain()).toEqual([1, 9.5]);
35
+
36
+ // test nice domain
37
+ s = scale(util.extend({ nice: true }, params));
38
+ expect(s.domain()).toEqual([0, 10]);
39
+
40
+ // test domain min/max
41
+ s = scale(util.extend({ domainMin: -1, domainMax: 10 }, params));
42
+ expect(s.domain()).toEqual([-1, 10]);
43
+
44
+ // domain min overrides zero
45
+ s = scale(
46
+ util.extend({ zero: true, domainMin: 0.5, domainMax: 10 }, params)
47
+ );
48
+ expect(s.domain()).toEqual([0.5, 10]);
49
+
50
+ // test domain mid
51
+ s = scale(util.extend({ domainMid: 5 }, params));
52
+ expect(s.domain()).toEqual([0, 5, 9.5]);
53
+
54
+ // test domain raw
55
+ s = scale(util.extend({ domainRaw: [2, 11] }, params));
56
+ expect(s.domain()).toEqual([2, 11]);
57
+ });
58
+
59
+ test("Scale respects domain padding", function () {
60
+ var d;
61
+
62
+ // test linear scale padding
63
+ d = scale({
64
+ type: "linear",
65
+ domain: [5, 95],
66
+ range: [0, 100],
67
+ padding: 5,
68
+ zero: false,
69
+ }).domain();
70
+ expect(d).toEqual([0, 100]);
71
+
72
+ // test log scale padding
73
+ d = scale({
74
+ type: "log",
75
+ domain: [1, 10],
76
+ range: [0, 60],
77
+ padding: 20,
78
+ zero: false,
79
+ }).domain();
80
+ expect(Math.abs(d[0] - 0.1) < 1e-8).toBeTruthy();
81
+ expect(Math.abs(d[1] - 100) < 1e-8).toBeTruthy();
82
+
83
+ // test sqrt scale padding
84
+ d = scale({
85
+ type: "sqrt",
86
+ domain: [2 * 2, 3 * 3],
87
+ range: [0, 60],
88
+ padding: 20,
89
+ zero: false,
90
+ }).domain();
91
+ expect(Math.abs(d[0] - 1 * 1) < 1e-8).toBeTruthy();
92
+ expect(Math.abs(d[1] - 4 * 4) < 1e-8).toBeTruthy();
93
+
94
+ // test power scale padding
95
+ d = scale({
96
+ type: "pow",
97
+ exponent: 1 / 3,
98
+ domain: [2 * 2 * 2, 3 * 3 * 3],
99
+ range: [0, 60],
100
+ padding: 20,
101
+ zero: false,
102
+ }).domain();
103
+ expect(Math.abs(d[0] - 1 * 1 * 1) < 1e-8).toBeTruthy();
104
+ expect(Math.abs(d[1] - 4 * 4 * 4) < 1e-8).toBeTruthy();
105
+ });
106
+
107
+ test("Ordinal scale respects domainImplicit", function () {
108
+ var s,
109
+ params = {
110
+ type: "ordinal",
111
+ domain: [],
112
+ range: ["a", "b", "c"],
113
+ };
114
+
115
+ s = scale(params);
116
+ expect(s("foo")).toBe(undefined);
117
+ expect(s("bar")).toBe(undefined);
118
+ expect(s("foo")).toBe(undefined);
119
+
120
+ s = scale(util.extend({ domainImplicit: false }, params));
121
+ expect(s("foo")).toBe(undefined);
122
+ expect(s("bar")).toBe(undefined);
123
+ expect(s("foo")).toBe(undefined);
124
+
125
+ s = scale(util.extend({ domainImplicit: true }, params));
126
+ expect(s("foo")).toBe("a");
127
+ expect(s("bar")).toBe("b");
128
+ expect(s("foo")).toBe("a");
129
+ });
130
+
131
+ test("Scale respects range configuration", function () {
132
+ var s,
133
+ params = {
134
+ type: "linear",
135
+ domain: [0, 10],
136
+ range: [0, 10],
137
+ };
138
+
139
+ // round
140
+ s = scale(params);
141
+ expect(s(0.5)).toBe(0.5);
142
+ s = scale(util.extend({ round: true }, params));
143
+ expect(s(0.5)).toBe(1);
144
+
145
+ // reverse
146
+ s = scale(util.extend({ reverse: true }, params));
147
+ expect(s.range()).toEqual([10, 0]);
148
+
149
+ // rangeStep
150
+ params = {
151
+ type: "band",
152
+ domain: ["a", "b", "c"],
153
+ rangeStep: 20,
154
+ padding: 0,
155
+ };
156
+ s = scale(params);
157
+ expect(s.range()).toEqual([0, 60]);
158
+ expect(s.bandwidth()).toBe(20);
159
+
160
+ s = expect(function () {
161
+ scale(util.extend({}, params, { type: "linear" }));
162
+ }).toThrow();
163
+ });
164
+
165
+ test("Scale respects range color schemes", function () {
166
+ var s, u, v;
167
+
168
+ // performs scheme lookup
169
+ s = scale({ type: "ordinal", scheme: "category10" });
170
+ expect(s.range().length).toBe(10);
171
+
172
+ // throws on invalid scheme
173
+ expect(function () {
174
+ scale({ type: "ordinal", scheme: "foobarbaz" });
175
+ }).toThrow();
176
+ expect(function () {
177
+ scale({ type: "sequential", scheme: "foobarbaz" });
178
+ }).toThrow();
179
+
180
+ // handles interpolating schemes and extents
181
+ s = scale({ type: "sequential", scheme: "viridis" });
182
+ u = s.interpolator();
183
+ expect(typeof u).toBe("function");
184
+
185
+ s = scale({
186
+ type: "sequential",
187
+ scheme: "viridis",
188
+ schemeExtent: [0.2, 0.9],
189
+ });
190
+ v = s.interpolator();
191
+ expect(typeof v).toBe("function");
192
+ expect(v(0)).toBe(u(0.2));
193
+ expect(v(1)).toBe(u(0.9));
194
+
195
+ s = scale({
196
+ type: "sequential",
197
+ scheme: "viridis",
198
+ schemeExtent: [0.2, 0.9],
199
+ reverse: true,
200
+ });
201
+ v = s.interpolator();
202
+ expect(typeof v).toBe("function");
203
+ expect(v(0)).toBe(u(0.9));
204
+ expect(v(1)).toBe(u(0.2));
205
+
206
+ // generate interpolator as needed
207
+ s = scale({ type: "sequential", range: ["#000", "#f00"] });
208
+ v = s.interpolator();
209
+ expect(typeof v).toBe("function");
210
+ expect(v(0)).toBe("rgb(0, 0, 0)");
211
+ expect(v(1)).toBe("rgb(255, 0, 0)");
212
+
213
+ // quantize to provided scheme count
214
+ s = scale({ type: "quantize", scheme: "viridis", schemeCount: 3 });
215
+ v = s.range();
216
+ expect(v.length).toBe(3);
217
+ expect(v[0]).toBe(u(1 / 4));
218
+ expect(v[1]).toBe(u(2 / 4));
219
+ expect(v[2]).toBe(u(3 / 4));
220
+ });
221
+
222
+ test("Scale warns for zero in log domain", function () {
223
+ function logScale(domain) {
224
+ const logger = {
225
+ count: 0,
226
+ warn: function (msg) {
227
+ this.count++;
228
+ },
229
+ };
230
+
231
+ return function () {
232
+ scale({ type: "log", domain: domain }, logger);
233
+ if (logger.count) {
234
+ throw new Error();
235
+ }
236
+ };
237
+ }
238
+
239
+ expect(logScale([0, 1])).toThrow();
240
+ expect(logScale([-1, 0])).toThrow();
241
+ expect(logScale([-1, 1])).toThrow();
242
+ expect(logScale([1, 0, 2])).toThrow();
243
+ expect(logScale([1, 2])).not.toThrow();
244
+ expect(logScale([-2, -1])).not.toThrow();
245
+ });
246
+
247
+ test("Scale infers scale key from type, domain, and range", function () {
248
+ function key(params) {
249
+ return scale(params).type;
250
+ }
251
+
252
+ // numeric domain scales should adapt
253
+ [vs.Linear, vs.Log, vs.Pow, vs.Sqrt, vs.Symlog].forEach(function (st) {
254
+ expect(key({ type: st, domain: [0, 1], range: [0, 1] })).toBe(st);
255
+ expect(key({ type: st, domain: [0, 1], range: [true, false] })).toBe(
256
+ st
257
+ );
258
+
259
+ // direct color range specification
260
+ expect(key({ type: st, domain: [0, 1], range: ["blue", "red"] })).toBe(
261
+ `${vs.Sequential}-${st}`
262
+ );
263
+ expect(
264
+ key({ type: st, domain: [0, 1, 2], range: ["blue", "red"] })
265
+ ).toBe(`${vs.Diverging}-${st}`);
266
+ expect(
267
+ key({ type: st, domain: [0, 1, 2, 3], range: ["blue", "red"] })
268
+ ).toBe(st);
269
+
270
+ // color scheme range specification
271
+ expect(key({ type: st, domain: [0, 1], scheme: "blues" })).toBe(
272
+ `${vs.Sequential}-${st}`
273
+ );
274
+ expect(key({ type: st, domain: [0, 1, 2], scheme: "blues" })).toBe(
275
+ `${vs.Diverging}-${st}`
276
+ );
277
+ expect(key({ type: st, domain: [0, 1, 2, 3], scheme: "blues" })).toBe(
278
+ st
279
+ );
280
+ });
281
+
282
+ // temporal domain scales should not adapt
283
+ [vs.Time, vs.UTC].forEach(function (st) {
284
+ const t0 = new Date(2010, 0, 1),
285
+ t1 = new Date(2011, 0, 1),
286
+ t2 = new Date(2012, 0, 1),
287
+ t3 = new Date(2013, 0, 1);
288
+
289
+ expect(key({ type: st, domain: [t0, t1], range: [0, 1] })).toBe(st);
290
+ expect(key({ type: st, domain: [t0, t1], range: [true, false] })).toBe(
291
+ st
292
+ );
293
+
294
+ // direct color range specification
295
+ expect(
296
+ key({ type: st, domain: [t0, t1], range: ["blue", "red"] })
297
+ ).toBe(st);
298
+ expect(
299
+ key({ type: st, domain: [t0, t1, t2], range: ["blue", "red"] })
300
+ ).toBe(st);
301
+ expect(
302
+ key({ type: st, domain: [t0, t1, t2, t3], range: ["blue", "red"] })
303
+ ).toBe(st);
304
+
305
+ // color scheme range specification
306
+ expect(key({ type: st, domain: [t0, t1], scheme: "blues" })).toBe(st);
307
+ expect(key({ type: st, domain: [t0, t1, t2], scheme: "blues" })).toBe(
308
+ st
309
+ );
310
+ expect(
311
+ key({ type: st, domain: [t0, t1, t2, t3], scheme: "blues" })
312
+ ).toBe(st);
313
+ });
314
+
315
+ // sequential should work for backwards compatibility
316
+ const st = vs.Sequential;
317
+ expect(key({ type: st, domain: [0, 1], range: ["blue", "red"] })).toBe(
318
+ `${st}-${vs.Linear}`
319
+ );
320
+ expect(key({ type: st, domain: [0, 1], scheme: "blues" })).toBe(
321
+ `${st}-${vs.Linear}`
322
+ );
323
+ });
@@ -0,0 +1,198 @@
1
+ /*!
2
+ * Adapted from vega-encode:
3
+ * https://github.com/vega/vega/blob/master/packages/vega-encode/src/ticks.js
4
+ *
5
+ * Copyright (c) 2015-2018, University of Washington Interactive Data Lab
6
+ * All rights reserved.
7
+ *
8
+ * BSD-3-Clause License: https://github.com/vega/vega-lite/blob/master/LICENSE
9
+ */
10
+
11
+ /* eslint-disable */
12
+
13
+ import { isLogarithmic } from "vega-scale";
14
+ import { error, isNumber, isObject, isString, peek, span } from "vega-util";
15
+ import { format as numberFormat, formatSpecifier } from "d3-format";
16
+
17
+ /**
18
+ * Determine the tick count or interval function.
19
+ * @param {Scale} scale - The scale for which to generate tick values.
20
+ * @param {*} count - The desired tick count or interval specifier.
21
+ * @param {number} minStep - The desired minimum step between tick values.
22
+ * @return {*} - The tick count or interval function.
23
+ */
24
+ export function tickCount(scale, count, minStep) {
25
+ var step;
26
+
27
+ if (isNumber(count) && minStep != null) {
28
+ count = Math.min(count, ~~(span(scale.domain()) / minStep) || 1);
29
+ }
30
+
31
+ if (isObject(count)) {
32
+ step = count.step;
33
+ count = count.interval;
34
+ }
35
+
36
+ return count;
37
+ }
38
+
39
+ /**
40
+ * Filter a set of candidate tick values, ensuring that only tick values
41
+ * that lie within the scale range are included.
42
+ * @param {Scale} scale - The scale for which to generate tick values.
43
+ * @param {Array<*>} ticks - The candidate tick values.
44
+ * @param {*} count - The tick count or interval function.
45
+ * @return {Array<*>} - The filtered tick values.
46
+ */
47
+ export function validTicks(scale, ticks, count) {
48
+ var range = scale.range(),
49
+ lo = Math.floor(range[0]),
50
+ hi = Math.ceil(peek(range));
51
+
52
+ if (lo > hi) {
53
+ range = hi;
54
+ hi = lo;
55
+ lo = range;
56
+ }
57
+
58
+ ticks = ticks.filter(function (v) {
59
+ v = scale(v);
60
+ return lo <= v && v <= hi;
61
+ });
62
+
63
+ if (count > 0 && ticks.length > 1) {
64
+ var endpoints = [ticks[0], peek(ticks)];
65
+ while (ticks.length > count && ticks.length >= 3) {
66
+ ticks = ticks.filter(function (_, i) {
67
+ return !(i % 2);
68
+ });
69
+ }
70
+ if (ticks.length < 3) {
71
+ ticks = endpoints;
72
+ }
73
+ }
74
+
75
+ return ticks;
76
+ }
77
+
78
+ /**
79
+ * Generate tick values for the given scale and approximate tick count or
80
+ * interval value. If the scale has a 'ticks' method, it will be used to
81
+ * generate the ticks, with the count argument passed as a parameter. If the
82
+ * scale lacks a 'ticks' method, the full scale domain will be returned.
83
+ * @param {Scale} scale - The scale for which to generate tick values.
84
+ * @param {*} [count] - The approximate number of desired ticks.
85
+ * @return {Array<*>} - The generated tick values.
86
+ */
87
+ export function tickValues(scale, count) {
88
+ return scale.bins
89
+ ? validTicks(scale, binValues(scale.bins, count))
90
+ : scale.ticks
91
+ ? scale.ticks(count)
92
+ : scale.domain();
93
+ }
94
+
95
+ /**
96
+ * Generate tick values for an array of bin values.
97
+ * @param {Array<*>} bins - An array of bin boundaries.
98
+ * @param {Number} [count] - The approximate number of desired ticks.
99
+ * @return {Array<*>} - The generated tick values.
100
+ */
101
+ function binValues(bins, count) {
102
+ var n = bins.length,
103
+ stride = ~~(n / (count || n));
104
+
105
+ return stride < 2
106
+ ? bins.slice()
107
+ : bins.filter(function (x, i) {
108
+ return !(i % stride);
109
+ });
110
+ }
111
+
112
+ /**
113
+ * Generate a label format function for a scale. If the scale has a
114
+ * 'tickFormat' method, it will be used to generate the formatter, with the
115
+ * count and specifier arguments passed as parameters. If the scale lacks a
116
+ * 'tickFormat' method, the returned formatter performs simple string coercion.
117
+ * If the input scale is a logarithmic scale and the format specifier does not
118
+ * indicate a desired decimal precision, a special variable precision formatter
119
+ * that automatically trims trailing zeroes will be generated.
120
+ * @param {Scale} scale - The scale for which to generate the label formatter.
121
+ * @param {*} [count] - The approximate number of desired ticks.
122
+ * @param {string} [specifier] - The format specifier. Must be a legal d3
123
+ * specifier string (see https://github.com/d3/d3-format#formatSpecifier).
124
+ * @return {function(*):string} - The generated label formatter.
125
+ */
126
+ export function tickFormat(scale, count, specifier) {
127
+ var format = scale.tickFormat
128
+ ? scale.tickFormat(count, specifier)
129
+ : specifier
130
+ ? numberFormat(specifier)
131
+ : String;
132
+
133
+ if (isLogarithmic(scale.type)) {
134
+ var logfmt = variablePrecision(specifier);
135
+ format = scale.bins ? logfmt : filter(format, logfmt);
136
+ }
137
+
138
+ return format;
139
+ }
140
+
141
+ function filter(sourceFormat, targetFormat) {
142
+ return function (_) {
143
+ return sourceFormat(_) ? targetFormat(_) : "";
144
+ };
145
+ }
146
+
147
+ function variablePrecision(specifier) {
148
+ var s = formatSpecifier(specifier || ",");
149
+
150
+ if (s.precision == null) {
151
+ s.precision = 12;
152
+ switch (s.type) {
153
+ case "%":
154
+ s.precision -= 2;
155
+ break;
156
+ case "e":
157
+ s.precision -= 1;
158
+ break;
159
+ }
160
+ return trimZeroes(
161
+ numberFormat(s), // number format
162
+ numberFormat(".1f")(1)[1] // decimal point character
163
+ );
164
+ } else {
165
+ return numberFormat(s);
166
+ }
167
+ }
168
+
169
+ function trimZeroes(format, decimalChar) {
170
+ return function (x) {
171
+ var str = format(x),
172
+ dec = str.indexOf(decimalChar),
173
+ idx,
174
+ end;
175
+
176
+ if (dec < 0) return str;
177
+
178
+ idx = rightmostDigit(str, dec);
179
+ end = idx < str.length ? str.slice(idx) : "";
180
+ while (--idx > dec)
181
+ if (str[idx] !== "0") {
182
+ ++idx;
183
+ break;
184
+ }
185
+
186
+ return str.slice(0, idx) + end;
187
+ };
188
+ }
189
+
190
+ function rightmostDigit(str, dec) {
191
+ var i = str.lastIndexOf("e"),
192
+ c;
193
+ if (i > 0) return i;
194
+ for (i = str.length; --i > dec; ) {
195
+ c = str.charCodeAt(i);
196
+ if (c >= 48 && c <= 57) return i + 1; // is digit
197
+ }
198
+ }
@@ -0,0 +1,39 @@
1
+ /*!
2
+ * Adapted from vega-encode:
3
+ * https://github.com/vega/vega/blob/master/packages/vega-encode/test/scale-test.js
4
+ *
5
+ * Copyright (c) 2015-2018, University of Washington Interactive Data Lab
6
+ * All rights reserved.
7
+ *
8
+ * BSD-3-Clause License: https://github.com/vega/vega-lite/blob/master/LICENSE
9
+ */
10
+
11
+ /* eslint-disable */
12
+
13
+ import { validTicks } from "./ticks";
14
+
15
+ test("validTicks uses count correctly", function () {
16
+ var data = [0, 1, 2, 3, 4, 5, 6, 7];
17
+
18
+ var identity = function (x) {
19
+ return x;
20
+ };
21
+ identity.range = function () {
22
+ return [0, 10];
23
+ };
24
+
25
+ var t1 = validTicks(identity, data, 5);
26
+ expect(t1).toEqual([0, 2, 4, 6]);
27
+
28
+ // don't change ticks if count is large
29
+ var t2 = validTicks(identity, data, 100);
30
+ expect(t2).toEqual(data);
31
+
32
+ // special case for low number of ticks
33
+ var t3 = validTicks(identity, data, 3);
34
+ expect(t3).toEqual([0, 7]);
35
+
36
+ // single tick should pass through
37
+ var t5 = validTicks(identity, [1], 5);
38
+ expect(t5).toEqual([1]);
39
+ });
@@ -0,0 +1,13 @@
1
+ import { embed } from "./index";
2
+
3
+ // This is for development purposes. Use "npm start" to launch.
4
+
5
+ const specUrl = new URLSearchParams(window.location.search).get("spec");
6
+ if (specUrl) {
7
+ embed(document.body, specUrl);
8
+ } else {
9
+ document.body.innerHTML = `
10
+ <p style="color: firebrick">No 'spec' url parameter defined!</p>
11
+ <p>Try this one from the "static" folder, for example:
12
+ <a href="?spec=examples/first.json">examples/first.json</a></p>`;
13
+ }