@genome-spy/core 0.36.0 → 0.37.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 (523) hide show
  1. package/README.md +1 -0
  2. package/dist/{index.es.js → bundled/index.es.js} +4227 -4085
  3. package/dist/{index.js → bundled/index.js} +191 -55
  4. package/dist/src/data/collector.d.ts +36 -0
  5. package/dist/src/data/collector.d.ts.map +1 -0
  6. package/dist/src/data/collector.js +184 -0
  7. package/dist/src/data/collector.test.js +84 -0
  8. package/dist/src/data/dataFlow.d.ts +65 -0
  9. package/dist/src/data/dataFlow.d.ts.map +1 -0
  10. package/dist/src/data/dataFlow.js +142 -0
  11. package/dist/src/data/dataFlow.test.js +5 -0
  12. package/dist/src/data/facetNode.d.ts +17 -0
  13. package/dist/src/data/facetNode.d.ts.map +1 -0
  14. package/dist/src/data/facetNode.js +17 -0
  15. package/dist/src/data/flow.test.js +72 -0
  16. package/dist/src/data/flowNode.d.ts +136 -0
  17. package/dist/src/data/flowNode.d.ts.map +1 -0
  18. package/dist/src/data/flowNode.js +286 -0
  19. package/dist/src/data/flowNode.test.js +50 -0
  20. package/dist/src/data/flowOptimizer.d.ts +27 -0
  21. package/dist/src/data/flowOptimizer.d.ts.map +1 -0
  22. package/dist/src/data/flowOptimizer.js +133 -0
  23. package/dist/src/data/flowOptimizer.test.js +193 -0
  24. package/dist/src/data/flowTestUtils.d.ts +30 -0
  25. package/dist/src/data/flowTestUtils.d.ts.map +1 -0
  26. package/dist/src/data/flowTestUtils.js +63 -0
  27. package/dist/src/data/formats/fasta.d.ts +20 -0
  28. package/dist/src/data/formats/fasta.d.ts.map +1 -0
  29. package/dist/src/data/formats/fasta.js +32 -0
  30. package/dist/src/data/formats/fasta.test.js +27 -0
  31. package/dist/src/data/sources/dataSource.d.ts +12 -0
  32. package/dist/src/data/sources/dataSource.d.ts.map +1 -0
  33. package/dist/src/data/sources/dataSource.js +25 -0
  34. package/dist/src/data/sources/dataSourceFactory.d.ts +16 -0
  35. package/dist/src/data/sources/dataSourceFactory.d.ts.map +1 -0
  36. package/dist/src/data/sources/dataSourceFactory.js +127 -0
  37. package/dist/src/data/sources/dataUtils.d.ts +50 -0
  38. package/dist/src/data/sources/dataUtils.d.ts.map +1 -0
  39. package/dist/src/data/sources/dataUtils.js +83 -0
  40. package/dist/src/data/sources/dynamic/README.md +3 -0
  41. package/dist/src/data/sources/dynamic/axisGenomeSource.d.ts +13 -0
  42. package/dist/src/data/sources/dynamic/axisGenomeSource.d.ts.map +1 -0
  43. package/dist/src/data/sources/dynamic/axisGenomeSource.js +19 -0
  44. package/dist/src/data/sources/dynamic/axisTickSource.d.ts +18 -0
  45. package/dist/src/data/sources/dynamic/axisTickSource.d.ts.map +1 -0
  46. package/dist/src/data/sources/dynamic/axisTickSource.js +73 -0
  47. package/dist/src/data/sources/dynamic/bamSource.d.ts +46 -0
  48. package/dist/src/data/sources/dynamic/bamSource.d.ts.map +1 -0
  49. package/dist/src/data/sources/dynamic/bamSource.js +115 -0
  50. package/dist/src/data/sources/dynamic/bigBedSource.d.ts +51 -0
  51. package/dist/src/data/sources/dynamic/bigBedSource.d.ts.map +1 -0
  52. package/dist/src/data/sources/dynamic/bigBedSource.js +128 -0
  53. package/dist/src/data/sources/dynamic/bigWigSource.d.ts +58 -0
  54. package/dist/src/data/sources/dynamic/bigWigSource.d.ts.map +1 -0
  55. package/dist/src/data/sources/dynamic/bigWigSource.js +166 -0
  56. package/dist/src/data/sources/dynamic/gff3Source.d.ts +8 -0
  57. package/dist/src/data/sources/dynamic/gff3Source.d.ts.map +1 -0
  58. package/dist/src/data/sources/dynamic/gff3Source.js +19 -0
  59. package/dist/src/data/sources/dynamic/indexedFastaSource.d.ts +30 -0
  60. package/dist/src/data/sources/dynamic/indexedFastaSource.d.ts.map +1 -0
  61. package/dist/src/data/sources/dynamic/indexedFastaSource.js +86 -0
  62. package/dist/src/data/sources/dynamic/singleAxisLazySource.d.ts +42 -0
  63. package/dist/src/data/sources/dynamic/singleAxisLazySource.d.ts.map +1 -0
  64. package/dist/src/data/sources/dynamic/singleAxisLazySource.js +129 -0
  65. package/dist/src/data/sources/dynamic/tabixSource.d.ts +54 -0
  66. package/dist/src/data/sources/dynamic/tabixSource.d.ts.map +1 -0
  67. package/dist/src/data/sources/dynamic/tabixSource.js +140 -0
  68. package/dist/src/data/sources/dynamic/windowedMixin.d.ts +32 -0
  69. package/dist/src/data/sources/dynamic/windowedMixin.d.ts.map +1 -0
  70. package/dist/src/data/sources/dynamic/windowedMixin.js +53 -0
  71. package/dist/src/data/sources/inlineSource.d.ts +16 -0
  72. package/dist/src/data/sources/inlineSource.d.ts.map +1 -0
  73. package/dist/src/data/sources/inlineSource.js +68 -0
  74. package/dist/src/data/sources/inlineSource.test.js +56 -0
  75. package/dist/src/data/sources/namedSource.d.ts +25 -0
  76. package/dist/src/data/sources/namedSource.d.ts.map +1 -0
  77. package/dist/src/data/sources/namedSource.js +80 -0
  78. package/dist/src/data/sources/sequenceSource.d.ts +17 -0
  79. package/dist/src/data/sources/sequenceSource.d.ts.map +1 -0
  80. package/dist/src/data/sources/sequenceSource.js +47 -0
  81. package/dist/src/data/sources/sequenceSource.test.js +46 -0
  82. package/dist/src/data/sources/urlSource.d.ts +16 -0
  83. package/dist/src/data/sources/urlSource.d.ts.map +1 -0
  84. package/dist/src/data/sources/urlSource.js +74 -0
  85. package/dist/src/data/transforms/aggregate.d.ts +18 -0
  86. package/dist/src/data/transforms/aggregate.d.ts.map +1 -0
  87. package/dist/src/data/transforms/aggregate.js +67 -0
  88. package/dist/src/data/transforms/clone.d.ts +15 -0
  89. package/dist/src/data/transforms/clone.d.ts.map +1 -0
  90. package/dist/src/data/transforms/clone.js +40 -0
  91. package/dist/src/data/transforms/clone.test.js +11 -0
  92. package/dist/src/data/transforms/coverage.d.ts +30 -0
  93. package/dist/src/data/transforms/coverage.d.ts.map +1 -0
  94. package/dist/src/data/transforms/coverage.js +183 -0
  95. package/dist/src/data/transforms/coverage.test.js +123 -0
  96. package/dist/src/data/transforms/filter.d.ts +12 -0
  97. package/dist/src/data/transforms/filter.d.ts.map +1 -0
  98. package/dist/src/data/transforms/filter.js +33 -0
  99. package/dist/src/data/transforms/filter.test.js +18 -0
  100. package/dist/src/data/transforms/filterScoredLabels.d.ts +29 -0
  101. package/dist/src/data/transforms/filterScoredLabels.d.ts.map +1 -0
  102. package/dist/src/data/transforms/filterScoredLabels.js +134 -0
  103. package/dist/src/data/transforms/flatten.d.ts +10 -0
  104. package/dist/src/data/transforms/flatten.d.ts.map +1 -0
  105. package/dist/src/data/transforms/flatten.js +68 -0
  106. package/dist/src/data/transforms/flatten.test.js +93 -0
  107. package/dist/src/data/transforms/flattenCompressedExons.d.ts +19 -0
  108. package/dist/src/data/transforms/flattenCompressedExons.d.ts.map +1 -0
  109. package/dist/src/data/transforms/flattenCompressedExons.js +53 -0
  110. package/dist/src/data/transforms/flattenDelimited.d.ts +10 -0
  111. package/dist/src/data/transforms/flattenDelimited.d.ts.map +1 -0
  112. package/dist/src/data/transforms/flattenDelimited.js +66 -0
  113. package/dist/src/data/transforms/flattenDelimited.test.js +87 -0
  114. package/dist/src/data/transforms/flattenSequence.d.ts +11 -0
  115. package/dist/src/data/transforms/flattenSequence.d.ts.map +1 -0
  116. package/dist/src/data/transforms/flattenSequence.js +35 -0
  117. package/dist/src/data/transforms/flattenSequence.test.js +34 -0
  118. package/dist/src/data/transforms/formula.d.ts +13 -0
  119. package/dist/src/data/transforms/formula.d.ts.map +1 -0
  120. package/dist/src/data/transforms/formula.js +35 -0
  121. package/dist/src/data/transforms/formula.test.js +19 -0
  122. package/dist/src/data/transforms/identifier.d.ts +40 -0
  123. package/dist/src/data/transforms/identifier.d.ts.map +1 -0
  124. package/dist/src/data/transforms/identifier.js +106 -0
  125. package/dist/src/data/transforms/identifier.test.js +83 -0
  126. package/dist/src/data/transforms/linearizeGenomicCoordinate.d.ts +10 -0
  127. package/dist/src/data/transforms/linearizeGenomicCoordinate.d.ts.map +1 -0
  128. package/dist/src/data/transforms/linearizeGenomicCoordinate.js +97 -0
  129. package/dist/src/data/transforms/measureText.d.ts +18 -0
  130. package/dist/src/data/transforms/measureText.d.ts.map +1 -0
  131. package/dist/src/data/transforms/measureText.js +42 -0
  132. package/dist/src/data/transforms/pileup.d.ts +10 -0
  133. package/dist/src/data/transforms/pileup.d.ts.map +1 -0
  134. package/dist/src/data/transforms/pileup.js +126 -0
  135. package/dist/src/data/transforms/pileup.test.js +70 -0
  136. package/dist/src/data/transforms/project.d.ts +13 -0
  137. package/dist/src/data/transforms/project.d.ts.map +1 -0
  138. package/dist/src/data/transforms/project.js +38 -0
  139. package/dist/src/data/transforms/project.test.js +32 -0
  140. package/dist/src/data/transforms/regexExtract.d.ts +13 -0
  141. package/dist/src/data/transforms/regexExtract.d.ts.map +1 -0
  142. package/dist/src/data/transforms/regexExtract.js +57 -0
  143. package/dist/src/data/transforms/regexExtract.test.js +67 -0
  144. package/dist/src/data/transforms/regexFold.d.ts +14 -0
  145. package/dist/src/data/transforms/regexFold.d.ts.map +1 -0
  146. package/dist/src/data/transforms/regexFold.js +139 -0
  147. package/dist/src/data/transforms/regexFold.test.js +160 -0
  148. package/dist/src/data/transforms/sample.d.ts +42 -0
  149. package/dist/src/data/transforms/sample.d.ts.map +1 -0
  150. package/dist/src/data/transforms/sample.js +99 -0
  151. package/dist/src/data/transforms/sample.test.js +38 -0
  152. package/dist/src/data/transforms/stack.d.ts +11 -0
  153. package/dist/src/data/transforms/stack.d.ts.map +1 -0
  154. package/dist/src/data/transforms/stack.js +134 -0
  155. package/dist/src/data/transforms/stack.test.js +91 -0
  156. package/dist/src/data/transforms/transformFactory.d.ts +12 -0
  157. package/dist/src/data/transforms/transformFactory.d.ts.map +1 -0
  158. package/dist/src/data/transforms/transformFactory.js +59 -0
  159. package/dist/src/encoder/accessor.d.ts +15 -0
  160. package/dist/src/encoder/accessor.d.ts.map +1 -0
  161. package/dist/src/encoder/accessor.js +76 -0
  162. package/dist/src/encoder/accessor.test.js +47 -0
  163. package/dist/src/encoder/encoder.d.ts +144 -0
  164. package/dist/src/encoder/encoder.d.ts.map +1 -0
  165. package/dist/src/encoder/encoder.js +400 -0
  166. package/dist/src/encoder/encoder.test.js +98 -0
  167. package/dist/src/fonts/Lato-Regular.json +1267 -0
  168. package/dist/src/fonts/Lato-Regular.png +0 -0
  169. package/dist/src/fonts/OFL.txt +93 -0
  170. package/dist/src/fonts/README.md +3 -0
  171. package/dist/src/fonts/bmFontManager.d.ts +182 -0
  172. package/dist/src/fonts/bmFontManager.d.ts.map +1 -0
  173. package/dist/src/fonts/bmFontManager.js +359 -0
  174. package/dist/src/fonts/bmFontMetrics.d.ts +45 -0
  175. package/dist/src/fonts/bmFontMetrics.d.ts.map +1 -0
  176. package/dist/src/fonts/bmFontMetrics.js +108 -0
  177. package/dist/src/genome/genome.d.ts +172 -0
  178. package/dist/src/genome/genome.d.ts.map +1 -0
  179. package/dist/src/genome/genome.js +379 -0
  180. package/dist/src/genome/genome.test.js +226 -0
  181. package/dist/src/genome/genomeStore.d.ts +20 -0
  182. package/dist/src/genome/genomeStore.d.ts.map +1 -0
  183. package/dist/src/genome/genomeStore.js +54 -0
  184. package/dist/src/genome/locusFormat.d.ts +14 -0
  185. package/dist/src/genome/locusFormat.d.ts.map +1 -0
  186. package/dist/src/genome/locusFormat.js +37 -0
  187. package/dist/src/genome/scaleIndex.d.ts +6 -0
  188. package/dist/src/genome/scaleIndex.d.ts.map +1 -0
  189. package/dist/src/genome/scaleIndex.js +165 -0
  190. package/dist/src/genome/scaleIndex.test.js +78 -0
  191. package/dist/src/genome/scaleLocus.d.ts +3 -0
  192. package/dist/src/genome/scaleLocus.d.ts.map +1 -0
  193. package/dist/src/genome/scaleLocus.js +101 -0
  194. package/dist/src/genome/scaleLocus.test.js +4 -0
  195. package/dist/src/genomeSpy.d.ts +141 -0
  196. package/dist/src/genomeSpy.d.ts.map +1 -0
  197. package/dist/src/genomeSpy.js +788 -0
  198. package/dist/src/gl/arrayBuilder.d.ts +71 -0
  199. package/dist/src/gl/arrayBuilder.d.ts.map +1 -0
  200. package/dist/src/gl/arrayBuilder.js +199 -0
  201. package/dist/src/gl/dataToVertices.d.ts +194 -0
  202. package/dist/src/gl/dataToVertices.d.ts.map +1 -0
  203. package/dist/src/gl/dataToVertices.js +639 -0
  204. package/dist/src/gl/includes/common.glsl.js +2 -0
  205. package/dist/src/gl/includes/picking.fragment.glsl.js +2 -0
  206. package/dist/src/gl/includes/picking.vertex.glsl.js +2 -0
  207. package/dist/src/gl/includes/sampleFacet.glsl.js +2 -0
  208. package/dist/src/gl/includes/scales.glsl.js +2 -0
  209. package/dist/src/gl/link.fragment.glsl.js +2 -0
  210. package/dist/src/gl/link.vertex.glsl.js +2 -0
  211. package/dist/src/gl/point.fragment.glsl.js +2 -0
  212. package/dist/src/gl/point.vertex.glsl.js +2 -0
  213. package/dist/src/gl/rect.fragment.glsl.js +2 -0
  214. package/dist/src/gl/rect.vertex.glsl.js +2 -0
  215. package/dist/src/gl/rule.fragment.glsl.js +2 -0
  216. package/dist/src/gl/rule.vertex.glsl.js +2 -0
  217. package/dist/src/gl/text.fragment.glsl.js +2 -0
  218. package/dist/src/gl/text.vertex.glsl.js +2 -0
  219. package/dist/src/gl/webGLHelper.d.ts +118 -0
  220. package/dist/src/gl/webGLHelper.d.ts.map +1 -0
  221. package/dist/src/gl/webGLHelper.js +513 -0
  222. package/dist/src/img/bowtie.svg +1 -0
  223. package/dist/src/img/genomespy-favicon.svg +34 -0
  224. package/dist/src/index.d.ts +15 -0
  225. package/dist/src/index.d.ts.map +1 -0
  226. package/dist/src/index.html +11 -0
  227. package/dist/src/index.js +129 -0
  228. package/dist/src/marks/link.d.ts +11 -0
  229. package/dist/src/marks/link.d.ts.map +1 -0
  230. package/dist/src/marks/link.js +175 -0
  231. package/dist/src/marks/mark.d.ts +226 -0
  232. package/dist/src/marks/mark.d.ts.map +1 -0
  233. package/dist/src/marks/mark.js +1004 -0
  234. package/dist/src/marks/markUtils.d.ts +23 -0
  235. package/dist/src/marks/markUtils.d.ts.map +1 -0
  236. package/dist/src/marks/markUtils.js +125 -0
  237. package/dist/src/marks/pointMark.d.ts +11 -0
  238. package/dist/src/marks/pointMark.d.ts.map +1 -0
  239. package/dist/src/marks/pointMark.js +251 -0
  240. package/dist/src/marks/rectMark.d.ts +18 -0
  241. package/dist/src/marks/rectMark.d.ts.map +1 -0
  242. package/dist/src/marks/rectMark.js +255 -0
  243. package/dist/src/marks/rule.d.ts +6 -0
  244. package/dist/src/marks/rule.d.ts.map +1 -0
  245. package/dist/src/marks/rule.js +250 -0
  246. package/dist/src/marks/text.d.ts +13 -0
  247. package/dist/src/marks/text.d.ts.map +1 -0
  248. package/dist/src/marks/text.js +279 -0
  249. package/dist/src/scale/colorUtils.d.ts +34 -0
  250. package/dist/src/scale/colorUtils.d.ts.map +1 -0
  251. package/dist/src/scale/colorUtils.js +184 -0
  252. package/dist/src/scale/glslScaleGenerator.d.ts +45 -0
  253. package/dist/src/scale/glslScaleGenerator.d.ts.map +1 -0
  254. package/dist/src/scale/glslScaleGenerator.js +506 -0
  255. package/dist/src/scale/scale.d.ts +10 -0
  256. package/dist/src/scale/scale.d.ts.map +1 -0
  257. package/dist/src/scale/scale.js +456 -0
  258. package/dist/src/scale/scale.test.js +324 -0
  259. package/dist/src/scale/ticks.d.ts +47 -0
  260. package/dist/src/scale/ticks.d.ts.map +1 -0
  261. package/dist/src/scale/ticks.js +203 -0
  262. package/dist/src/scale/ticks.test.js +40 -0
  263. package/dist/src/singlePageApp.d.ts +2 -0
  264. package/dist/src/singlePageApp.d.ts.map +1 -0
  265. package/dist/src/singlePageApp.js +13 -0
  266. package/dist/src/spec/axis.d.ts +402 -0
  267. package/dist/src/spec/channel.d.ts +440 -0
  268. package/dist/src/spec/data.d.ts +370 -0
  269. package/dist/src/spec/font.d.ts +15 -0
  270. package/dist/src/spec/genome.d.ts +35 -0
  271. package/dist/src/spec/mark.d.ts +435 -0
  272. package/dist/src/spec/root.d.ts +22 -0
  273. package/dist/src/spec/sampleView.d.ts +185 -0
  274. package/dist/src/spec/scale.d.ts +273 -0
  275. package/dist/src/spec/title.d.ts +102 -0
  276. package/dist/src/spec/tooltip.d.ts +9 -0
  277. package/dist/src/spec/transform.d.ts +504 -0
  278. package/dist/src/spec/view.d.ts +214 -0
  279. package/dist/src/styles/genome-spy.css.d.ts +3 -0
  280. package/dist/src/styles/genome-spy.css.d.ts.map +1 -0
  281. package/dist/src/styles/genome-spy.css.js +114 -0
  282. package/dist/src/styles/genome-spy.scss +153 -0
  283. package/dist/src/tooltip/dataTooltipHandler.d.ts +2 -0
  284. package/dist/src/tooltip/dataTooltipHandler.d.ts.map +1 -0
  285. package/dist/src/tooltip/dataTooltipHandler.js +64 -0
  286. package/dist/src/tooltip/refseqGeneTooltipHandler.d.ts +2 -0
  287. package/dist/src/tooltip/refseqGeneTooltipHandler.d.ts.map +1 -0
  288. package/dist/src/tooltip/refseqGeneTooltipHandler.js +78 -0
  289. package/dist/src/tooltip/tooltipHandler.d.ts +9 -0
  290. package/dist/src/tooltip/tooltipHandler.d.ts.map +1 -0
  291. package/dist/src/tooltip/tooltipHandler.ts +12 -0
  292. package/dist/src/types/bmFont.d.ts +58 -0
  293. package/dist/src/types/embedApi.d.ts +67 -0
  294. package/dist/src/types/encoder.d.ts +84 -0
  295. package/dist/src/types/flowBatch.d.ts +40 -0
  296. package/dist/src/types/rendering.d.ts +65 -0
  297. package/dist/src/types/scaleResolutionApi.d.ts +40 -0
  298. package/dist/src/types/viewContext.d.ts +85 -0
  299. package/dist/src/utils/addBaseUrl.d.ts +6 -0
  300. package/dist/src/utils/addBaseUrl.d.ts.map +1 -0
  301. package/dist/src/utils/addBaseUrl.js +19 -0
  302. package/dist/src/utils/addBaseUrl.test.js +22 -0
  303. package/dist/src/utils/animator.d.ts +41 -0
  304. package/dist/src/utils/animator.d.ts.map +1 -0
  305. package/dist/src/utils/animator.js +83 -0
  306. package/dist/src/utils/arrayUtils.d.ts +34 -0
  307. package/dist/src/utils/arrayUtils.d.ts.map +1 -0
  308. package/dist/src/utils/arrayUtils.js +61 -0
  309. package/dist/src/utils/binnedIndex.d.ts +23 -0
  310. package/dist/src/utils/binnedIndex.d.ts.map +1 -0
  311. package/dist/src/utils/binnedIndex.js +167 -0
  312. package/dist/src/utils/binnedIndex.test.js +155 -0
  313. package/dist/src/utils/clamp.d.ts +7 -0
  314. package/dist/src/utils/clamp.d.ts.map +1 -0
  315. package/dist/src/utils/clamp.js +8 -0
  316. package/dist/src/utils/cloner.d.ts +16 -0
  317. package/dist/src/utils/cloner.d.ts.map +1 -0
  318. package/dist/src/utils/cloner.js +34 -0
  319. package/dist/src/utils/cloner.test.js +24 -0
  320. package/dist/src/utils/coalesce.d.ts +6 -0
  321. package/dist/src/utils/coalesce.d.ts.map +1 -0
  322. package/dist/src/utils/coalesce.js +11 -0
  323. package/dist/src/utils/coalesce.test.js +16 -0
  324. package/dist/src/utils/concatIterables.d.ts +8 -0
  325. package/dist/src/utils/concatIterables.d.ts.map +1 -0
  326. package/dist/src/utils/concatIterables.js +26 -0
  327. package/dist/src/utils/concatIterables.test.js +8 -0
  328. package/dist/src/utils/debounce.d.ts +8 -0
  329. package/dist/src/utils/debounce.d.ts.map +1 -0
  330. package/dist/src/utils/debounce.js +37 -0
  331. package/dist/src/utils/domainArray.d.ts +61 -0
  332. package/dist/src/utils/domainArray.d.ts.map +1 -0
  333. package/dist/src/utils/domainArray.js +216 -0
  334. package/dist/src/utils/domainArray.test.js +130 -0
  335. package/dist/src/utils/eerp.d.ts +12 -0
  336. package/dist/src/utils/eerp.d.ts.map +1 -0
  337. package/dist/src/utils/eerp.js +13 -0
  338. package/dist/src/utils/expression.d.ts +9 -0
  339. package/dist/src/utils/expression.d.ts.map +1 -0
  340. package/dist/src/utils/expression.js +32 -0
  341. package/dist/src/utils/field.d.ts +17 -0
  342. package/dist/src/utils/field.d.ts.map +1 -0
  343. package/dist/src/utils/field.js +28 -0
  344. package/dist/src/utils/formatObject.d.ts +7 -0
  345. package/dist/src/utils/formatObject.d.ts.map +1 -0
  346. package/dist/src/utils/formatObject.js +37 -0
  347. package/dist/src/utils/indexer.d.ts +16 -0
  348. package/dist/src/utils/indexer.d.ts.map +1 -0
  349. package/dist/src/utils/indexer.js +43 -0
  350. package/dist/src/utils/indexer.test.js +47 -0
  351. package/dist/src/utils/inertia.d.ts +42 -0
  352. package/dist/src/utils/inertia.d.ts.map +1 -0
  353. package/dist/src/utils/inertia.js +124 -0
  354. package/dist/src/utils/interactionEvent.d.ts +26 -0
  355. package/dist/src/utils/interactionEvent.d.ts.map +1 -0
  356. package/dist/src/utils/interactionEvent.js +33 -0
  357. package/dist/src/utils/iterateNestedMaps.d.ts +11 -0
  358. package/dist/src/utils/iterateNestedMaps.d.ts.map +1 -0
  359. package/dist/src/utils/iterateNestedMaps.js +21 -0
  360. package/dist/src/utils/iterateNestedMaps.test.js +33 -0
  361. package/dist/src/utils/kWayMerge.d.ts +9 -0
  362. package/dist/src/utils/kWayMerge.d.ts.map +1 -0
  363. package/dist/src/utils/kWayMerge.js +42 -0
  364. package/dist/src/utils/kWayMerge.test.js +26 -0
  365. package/dist/src/utils/layout/flexLayout.d.ts +182 -0
  366. package/dist/src/utils/layout/flexLayout.d.ts.map +1 -0
  367. package/dist/src/utils/layout/flexLayout.js +381 -0
  368. package/dist/src/utils/layout/flexLayout.test.js +323 -0
  369. package/dist/src/utils/layout/grid.d.ts +29 -0
  370. package/dist/src/utils/layout/grid.d.ts.map +1 -0
  371. package/dist/src/utils/layout/grid.js +95 -0
  372. package/dist/src/utils/layout/grid.test.js +71 -0
  373. package/dist/src/utils/layout/padding.d.ts +83 -0
  374. package/dist/src/utils/layout/padding.d.ts.map +1 -0
  375. package/dist/src/utils/layout/padding.js +155 -0
  376. package/dist/src/utils/layout/point.d.ts +16 -0
  377. package/dist/src/utils/layout/point.d.ts.map +1 -0
  378. package/dist/src/utils/layout/point.js +23 -0
  379. package/dist/src/utils/layout/rectangle.d.ts +142 -0
  380. package/dist/src/utils/layout/rectangle.d.ts.map +1 -0
  381. package/dist/src/utils/layout/rectangle.js +296 -0
  382. package/dist/src/utils/layout/rectangle.test.js +172 -0
  383. package/dist/src/utils/mergeObjects.d.ts +15 -0
  384. package/dist/src/utils/mergeObjects.d.ts.map +1 -0
  385. package/dist/src/utils/mergeObjects.js +99 -0
  386. package/dist/src/utils/mergeObjects.test.js +42 -0
  387. package/dist/src/utils/numberExtractor.d.ts +9 -0
  388. package/dist/src/utils/numberExtractor.d.ts.map +1 -0
  389. package/dist/src/utils/numberExtractor.js +24 -0
  390. package/dist/src/utils/numberExtractor.test.js +6 -0
  391. package/dist/src/utils/point.d.ts +9 -0
  392. package/dist/src/utils/point.d.ts.map +1 -0
  393. package/dist/src/utils/point.js +14 -0
  394. package/dist/src/utils/propertyCacher.d.ts +30 -0
  395. package/dist/src/utils/propertyCacher.d.ts.map +1 -0
  396. package/dist/src/utils/propertyCacher.js +70 -0
  397. package/dist/src/utils/propertyCacher.test.js +85 -0
  398. package/dist/src/utils/propertyCoalescer.d.ts +15 -0
  399. package/dist/src/utils/propertyCoalescer.d.ts.map +1 -0
  400. package/dist/src/utils/propertyCoalescer.js +42 -0
  401. package/dist/src/utils/propertyCoalescer.test.js +22 -0
  402. package/dist/src/utils/reservationMap.d.ts +42 -0
  403. package/dist/src/utils/reservationMap.d.ts.map +1 -0
  404. package/dist/src/utils/reservationMap.js +103 -0
  405. package/dist/src/utils/reservationMap.test.js +20 -0
  406. package/dist/src/utils/scaleNull.d.ts +13 -0
  407. package/dist/src/utils/scaleNull.d.ts.map +1 -0
  408. package/dist/src/utils/scaleNull.js +21 -0
  409. package/dist/src/utils/setOperations.d.ts +31 -0
  410. package/dist/src/utils/setOperations.d.ts.map +1 -0
  411. package/dist/src/utils/setOperations.js +75 -0
  412. package/dist/src/utils/smoothstep.d.ts +7 -0
  413. package/dist/src/utils/smoothstep.d.ts.map +1 -0
  414. package/dist/src/utils/smoothstep.js +10 -0
  415. package/dist/src/utils/throttle.d.ts +8 -0
  416. package/dist/src/utils/throttle.d.ts.map +1 -0
  417. package/dist/src/utils/throttle.js +34 -0
  418. package/dist/src/utils/topK.d.ts +22 -0
  419. package/dist/src/utils/topK.d.ts.map +1 -0
  420. package/dist/src/utils/topK.js +76 -0
  421. package/dist/src/utils/topK.test.js +64 -0
  422. package/dist/src/utils/transition.d.ts +44 -0
  423. package/dist/src/utils/transition.d.ts.map +1 -0
  424. package/dist/src/utils/transition.js +74 -0
  425. package/dist/src/utils/trees.d.ts +56 -0
  426. package/dist/src/utils/trees.d.ts.map +1 -0
  427. package/dist/src/utils/trees.js +92 -0
  428. package/dist/src/utils/trees.test.js +130 -0
  429. package/dist/src/utils/ui/tooltip.d.ts +50 -0
  430. package/dist/src/utils/ui/tooltip.d.ts.map +1 -0
  431. package/dist/src/utils/ui/tooltip.js +189 -0
  432. package/dist/src/utils/url.d.ts +9 -0
  433. package/dist/src/utils/url.d.ts.map +1 -0
  434. package/dist/src/utils/url.js +22 -0
  435. package/dist/src/utils/variableTools.d.ts +14 -0
  436. package/dist/src/utils/variableTools.d.ts.map +1 -0
  437. package/dist/src/utils/variableTools.js +24 -0
  438. package/dist/src/utils/variableTools.test.js +13 -0
  439. package/dist/src/view/axisGridView.d.ts +39 -0
  440. package/dist/src/view/axisGridView.d.ts.map +1 -0
  441. package/dist/src/view/axisGridView.js +246 -0
  442. package/dist/src/view/axisResolution.d.ts +24 -0
  443. package/dist/src/view/axisResolution.d.ts.map +1 -0
  444. package/dist/src/view/axisResolution.js +141 -0
  445. package/dist/src/view/axisResolution.test.js +201 -0
  446. package/dist/src/view/axisView.d.ts +49 -0
  447. package/dist/src/view/axisView.d.ts.map +1 -0
  448. package/dist/src/view/axisView.js +629 -0
  449. package/dist/src/view/concatView.d.ts +16 -0
  450. package/dist/src/view/concatView.d.ts.map +1 -0
  451. package/dist/src/view/concatView.js +84 -0
  452. package/dist/src/view/containerView.d.ts +43 -0
  453. package/dist/src/view/containerView.d.ts.map +1 -0
  454. package/dist/src/view/containerView.js +137 -0
  455. package/dist/src/view/facetView.d.ts +71 -0
  456. package/dist/src/view/facetView.d.ts.map +1 -0
  457. package/dist/src/view/facetView.js +492 -0
  458. package/dist/src/view/flowBuilder.d.ts +37 -0
  459. package/dist/src/view/flowBuilder.d.ts.map +1 -0
  460. package/dist/src/view/flowBuilder.js +383 -0
  461. package/dist/src/view/flowBuilder.test.js +125 -0
  462. package/dist/src/view/gridView.d.ts +111 -0
  463. package/dist/src/view/gridView.d.ts.map +1 -0
  464. package/dist/src/view/gridView.js +1086 -0
  465. package/dist/src/view/implicitRootView.d.ts +9 -0
  466. package/dist/src/view/implicitRootView.d.ts.map +1 -0
  467. package/dist/src/view/implicitRootView.js +23 -0
  468. package/dist/src/view/importView.d.ts +17 -0
  469. package/dist/src/view/importView.d.ts.map +1 -0
  470. package/dist/src/view/importView.js +22 -0
  471. package/dist/src/view/layerView.d.ts +25 -0
  472. package/dist/src/view/layerView.d.ts.map +1 -0
  473. package/dist/src/view/layerView.js +77 -0
  474. package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts +30 -0
  475. package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts.map +1 -0
  476. package/dist/src/view/renderingContext/bufferedViewRenderingContext.js +175 -0
  477. package/dist/src/view/renderingContext/compositeViewRenderingContext.d.ts +14 -0
  478. package/dist/src/view/renderingContext/compositeViewRenderingContext.d.ts.map +1 -0
  479. package/dist/src/view/renderingContext/compositeViewRenderingContext.js +51 -0
  480. package/dist/src/view/renderingContext/debuggingViewRenderingContext.d.ts +51 -0
  481. package/dist/src/view/renderingContext/debuggingViewRenderingContext.d.ts.map +1 -0
  482. package/dist/src/view/renderingContext/debuggingViewRenderingContext.js +94 -0
  483. package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.d.ts +60 -0
  484. package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.d.ts.map +1 -0
  485. package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.js +128 -0
  486. package/dist/src/view/renderingContext/simpleViewRenderingContext.d.ts +19 -0
  487. package/dist/src/view/renderingContext/simpleViewRenderingContext.d.ts.map +1 -0
  488. package/dist/src/view/renderingContext/simpleViewRenderingContext.js +64 -0
  489. package/dist/src/view/renderingContext/svgViewRenderingContext.d.ts +22 -0
  490. package/dist/src/view/renderingContext/svgViewRenderingContext.d.ts.map +1 -0
  491. package/dist/src/view/renderingContext/svgViewRenderingContext.js +125 -0
  492. package/dist/src/view/renderingContext/viewRenderingContext.d.ts +33 -0
  493. package/dist/src/view/renderingContext/viewRenderingContext.d.ts.map +1 -0
  494. package/dist/src/view/renderingContext/viewRenderingContext.js +41 -0
  495. package/dist/src/view/scaleResolution.d.ts +170 -0
  496. package/dist/src/view/scaleResolution.d.ts.map +1 -0
  497. package/dist/src/view/scaleResolution.js +874 -0
  498. package/dist/src/view/scaleResolution.test.js +658 -0
  499. package/dist/src/view/testUtils.d.ts +30 -0
  500. package/dist/src/view/testUtils.d.ts.map +1 -0
  501. package/dist/src/view/testUtils.js +101 -0
  502. package/dist/src/view/title.d.ts +6 -0
  503. package/dist/src/view/title.d.ts.map +1 -0
  504. package/dist/src/view/title.js +165 -0
  505. package/dist/src/view/unitView.d.ts +93 -0
  506. package/dist/src/view/unitView.d.ts.map +1 -0
  507. package/dist/src/view/unitView.js +345 -0
  508. package/dist/src/view/view.d.ts +291 -0
  509. package/dist/src/view/view.d.ts.map +1 -0
  510. package/dist/src/view/view.js +691 -0
  511. package/dist/src/view/view.test.js +214 -0
  512. package/dist/src/view/viewFactory.d.ts +76 -0
  513. package/dist/src/view/viewFactory.d.ts.map +1 -0
  514. package/dist/src/view/viewFactory.js +178 -0
  515. package/dist/src/view/viewFactory.test.js +17 -0
  516. package/dist/src/view/viewUtils.d.ts +90 -0
  517. package/dist/src/view/viewUtils.d.ts.map +1 -0
  518. package/dist/src/view/viewUtils.js +326 -0
  519. package/dist/src/view/zoom.d.ts +23 -0
  520. package/dist/src/view/zoom.d.ts.map +1 -0
  521. package/dist/src/view/zoom.js +89 -0
  522. package/package.json +15 -12
  523. package/dist/style.css +0 -1
@@ -0,0 +1,874 @@
1
+ import scaleLocus, { isScaleLocus } from "../genome/scaleLocus";
2
+ import scaleIndex from "../genome/scaleIndex";
3
+ import scaleNull from "../utils/scaleNull";
4
+
5
+ import {
6
+ panLinear,
7
+ zoomLinear,
8
+ clampRange,
9
+ span,
10
+ panLog,
11
+ zoomLog,
12
+ panPow,
13
+ zoomPow,
14
+ isArray,
15
+ isObject,
16
+ isBoolean,
17
+ } from "vega-util";
18
+ import { scale as vegaScale, isDiscrete, isContinuous } from "vega-scale";
19
+
20
+ import mergeObjects from "../utils/mergeObjects";
21
+ import createScale, { configureScale } from "../scale/scale";
22
+
23
+ import { invalidate, getCachedOrCall } from "../utils/propertyCacher";
24
+ import {
25
+ getChannelDefWithScale,
26
+ getDiscreteRange,
27
+ isColorChannel,
28
+ isDiscreteChannel,
29
+ isPositionalChannel,
30
+ isPrimaryPositionalChannel,
31
+ isSecondaryChannel,
32
+ } from "../encoder/encoder";
33
+ import {
34
+ isChromosomalLocus,
35
+ isChromosomalLocusInterval,
36
+ } from "../genome/genome";
37
+ import { NominalDomain } from "../utils/domainArray";
38
+ import { easeCubicInOut } from "d3-ease";
39
+ import { asArray, shallowArrayEquals } from "../utils/arrayUtils";
40
+ import eerp from "../utils/eerp";
41
+
42
+ // Register scaleLocus to Vega-Scale.
43
+ // Loci are discrete but the scale's domain can be adjusted in a continuous manner.
44
+ vegaScale("index", scaleIndex, ["continuous"]);
45
+ vegaScale("locus", scaleLocus, ["continuous"]);
46
+ vegaScale("null", scaleNull, []);
47
+
48
+ export const QUANTITATIVE = "quantitative";
49
+ export const ORDINAL = "ordinal";
50
+ export const NOMINAL = "nominal";
51
+ export const LOCUS = "locus";
52
+ export const INDEX = "index";
53
+
54
+ /**
55
+ * @template {ChannelWithScale}[T=ChannelWithScale]
56
+ * @typedef {{view: import("./unitView").default, channel: T}} ResolutionMember
57
+ *
58
+ */
59
+ /**
60
+ * Resolution takes care of merging domains and scales from multiple views.
61
+ * This class also provides some utility methods for zooming the scales etc..
62
+ *
63
+ * TODO: This has grown a bit too fat. Consider splitting.
64
+ *
65
+ * @implements {ScaleResolutionApi}
66
+ */
67
+ export default class ScaleResolution {
68
+ /**
69
+ * @typedef {import("../types/scaleResolutionApi").ScaleResolutionApi} ScaleResolutionApi
70
+ * @typedef {import("../spec/channel").Channel} Channel
71
+ * @typedef {import("../spec/channel").ChannelWithScale} ChannelWithScale
72
+ * @typedef {import("../spec/scale").NumericDomain} NumericDomain
73
+ * @typedef {import("../spec/scale").ScalarDomain} ScalarDomain
74
+ * @typedef {import("../spec/scale").ComplexDomain} ComplexDomain
75
+ * @typedef {import("../spec/scale").ZoomParams} ZoomParams
76
+ * @typedef {import("./unitView").default} UnitView
77
+ * @typedef {import("../types/encoder").VegaScale} VegaScale
78
+ * @typedef {import("../utils/domainArray").DomainArray} DomainArray
79
+ * @typedef {import("../genome/genome").ChromosomalLocus} ChromosomalLocus
80
+ * @typedef {import("../types/scaleResolutionApi").ScaleResolutionListener} ScaleResolutionListener
81
+ */
82
+
83
+ /** @type {number[]} */
84
+ #zoomExtent = undefined;
85
+
86
+ /** @type {Set<ScaleResolutionListener>} Observers that are called when the scale domain is changed */
87
+ #domainListeners = new Set();
88
+
89
+ /** @type {VegaScale} */
90
+ #scale = undefined;
91
+
92
+ /**
93
+ * @param {Channel} channel
94
+ */
95
+ constructor(channel) {
96
+ this.channel = channel;
97
+ /** @type {ResolutionMember[]} The involved views */
98
+ this.members = [];
99
+ /** @type {string} Data type (quantitative, nominal, etc...) */
100
+ this.type = null;
101
+
102
+ /** @type {string} An optional unique identifier for the scale */
103
+ this.name = undefined;
104
+ }
105
+
106
+ /**
107
+ * Adds a listener that is called when the scale domain is changed,
108
+ * e.g., zoomed. The call is synchronous and happens before the views
109
+ * are rendered.
110
+ *
111
+ * @param {"domain"} type
112
+ * @param {ScaleResolutionListener} listener function
113
+ */
114
+ addEventListener(type, listener) {
115
+ if (type != "domain") {
116
+ throw new Error("Unsupported event type: " + type);
117
+ }
118
+ this.#domainListeners.add(listener);
119
+ }
120
+
121
+ /**
122
+ * @param {"domain"} type
123
+ * @param {ScaleResolutionListener} listener function
124
+ */
125
+ removeEventListener(type, listener) {
126
+ if (type != "domain") {
127
+ throw new Error("Unsupported event type: " + type);
128
+ }
129
+ this.#domainListeners.delete(listener);
130
+ }
131
+
132
+ #notifyDomainListeners() {
133
+ for (const listener of this.#domainListeners.values()) {
134
+ listener({
135
+ type: "domain",
136
+ scaleResolution: this,
137
+ });
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Add a view to this resolution.
143
+ * N.B. This is expected to be called in depth-first order
144
+ *
145
+ * @param {UnitView} view
146
+ * @param {ChannelWithScale} channel
147
+ */
148
+ pushUnitView(view, channel) {
149
+ const channelDef = getChannelDefWithScale(view, channel);
150
+ const type = channelDef.type;
151
+ const name = channelDef?.scale?.name;
152
+
153
+ if (name) {
154
+ if (this.name !== undefined && name != this.name) {
155
+ throw new Error(
156
+ `Shared scales have conflicting names: "${name}" vs. "${this.name}"!`
157
+ );
158
+ }
159
+ this.name = name;
160
+ }
161
+
162
+ if (!this.type) {
163
+ this.type = type;
164
+ } else if (type !== this.type && !isSecondaryChannel(channel)) {
165
+ // TODO: Include a reference to the layer
166
+ throw new Error(
167
+ `Can not use shared scale for different data types: ${this.type} vs. ${type}. Use "resolve: independent" for channel ${this.channel}`
168
+ );
169
+ // Actually, point scale could be changed into band scale
170
+ // TODO: Use the same merging logic as in: https://github.com/vega/vega-lite/blob/master/src/scale.ts
171
+ }
172
+
173
+ this.members.push({ view, channel });
174
+ }
175
+
176
+ /**
177
+ * Returns true if the domain has been defined explicitly, i.e. not extracted from the data.
178
+ */
179
+ isExplicitDomain() {
180
+ return !!this.getConfiguredDomain();
181
+ }
182
+
183
+ isDomainInitialized() {
184
+ const s = this.#scale;
185
+ if (!s) {
186
+ return false;
187
+ }
188
+
189
+ const domain = s.domain();
190
+
191
+ // We could alternatively have a flag that is set when the domain is initialized.
192
+ if (isContinuous(s.type)) {
193
+ return (
194
+ domain.length > 2 ||
195
+ (domain.length == 2 && (domain[0] !== 0 || domain[1] !== 0))
196
+ );
197
+ } else {
198
+ return domain.length > 0;
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Collects and merges scale properties from the participating views.
204
+ * Does not include inferred default values such as schemes etc.
205
+ *
206
+ * @returns {import("../spec/scale").Scale}
207
+ */
208
+ #getMergedScaleProps() {
209
+ return getCachedOrCall(this, "mergedScaleProps", () => {
210
+ const propArray = this.members
211
+ .map(
212
+ (member) =>
213
+ getChannelDefWithScale(member.view, member.channel)
214
+ .scale
215
+ )
216
+ .filter((props) => props !== undefined);
217
+
218
+ // TODO: Disabled scale: https://vega.github.io/vega-lite/docs/scale.html#disable
219
+ return mergeObjects(propArray, "scale", ["domain"]);
220
+ });
221
+ }
222
+
223
+ /**
224
+ * Returns the merged scale properties supplemented with inferred properties
225
+ * and domain.
226
+ *
227
+ * @returns {import("../spec/scale").Scale}
228
+ */
229
+ getScaleProps() {
230
+ // eslint-disable-next-line complexity
231
+ return getCachedOrCall(this, "scaleProps", () => {
232
+ const mergedProps = this.#getMergedScaleProps();
233
+ if (mergedProps === null || mergedProps.type == "null") {
234
+ // No scale (pass-thru)
235
+ // TODO: Check that the channel is compatible
236
+ return { type: "null" };
237
+ }
238
+
239
+ const props = {
240
+ ...this.#getDefaultScaleProperties(this.type),
241
+ ...mergedProps,
242
+ };
243
+
244
+ if (!props.type) {
245
+ props.type = getDefaultScaleType(this.channel, this.type);
246
+ }
247
+
248
+ const domain = this.#getInitialDomain();
249
+
250
+ if (domain && domain.length > 0) {
251
+ props.domain = domain;
252
+ } else if (isDiscrete(props.type)) {
253
+ props.domain = new NominalDomain();
254
+ }
255
+
256
+ if (!props.domain && props.domainMid !== undefined) {
257
+ // Initialize with a bogus domain so that scale.js can inject the domainMid.
258
+ // The number of domain elements must be know before the glsl scale is generated.
259
+ props.domain = [props.domainMin ?? 0, props.domainMax ?? 1];
260
+ }
261
+
262
+ // Reverse discrete y axis
263
+ if (
264
+ this.channel == "y" &&
265
+ isDiscrete(props.type) &&
266
+ props.reverse == undefined
267
+ ) {
268
+ props.reverse = true;
269
+ }
270
+
271
+ if (props.range && props.scheme) {
272
+ delete props.scheme;
273
+ // TODO: Props should be set more intelligently
274
+ /*
275
+ throw new Error(
276
+ `Scale has both "range" and "scheme" defined! Views: ${this._getViewPaths()}`
277
+ );
278
+ */
279
+ }
280
+
281
+ // By default, index and locus scales are zoomable, others are not
282
+ if (!("zoom" in props) && ["index", "locus"].includes(props.type)) {
283
+ props.zoom = true;
284
+ }
285
+
286
+ applyLockedProperties(props, this.channel);
287
+
288
+ return props;
289
+ });
290
+ }
291
+
292
+ #getInitialDomain() {
293
+ // TODO: intersect the domain with zoom extent (if it's defined)
294
+ return (
295
+ this.getConfiguredDomain() ??
296
+ (this.type == LOCUS
297
+ ? this.getGenome().getExtent()
298
+ : this.getDataDomain())
299
+ );
300
+ }
301
+
302
+ /**
303
+ * Unions the configured domains of all participating views.
304
+ *
305
+ * @return { DomainArray }
306
+ */
307
+ getConfiguredDomain() {
308
+ return this.#reduceDomains((member) =>
309
+ isSecondaryChannel(member.channel)
310
+ ? undefined
311
+ : member.view.getConfiguredDomain(member.channel)
312
+ );
313
+ }
314
+
315
+ /**
316
+ * Extracts and unions the data domains of all participating views.
317
+ *
318
+ * @return { DomainArray }
319
+ */
320
+ getDataDomain() {
321
+ // TODO: Optimize: extract domain only once if the views share the data.
322
+ // In fact, this should be a responsibility of collectors.
323
+ return this.#reduceDomains((member) =>
324
+ isSecondaryChannel(member.channel)
325
+ ? undefined
326
+ : member.view.extractDataDomain(member.channel)
327
+ );
328
+ }
329
+
330
+ /**
331
+ * Reconfigures the scale: updates domain and other settings
332
+ */
333
+ reconfigure() {
334
+ if (this.#scale && this.#scale.type != "null") {
335
+ const domainWasInitialized = this.isDomainInitialized();
336
+
337
+ const previousDomain = this.#scale.domain();
338
+
339
+ invalidate(this, "scaleProps");
340
+ const props = this.getScaleProps();
341
+ configureScale(props, this.#scale);
342
+ if (isContinuous(this.#scale.type)) {
343
+ this.#zoomExtent = this.#getZoomExtent();
344
+ }
345
+
346
+ if (!domainWasInitialized) {
347
+ this.#notifyDomainListeners();
348
+ return;
349
+ }
350
+
351
+ const newDomain = this.#scale.domain();
352
+ if (!shallowArrayEquals(newDomain, previousDomain)) {
353
+ if (this.isZoomable()) {
354
+ // Don't mess with zoomed views, restore the previous domain
355
+ this.#scale.domain(previousDomain);
356
+ } else if (this.#isZoomingSupported()) {
357
+ // It can be zoomed, so lets make a smooth transition.
358
+ // Restore the previous domain and zoom smoothly to the new domain.
359
+ this.#scale.domain(previousDomain);
360
+ this.zoomTo(newDomain, 500); // TODO: Configurable duration
361
+ } else {
362
+ // Update immediately if the previous domain was the initial domain [0, 0]
363
+ this.#notifyDomainListeners();
364
+ }
365
+ }
366
+ }
367
+ }
368
+
369
+ /**
370
+ * @returns {VegaScale}
371
+ */
372
+ getScale() {
373
+ if (this.#scale) {
374
+ return this.#scale;
375
+ }
376
+
377
+ const props = this.getScaleProps();
378
+
379
+ const scale = createScale(props);
380
+ this.#scale = scale;
381
+
382
+ if (isScaleLocus(scale)) {
383
+ scale.genome(this.getGenome());
384
+ }
385
+
386
+ if (isContinuous(scale.type)) {
387
+ this.#zoomExtent = this.#getZoomExtent();
388
+ }
389
+
390
+ return scale;
391
+ }
392
+
393
+ getDomain() {
394
+ return this.getScale().domain();
395
+ }
396
+
397
+ /**
398
+ * @returns {NumericDomain | ComplexDomain}
399
+ */
400
+ getComplexDomain() {
401
+ return (
402
+ this.getGenome()?.toChromosomalInterval(this.getDomain()) ??
403
+ this.getDomain()
404
+ );
405
+ }
406
+
407
+ /**
408
+ * Return true if the scale is zoomable and the current domain differs from the initial domain.
409
+ *
410
+ * @returns true if zoomed
411
+ */
412
+ isZoomed() {
413
+ return (
414
+ this.#isZoomingSupported() &&
415
+ shallowArrayEquals(this.#getInitialDomain(), this.getDomain())
416
+ );
417
+ }
418
+
419
+ /**
420
+ * Returns true if zooming is supported and allowed in view spec.
421
+ */
422
+ isZoomable() {
423
+ // Check explicit configuration
424
+ return this.#isZoomingSupported() && !!this.getScaleProps().zoom;
425
+ }
426
+
427
+ /**
428
+ * Returns true if zooming is supported but not necessarily allowed in view spec.
429
+ */
430
+ #isZoomingSupported() {
431
+ const type = this.getScale().type;
432
+ return isContinuous(type);
433
+ }
434
+
435
+ /**
436
+ * Pans (translates) and zooms using a specified scale factor.
437
+ *
438
+ * @param {number} scaleFactor
439
+ * @param {number} scaleAnchor
440
+ * @param {number} pan
441
+ * @returns {boolean} true if the scale was zoomed
442
+ */
443
+ zoom(scaleFactor, scaleAnchor, pan) {
444
+ if (!this.#isZoomingSupported()) {
445
+ return false;
446
+ }
447
+
448
+ const scale = this.getScale();
449
+ const oldDomain = scale.domain();
450
+ let newDomain = [...oldDomain];
451
+
452
+ // @ts-expect-error
453
+ let anchor = scale.invert(scaleAnchor);
454
+
455
+ if (this.getScaleProps().reverse) {
456
+ pan = -pan;
457
+ }
458
+
459
+ if ("align" in scale) {
460
+ anchor += scale.align();
461
+ }
462
+
463
+ // TODO: symlog
464
+ switch (scale.type) {
465
+ case "linear":
466
+ case "index":
467
+ case "locus":
468
+ newDomain = panLinear(newDomain, pan || 0);
469
+ newDomain = zoomLinear(newDomain, anchor, scaleFactor);
470
+ break;
471
+ case "log":
472
+ newDomain = panLog(newDomain, pan || 0);
473
+ newDomain = zoomLog(newDomain, anchor, scaleFactor);
474
+ break;
475
+ case "pow":
476
+ case "sqrt": {
477
+ const powScale =
478
+ /** @type {import("d3-scale").ScalePower<number, number>} */ (
479
+ scale
480
+ );
481
+ newDomain = panPow(newDomain, pan || 0, powScale.exponent());
482
+ newDomain = zoomPow(
483
+ newDomain,
484
+ anchor,
485
+ scaleFactor,
486
+ powScale.exponent()
487
+ );
488
+ break;
489
+ }
490
+ default:
491
+ throw new Error(
492
+ "Zooming is not implemented for: " + scale.type
493
+ );
494
+ }
495
+
496
+ // TODO: Use the zoomTo method. Move clamping etc there.
497
+ if (this.#zoomExtent) {
498
+ newDomain = clampRange(
499
+ newDomain,
500
+ this.#zoomExtent[0],
501
+ this.#zoomExtent[1]
502
+ );
503
+ }
504
+
505
+ if ([0, 1].some((i) => newDomain[i] != oldDomain[i])) {
506
+ scale.domain(newDomain);
507
+ this.#notifyDomainListeners();
508
+ return true;
509
+ }
510
+
511
+ return false;
512
+ }
513
+
514
+ /**
515
+ * Immediately zooms to the given interval.
516
+ *
517
+ * @param {NumericDomain | ComplexDomain} domain
518
+ * @param {boolean | number} [duration] an approximate duration for transition.
519
+ * Zero duration zooms immediately. Boolean `true` indicates a default duration.
520
+ */
521
+ async zoomTo(domain, duration = false) {
522
+ if (isBoolean(duration)) {
523
+ duration = duration ? 700 : 0;
524
+ }
525
+
526
+ if (!this.#isZoomingSupported()) {
527
+ throw new Error("Not a zoomable scale!");
528
+ }
529
+
530
+ const to = this.fromComplexInterval(domain);
531
+
532
+ // TODO: Intersect the domain with zoom extent
533
+
534
+ const animator = this.members[0]?.view.context.animator;
535
+
536
+ const scale = this.getScale();
537
+ const from = /** @type {number[]} */ (scale.domain());
538
+
539
+ if (duration > 0 && from.length == 2) {
540
+ const fw = from[1] - from[0];
541
+ const fc = from[0] + fw / 2;
542
+
543
+ const tw = to[1] - to[0];
544
+ const tc = to[0] + tw / 2;
545
+
546
+ // TODO: Abort possible previous transition
547
+ await animator.transition({
548
+ duration,
549
+ easingFunction: easeCubicInOut,
550
+ onUpdate: (t) => {
551
+ const w = eerp(fw, tw, t);
552
+ const wt = (fw - w) / (fw - tw);
553
+ const c = wt * tc + (1 - wt) * fc;
554
+ scale.domain([c - w / 2, c + w / 2]);
555
+ this.#notifyDomainListeners();
556
+ },
557
+ });
558
+
559
+ scale.domain(to);
560
+ this.#notifyDomainListeners();
561
+ } else {
562
+ scale.domain(to);
563
+ animator?.requestRender();
564
+ this.#notifyDomainListeners();
565
+ }
566
+ }
567
+
568
+ /**
569
+ * Resets the current domain to the initial one
570
+ *
571
+ * @returns true if the domain was changed
572
+ */
573
+ resetZoom() {
574
+ if (!this.#isZoomingSupported()) {
575
+ throw new Error("Not a zoomable scale!");
576
+ }
577
+
578
+ const oldDomain = this.getDomain();
579
+ const newDomain = this.#getInitialDomain();
580
+
581
+ if ([0, 1].some((i) => newDomain[i] != oldDomain[i])) {
582
+ this.#scale.domain(newDomain);
583
+ this.#notifyDomainListeners();
584
+ return true;
585
+ }
586
+ return false;
587
+ }
588
+
589
+ /**
590
+ * Returns the zoom level with respect to the reference domain span (the original domain).
591
+ *
592
+ * In principle, this is highly specific to positional channels. However, zooming can
593
+ * be generalized to other quantitative channels such as color, opacity, size, etc.
594
+ */
595
+ getZoomLevel() {
596
+ // Zoom level makes sense only for user-zoomable scales where zoom extent is defined
597
+ if (this.isZoomable()) {
598
+ return span(this.#zoomExtent) / span(this.getScale().domain());
599
+ }
600
+
601
+ return 1.0;
602
+ }
603
+
604
+ #getZoomExtent() {
605
+ const props = this.getScaleProps();
606
+ const zoom = props.zoom;
607
+
608
+ if (isZoomParams(zoom)) {
609
+ if (isArray(zoom.extent)) {
610
+ return this.fromComplexInterval(zoom.extent);
611
+ }
612
+ }
613
+
614
+ if (zoom) {
615
+ if (props.type == "locus") {
616
+ return this.getGenome().getExtent();
617
+ }
618
+
619
+ // TODO: Perhaps this should be "domain" for index scale and nothing for quantitative.
620
+ // Would behave similarly to Vega-Lite, which doesn't have constraints.
621
+ return this.#scale.domain();
622
+ }
623
+ }
624
+
625
+ /**
626
+ * TODO: These actually depend on the mark, so this is clearly a wrong place.
627
+ * And besides, these should be configurable (themeable)
628
+ *
629
+ * @param {string} dataType
630
+ */
631
+ #getDefaultScaleProperties(dataType) {
632
+ const channel = this.channel;
633
+ const props = {};
634
+
635
+ if (this.isExplicitDomain()) {
636
+ props.zero = false;
637
+ }
638
+
639
+ if (isPositionalChannel(channel)) {
640
+ props.nice = !this.isExplicitDomain();
641
+ } else if (isColorChannel(channel)) {
642
+ // TODO: Named ranges
643
+ props.scheme =
644
+ dataType == NOMINAL
645
+ ? "tableau10"
646
+ : dataType == ORDINAL
647
+ ? "blues"
648
+ : "viridis";
649
+ } else if (isDiscreteChannel(channel)) {
650
+ // Shapes of point mark, for example
651
+ props.range = getDiscreteRange(channel);
652
+ } else if (channel == "size") {
653
+ props.range = [0, 400]; // TODO: Configurable default. This is currently optimized for points.
654
+ } else if (channel == "angle") {
655
+ props.range = [0, 360];
656
+ }
657
+
658
+ return props;
659
+ }
660
+
661
+ getGenome() {
662
+ if (this.type !== "locus") {
663
+ return undefined;
664
+ }
665
+
666
+ // TODO: Support multiple assemblies
667
+ const genome = this.members[0].view.context.genomeStore?.getGenome();
668
+ if (!genome) {
669
+ throw new Error("No genome has been defined!");
670
+ }
671
+ return genome;
672
+ }
673
+
674
+ // TODO: Move the "complex" stuff into scaleLocus.
675
+
676
+ /**
677
+ * Inverts a value in range to a value on domain. Returns an object in
678
+ * case of locus scale.
679
+ *
680
+ * @param {number} value
681
+ */
682
+ invertToComplex(value) {
683
+ const scale = this.getScale();
684
+ if ("invert" in scale) {
685
+ const inverted = /** @type {number} */ (scale.invert(value));
686
+ return this.toComplex(inverted);
687
+ } else {
688
+ throw new Error("The scale does not support inverting!");
689
+ }
690
+ }
691
+
692
+ /**
693
+ * @param {number} value
694
+ */
695
+ toComplex(value) {
696
+ const genome = this.getGenome();
697
+ return genome ? genome.toChromosomal(value) : value;
698
+ }
699
+
700
+ /**
701
+ * @param {number | ChromosomalLocus} complex
702
+ * @returns {number}
703
+ */
704
+ fromComplex(complex) {
705
+ if (isChromosomalLocus(complex)) {
706
+ const genome = this.getGenome();
707
+ return genome.toContinuous(complex.chrom, complex.pos);
708
+ }
709
+ return complex;
710
+ }
711
+
712
+ /**
713
+ * @param {ScalarDomain | ComplexDomain} interval
714
+ * @returns {number[]}
715
+ */
716
+ fromComplexInterval(interval) {
717
+ if (this.type === "locus" && isChromosomalLocusInterval(interval)) {
718
+ return this.getGenome().toContinuousInterval(interval);
719
+ }
720
+ return /** @type {number[]} */ (interval);
721
+ }
722
+
723
+ #getViewPaths() {
724
+ return this.members.map((v) => v.view.getPathString()).join(", ");
725
+ }
726
+
727
+ /**
728
+ * Iterate all participanting views and reduce (union) their domains using an accessor.
729
+ * Accessor may return the an explicitly configured domain or a domain extracted from the data.
730
+ *
731
+ * @param {function(ResolutionMember):DomainArray} domainAccessor
732
+ * @returns {DomainArray}
733
+ */
734
+ #reduceDomains(domainAccessor) {
735
+ const domains = this.members
736
+ .filter(
737
+ (member) =>
738
+ !member.view
739
+ .getLayoutAncestors()
740
+ // TODO: Should check until the resolved scale resolution
741
+ .some((view) => !view.contributesToScaleDomain)
742
+ )
743
+ .map(domainAccessor)
744
+ .filter((domain) => !!domain);
745
+
746
+ if (domains.length) {
747
+ return domains.reduce((acc, curr) => acc.extendAll(curr));
748
+ }
749
+ }
750
+ }
751
+
752
+ /**
753
+ *
754
+ * @param {Channel} channel
755
+ * @param {string} dataType
756
+ * @returns {import("../spec/scale").ScaleType}
757
+ */
758
+ function getDefaultScaleType(channel, dataType) {
759
+ // TODO: Band scale, Bin-Quantitative
760
+
761
+ if (dataType == INDEX || dataType == LOCUS) {
762
+ if (isPrimaryPositionalChannel(channel)) {
763
+ return dataType;
764
+ } else {
765
+ // TODO: Also explicitly set scales should be validated
766
+ throw new Error(
767
+ `${channel} does not support ${dataType} data type. Only positional channels do.`
768
+ );
769
+ }
770
+ }
771
+
772
+ /**
773
+ * @type {Partial<Record<Channel, (import("../spec/scale").ScaleType | undefined)[]>>}
774
+ * Default types: nominal, ordinal, quantitative.
775
+ * undefined = incompatible, "null" = disabled (pass-thru)
776
+ */
777
+ const defaults = {
778
+ x: ["band", "band", "linear"],
779
+ y: ["band", "band", "linear"],
780
+ size: [undefined, "point", "linear"],
781
+ opacity: [undefined, "point", "linear"],
782
+ fillOpacity: [undefined, "point", "linear"],
783
+ strokeOpacity: [undefined, "point", "linear"],
784
+ color: ["ordinal", "ordinal", "linear"],
785
+ fill: ["ordinal", "ordinal", "linear"],
786
+ stroke: ["ordinal", "ordinal", "linear"],
787
+ strokeWidth: [undefined, undefined, "linear"],
788
+ shape: ["ordinal", "ordinal", undefined],
789
+ dx: [undefined, undefined, "null"],
790
+ dy: [undefined, undefined, "null"],
791
+ angle: [undefined, undefined, "linear"],
792
+ };
793
+
794
+ /** @type {Channel[]} */
795
+ const typelessChannels = ["sample"];
796
+
797
+ const type = typelessChannels.includes(channel)
798
+ ? "null"
799
+ : defaults[channel]
800
+ ? defaults[channel][[NOMINAL, ORDINAL, QUANTITATIVE].indexOf(dataType)]
801
+ : dataType == QUANTITATIVE
802
+ ? "linear"
803
+ : "ordinal";
804
+
805
+ if (type === undefined) {
806
+ throw new Error(
807
+ `Channel "${channel}" is not compatible with "${dataType}" data type. Use of a proper scale may be needed.`
808
+ );
809
+ }
810
+
811
+ return type;
812
+ }
813
+
814
+ /**
815
+ * @param {import("../spec/scale").Scale} props
816
+ * @param {import("../spec/channel").Channel} channel
817
+ */
818
+ function applyLockedProperties(props, channel) {
819
+ if (isPositionalChannel(channel) && props.type !== "ordinal") {
820
+ props.range = [0, 1];
821
+ }
822
+
823
+ if (channel == "opacity" && isContinuous(props.type)) {
824
+ props.clamp = true;
825
+ }
826
+ }
827
+
828
+ /**
829
+ *
830
+ * @param {boolean | ZoomParams} zoom
831
+ * @returns {zoom is ZoomParams}
832
+ */
833
+ function isZoomParams(zoom) {
834
+ return isObject(zoom);
835
+ }
836
+
837
+ /**
838
+ * Reconfigures scales, starting from the given view.
839
+ *
840
+ * TODO: This should be made unnecessary. Collectors should trigger the reconfiguration
841
+ * for those views that get their data from the collector.
842
+ *
843
+ * TODO: This may reconfigure channels that are not affected by the change.
844
+ * Causes performance issues with domains that are extracted from data.
845
+ *
846
+ * @param {import("./view").default | import("./view").default[]} fromViews
847
+ */
848
+ export function reconfigureScales(fromViews) {
849
+ /** @type {Set<ScaleResolution>} */
850
+ const uniqueResolutions = new Set();
851
+
852
+ /** @param {import("./view").default} view */
853
+ function collectResolutions(view) {
854
+ for (const resolution of Object.values(view.resolutions.scale)) {
855
+ uniqueResolutions.add(resolution);
856
+ }
857
+ }
858
+
859
+ for (const fromView of asArray(fromViews)) {
860
+ // Descendants
861
+ fromView.visit(collectResolutions);
862
+
863
+ // Ancestors
864
+ for (const view of fromView.getDataAncestors()) {
865
+ // Skip axis views etc. They should not mess with the domains.
866
+ if (!view.contributesToScaleDomain) {
867
+ break;
868
+ }
869
+ collectResolutions(view);
870
+ }
871
+ }
872
+
873
+ uniqueResolutions.forEach((resolution) => resolution.reconfigure());
874
+ }