@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,788 @@
1
+ import { formats as vegaFormats } from "vega-loader";
2
+
3
+ import css from "./styles/genome-spy.css.js";
4
+ import Tooltip from "./utils/ui/tooltip";
5
+
6
+ import AccessorFactory from "./encoder/accessor";
7
+ import {
8
+ resolveScalesAndAxes,
9
+ processImports,
10
+ setImplicitScaleNames,
11
+ calculateCanvasSize,
12
+ } from "./view/viewUtils";
13
+ import UnitView from "./view/unitView";
14
+
15
+ import WebGLHelper from "./gl/webGLHelper";
16
+ import Rectangle from "./utils/layout/rectangle";
17
+ import BufferedViewRenderingContext from "./view/renderingContext/bufferedViewRenderingContext";
18
+ import CompositeViewRenderingContext from "./view/renderingContext/compositeViewRenderingContext";
19
+ import InteractionEvent from "./utils/interactionEvent";
20
+ import Point from "./utils/layout/point";
21
+ import Animator from "./utils/animator";
22
+ import DataFlow from "./data/dataFlow";
23
+ import { buildDataFlow } from "./view/flowBuilder";
24
+ import { optimizeDataFlow } from "./data/flowOptimizer";
25
+ import GenomeStore from "./genome/genomeStore";
26
+ import BmFontManager from "./fonts/bmFontManager";
27
+ import fasta from "./data/formats/fasta";
28
+ import { VISIT_STOP } from "./view/view";
29
+ import Inertia, { makeEventTemplate } from "./utils/inertia";
30
+ import refseqGeneTooltipHandler from "./tooltip/refseqGeneTooltipHandler";
31
+ import dataTooltipHandler from "./tooltip/dataTooltipHandler";
32
+ import { invalidatePrefix } from "./utils/propertyCacher";
33
+ import { ViewFactory } from "./view/viewFactory";
34
+ import ImplicitRootView from "./view/implicitRootView";
35
+ import { reconfigureScales } from "./view/scaleResolution";
36
+
37
+ /**
38
+ * Events that are broadcasted to all views.
39
+ * @typedef {"dataFlowBuilt" | "dataLoaded" | "layout" | "layoutComputed"} BroadcastEventType
40
+ */
41
+
42
+ vegaFormats("fasta", fasta);
43
+
44
+ export default class GenomeSpy {
45
+ /**
46
+ * @typedef {import("./view/view").default} View
47
+ * @typedef {import("./spec/view").ViewSpec} ViewSpec
48
+ * @typedef {import("./spec/root").RootSpec} RootSpec
49
+ * @typedef {import("./spec/root").RootConfig} RootConfig
50
+ */
51
+
52
+ /**
53
+ *
54
+ * @param {HTMLElement} container
55
+ * @param {RootSpec} spec
56
+ * @param {import("./types/embedApi").EmbedOptions} [options]
57
+ */
58
+ constructor(container, spec, options = {}) {
59
+ this.container = container;
60
+
61
+ const styleElement = document.createElement("style");
62
+ styleElement.innerHTML = css;
63
+ container.appendChild(styleElement);
64
+
65
+ /** Root level configuration object */
66
+ this.spec = spec;
67
+
68
+ this.accessorFactory = new AccessorFactory();
69
+ this.viewFactory = new ViewFactory();
70
+
71
+ /** @type {(function(string):object[])[]} */
72
+ this.namedDataProviders = [];
73
+
74
+ this.animator = new Animator(() => this.renderAll());
75
+
76
+ /** @type {GenomeStore} */
77
+ this.genomeStore = undefined;
78
+
79
+ /**
80
+ * View visibility is checked using a predicate that can be overridden
81
+ * for more dynamic visibility management.
82
+ *
83
+ * @type {(view: View) => boolean}
84
+ */
85
+ this.viewVisibilityPredicate = (view) => view.isVisibleInSpec();
86
+
87
+ /** @type {BufferedViewRenderingContext} */
88
+ this._renderingContext = undefined;
89
+ /** @type {BufferedViewRenderingContext} */
90
+ this._pickingContext = undefined;
91
+
92
+ /** Does picking buffer need to be rendered again */
93
+ this._dirtyPickingBuffer = false;
94
+
95
+ /**
96
+ * Currently hovered mark and datum
97
+ * @type {{ mark: import("./marks/mark").default, datum: import("./data/flowNode").Datum, uniqueId: number }}
98
+ */
99
+ this._currentHover = undefined;
100
+
101
+ this._wheelInertia = new Inertia(this.animator);
102
+
103
+ /**
104
+ * Keeping track so that these can be cleaned up upon finalization.
105
+ * @type {Map<string, (function(KeyboardEvent):void)[]>}
106
+ */
107
+ this._keyboardListeners = new Map();
108
+
109
+ /**
110
+ * Listers for exposed high-level events such as click on a mark instance.
111
+ * These should probably be in the View class and support bubbling through
112
+ * the hierarchy.
113
+ *
114
+ * @type {Map<string, Set<(event: any) => void>>}
115
+ */
116
+ this._eventListeners = new Map();
117
+
118
+ /**
119
+ *
120
+ * @type {Map<string, Set<(event: any) => void>>}
121
+ */
122
+ this._extraBroadcastListeners = new Map();
123
+
124
+ /** @type {Record<string, import("./tooltip/tooltipHandler").TooltipHandler>}> */
125
+ this.tooltipHandlers = {
126
+ default: dataTooltipHandler,
127
+ refseqgene: refseqGeneTooltipHandler,
128
+ ...(options.tooltipHandlers ?? {}),
129
+ };
130
+
131
+ /** @type {View} */
132
+ this.viewRoot = undefined;
133
+ }
134
+
135
+ /**
136
+ *
137
+ * @param {(name: string) => any[]} provider
138
+ */
139
+ registerNamedDataProvider(provider) {
140
+ this.namedDataProviders.unshift(provider);
141
+ }
142
+
143
+ /**
144
+ * @param {string} name
145
+ */
146
+ getNamedDataFromProvider(name) {
147
+ for (const provider of this.namedDataProviders) {
148
+ const data = provider(name);
149
+ if (data) {
150
+ return data;
151
+ }
152
+ }
153
+ }
154
+
155
+ /**
156
+ *
157
+ * @param {string} name
158
+ * @param {any[]} data
159
+ */
160
+ updateNamedData(name, data) {
161
+ const namedSource =
162
+ this.viewRoot.context.dataFlow.findNamedDataSource(name);
163
+ if (!namedSource) {
164
+ throw new Error("No such named data source: " + name);
165
+ }
166
+
167
+ namedSource.dataSource.updateDynamicData(data);
168
+ reconfigureScales(namedSource.hosts);
169
+
170
+ this.animator.requestRender();
171
+ }
172
+
173
+ /**
174
+ * Broadcast a message to all views
175
+
176
+ * @param {BroadcastEventType} type
177
+ * @param {any} [payload]
178
+ */
179
+ broadcast(type, payload) {
180
+ const message = { type, payload };
181
+ this.viewRoot.visit((view) => view.handleBroadcast(message));
182
+ this._extraBroadcastListeners
183
+ .get(type)
184
+ ?.forEach((listener) => listener(message));
185
+ }
186
+
187
+ _prepareContainer() {
188
+ this.container.classList.add("genome-spy");
189
+ this.container.classList.add("loading");
190
+
191
+ this._glHelper = new WebGLHelper(
192
+ this.container,
193
+ () =>
194
+ this.viewRoot
195
+ ? calculateCanvasSize(this.viewRoot)
196
+ : { width: undefined, height: undefined },
197
+ this.spec.background
198
+ );
199
+
200
+ this.loadingMessageElement = document.createElement("div");
201
+ this.loadingMessageElement.className = "loading-message";
202
+ this.loadingMessageElement.innerHTML = `<div class="message">Loading<span class="ellipsis">...</span></div>`;
203
+ this.container.appendChild(this.loadingMessageElement);
204
+
205
+ this.tooltip = new Tooltip(this.container);
206
+
207
+ this.loadingMessageElement
208
+ .querySelector(".message")
209
+ .addEventListener("transitionend", () => {
210
+ /** @type {HTMLElement} */ (
211
+ this.loadingMessageElement
212
+ ).style.display = "none";
213
+ });
214
+ }
215
+
216
+ /**
217
+ * Unregisters all listeners, removes all created dom elements, removes all css classes from the container
218
+ */
219
+ destroy() {
220
+ // TODO: There's a memory leak somewhere
221
+
222
+ this.container.classList.remove("genome-spy");
223
+ this.container.classList.remove("loading");
224
+
225
+ for (const [type, listeners] of this._keyboardListeners) {
226
+ for (const listener of listeners) {
227
+ document.removeEventListener(type, listener);
228
+ }
229
+ }
230
+
231
+ this._glHelper.finalize();
232
+
233
+ while (this.container.firstChild) {
234
+ this.container.firstChild.remove();
235
+ }
236
+ }
237
+
238
+ async _prepareViewsAndData() {
239
+ if (this.spec.genome) {
240
+ this.genomeStore = new GenomeStore(this.spec.baseUrl);
241
+ await this.genomeStore.initialize(this.spec.genome);
242
+ }
243
+
244
+ // eslint-disable-next-line consistent-this
245
+ const self = this;
246
+
247
+ /** @type {import("./types/viewContext").default} */
248
+ const context = {
249
+ dataFlow: new DataFlow(),
250
+ accessorFactory: this.accessorFactory,
251
+ glHelper: this._glHelper,
252
+ animator: this.animator,
253
+ genomeStore: this.genomeStore,
254
+ fontManager: new BmFontManager(this._glHelper),
255
+
256
+ get devicePixelRatio() {
257
+ return self._glHelper.dpr;
258
+ },
259
+
260
+ requestLayoutReflow: () => {
261
+ // placeholder
262
+ },
263
+ updateTooltip: this.updateTooltip.bind(this),
264
+ getNamedDataFromProvider: this.getNamedDataFromProvider.bind(this),
265
+ getCurrentHover: () => this._currentHover,
266
+
267
+ addKeyboardListener: (type, listener) => {
268
+ // TODO: Listeners should be called only when the mouse pointer is inside the
269
+ // container or the app covers the full document.
270
+ document.addEventListener(type, listener);
271
+ let listeners = this._keyboardListeners.get(type);
272
+ if (!listeners) {
273
+ listeners = [];
274
+ this._keyboardListeners.set(type, listeners);
275
+ }
276
+ listeners.push(listener);
277
+ },
278
+
279
+ addBroadcastListener(type, listener) {
280
+ const listenersByType = self._extraBroadcastListeners;
281
+
282
+ // Copy-paste code. TODO: Refactor into a helper function.
283
+ let listeners = listenersByType.get(type);
284
+ if (!listeners) {
285
+ listeners = new Set();
286
+ listenersByType.set(type, listeners);
287
+ }
288
+
289
+ listeners.add(listener);
290
+ },
291
+
292
+ removeBroadcastListener(type, listener) {
293
+ const listenersByType = self._extraBroadcastListeners;
294
+
295
+ listenersByType.get(type)?.delete(listener);
296
+ },
297
+
298
+ isViewConfiguredVisible: self.viewVisibilityPredicate,
299
+
300
+ isViewSpec: (spec) => self.viewFactory.isViewSpec(spec),
301
+
302
+ createView: function (spec, layoutParent, dataParent, defaultName) {
303
+ return self.viewFactory.createView(
304
+ spec,
305
+ context,
306
+ layoutParent,
307
+ dataParent,
308
+ defaultName
309
+ );
310
+ },
311
+ };
312
+
313
+ /** @type {ViewSpec & RootConfig} */
314
+ const rootSpec = this.spec;
315
+
316
+ if (rootSpec.datasets) {
317
+ this.registerNamedDataProvider((name) => rootSpec.datasets[name]);
318
+ }
319
+
320
+ // Create the view hierarchy
321
+ this.viewRoot = context.createView(rootSpec, null, null, "viewRoot");
322
+
323
+ // Replace placeholder ImportViews with actual views.
324
+ await processImports(this.viewRoot);
325
+
326
+ if (this.viewRoot.needsAxes.x || this.viewRoot.needsAxes.y) {
327
+ this.viewRoot = new ImplicitRootView(context, this.viewRoot);
328
+ }
329
+
330
+ // Resolve scales, i.e., if possible, pull them towards the root
331
+ resolveScalesAndAxes(this.viewRoot);
332
+ setImplicitScaleNames(this.viewRoot);
333
+
334
+ // Wrap unit or layer views that need axes
335
+ //this.viewRoot = addDecorators(this.viewRoot);
336
+
337
+ // We should now have a complete view hierarchy. Let's update the canvas size
338
+ // and ensure that the loading message is visible.
339
+ this._glHelper.invalidateSize();
340
+
341
+ // Collect all unit views to a list because they need plenty of initialization
342
+ /** @type {UnitView[]} */
343
+ const unitViews = [];
344
+ this.viewRoot.visit((view) => {
345
+ if (view instanceof UnitView) {
346
+ unitViews.push(view);
347
+ }
348
+ });
349
+
350
+ // Build the data flow based on the view hierarchy
351
+ const flow = buildDataFlow(this.viewRoot, context.dataFlow);
352
+ optimizeDataFlow(flow);
353
+ this.broadcast("dataFlowBuilt", flow);
354
+
355
+ // @ts-expect-error
356
+ if (import.meta.env.DEV) {
357
+ flow.dataSources.forEach((ds) => console.log(ds.subtreeToString()));
358
+ }
359
+
360
+ // Create encoders (accessors, scales and related metadata)
361
+ unitViews.forEach((view) => view.mark.initializeEncoders());
362
+
363
+ // Compile shaders, create or load textures, etc.
364
+ const graphicsInitialized = Promise.all(
365
+ unitViews.map((view) => view.mark.initializeGraphics())
366
+ );
367
+
368
+ for (const view of unitViews) {
369
+ flow.addObserver((collector) => {
370
+ view.mark.initializeData();
371
+ // Update WebGL buffers
372
+ view.mark.updateGraphicsData();
373
+ }, view);
374
+ }
375
+
376
+ // Have to wait until asynchronous font loading is complete.
377
+ // Text mark's geometry builder needs font metrics before data can be
378
+ // converted into geometries.
379
+ await context.fontManager.waitUntilReady();
380
+
381
+ // Find all data sources and initiate loading
382
+ flow.initialize();
383
+ await Promise.all(
384
+ flow.dataSources.map((dataSource) => dataSource.load())
385
+ );
386
+
387
+ // Now that all data have been loaded, the domains may need adjusting
388
+ // IMPORTANT TODO: Check that discrete domains and indexers match!!!!!!!!!
389
+ reconfigureScales(this.viewRoot);
390
+
391
+ // This event is needed by SampleView so that it can extract the sample ids
392
+ // from the data once they are loaded.
393
+ // TODO: It would be great if this could be attached to the data flow,
394
+ // because now this is somewhat a hack and is incompatible with dynamic data
395
+ // loading in the future.
396
+ this.broadcast("dataLoaded");
397
+
398
+ await graphicsInitialized;
399
+
400
+ this.viewRoot.visit((view) => {
401
+ for (const resolution of Object.values(view.resolutions.scale)) {
402
+ this._glHelper.createRangeTexture(resolution);
403
+ }
404
+ });
405
+
406
+ for (const view of unitViews) {
407
+ view.mark.finalizeGraphicsInitialization();
408
+ }
409
+
410
+ // Allow layout computation
411
+ // eslint-disable-next-line require-atomic-updates
412
+ context.requestLayoutReflow = this.computeLayout.bind(this);
413
+
414
+ // Invalidate cached sizes to ensure that step-based sizes are current.
415
+ // TODO: This should be done automatically when the domains of band/point scales are updated.
416
+ this.viewRoot.visit((view) => invalidatePrefix(view, "size"));
417
+ this._glHelper.invalidateSize();
418
+ }
419
+
420
+ /**
421
+ * TODO: Come up with a sensible name. And maybe this should be called at the end of the constructor.
422
+ * @returns {Promise<boolean>} true if the launch was successful
423
+ */
424
+ async launch() {
425
+ try {
426
+ this._prepareContainer();
427
+
428
+ await this._prepareViewsAndData();
429
+
430
+ this.registerMouseEvents();
431
+
432
+ this.computeLayout();
433
+ this.animator.requestRender();
434
+
435
+ // Register resize listener after the initial layout computation to prevent
436
+ // incomplete layouts from accidentally polluting any caches related to sizes.
437
+ this._glHelper.addEventListener("resize", () => {
438
+ this.computeLayout();
439
+ // Render immediately, without RAF
440
+ this.renderAll();
441
+ });
442
+
443
+ return true;
444
+ } catch (reason) {
445
+ const message = `${
446
+ reason.view ? `At "${reason.view.getPathString()}": ` : ""
447
+ }${reason.toString()}`;
448
+ console.error(reason.stack);
449
+ createMessageBox(this.container, message);
450
+
451
+ return false;
452
+ } finally {
453
+ this.container.classList.remove("loading");
454
+ // Transition listener doesn't appear to work on observablehq
455
+ window.setTimeout(() => {
456
+ this.loadingMessageElement.style.display = "none";
457
+ }, 2000);
458
+ }
459
+ }
460
+
461
+ registerMouseEvents() {
462
+ const canvas = this._glHelper.canvas;
463
+
464
+ // TODO: This function is huge. Refactor this into a separate class
465
+ // that would also contain state-related stuff that currently pollute the
466
+ // GenomeSpy class.
467
+
468
+ /** @param {Event} event */
469
+ const listener = (event) => {
470
+ if (event instanceof MouseEvent) {
471
+ if (event.type == "mousemove") {
472
+ this.tooltip.handleMouseMove(event);
473
+ this._tooltipUpdateRequested = false;
474
+
475
+ if (event.buttons == 0) {
476
+ // Disable during dragging
477
+ this.renderPickingFramebuffer();
478
+ }
479
+ }
480
+
481
+ const rect = canvas.getBoundingClientRect();
482
+ const point = new Point(
483
+ event.clientX - rect.left - canvas.clientLeft,
484
+ event.clientY - rect.top - canvas.clientTop
485
+ );
486
+
487
+ /**
488
+ * @param {MouseEvent} event
489
+ */
490
+ const dispatchEvent = (event) => {
491
+ this.viewRoot.propagateInteractionEvent(
492
+ new InteractionEvent(point, event)
493
+ );
494
+
495
+ if (!this._tooltipUpdateRequested) {
496
+ this.tooltip.clear();
497
+ }
498
+ };
499
+
500
+ if (event.type != "wheel") {
501
+ this._wheelInertia.cancel();
502
+ }
503
+
504
+ if (event.type == "mousemove") {
505
+ this._handlePicking(point.x, point.y);
506
+ } else if (
507
+ event.type == "mousedown" ||
508
+ event.type == "mouseup"
509
+ ) {
510
+ this.renderPickingFramebuffer();
511
+ } else if (event.type == "wheel") {
512
+ this._tooltipUpdateRequested = false;
513
+
514
+ const wheelEvent = /** @type {WheelEvent} */ (event);
515
+
516
+ if (
517
+ Math.abs(wheelEvent.deltaX) >
518
+ Math.abs(wheelEvent.deltaY)
519
+ ) {
520
+ // If the viewport is panned (horizontally) using the wheel (touchpad),
521
+ // the picking buffer becomes stale and needs redrawing. However, we
522
+ // optimize by just clearing the currently hovered item so that snapping
523
+ // doesn't work incorrectly when zooming in/out.
524
+
525
+ // TODO: More robust solution (handle at higher level such as ScaleResolution's zoom method)
526
+ this._currentHover = null;
527
+
528
+ this._wheelInertia.cancel();
529
+ } else {
530
+ // Vertical wheeling zooms.
531
+ // We use inertia to generate fake wheel events for smoother zooming
532
+
533
+ const template = makeEventTemplate(wheelEvent);
534
+
535
+ this._wheelInertia.setMomentum(
536
+ wheelEvent.deltaY * (wheelEvent.deltaMode ? 80 : 1),
537
+ (delta) => {
538
+ const e = new WheelEvent("wheel", {
539
+ ...template,
540
+ deltaMode: 0,
541
+ deltaX: 0,
542
+ deltaY: delta,
543
+ });
544
+ dispatchEvent(e);
545
+ }
546
+ );
547
+
548
+ wheelEvent.preventDefault();
549
+ return;
550
+ }
551
+ }
552
+
553
+ // TODO: Should be handled at the view level, not globally
554
+ if (event.type == "click") {
555
+ const e = this._currentHover
556
+ ? {
557
+ type: event.type,
558
+ viewPath: this._currentHover.mark.unitView
559
+ .getLayoutAncestors()
560
+ .map((view) => view.name)
561
+ .reverse(),
562
+ datum: this._currentHover.datum,
563
+ }
564
+ : {
565
+ type: event.type,
566
+ viewPath: null,
567
+ datum: null,
568
+ };
569
+
570
+ this._eventListeners
571
+ .get("click")
572
+ ?.forEach((listener) => listener(e));
573
+ }
574
+
575
+ dispatchEvent(event);
576
+ }
577
+ };
578
+
579
+ [
580
+ "mousedown",
581
+ "mouseup",
582
+ "wheel",
583
+ "click",
584
+ "mousemove",
585
+ "gesturechange",
586
+ "contextmenu",
587
+ ].forEach((type) => canvas.addEventListener(type, listener));
588
+
589
+ canvas.addEventListener("mousedown", () => {
590
+ document.addEventListener(
591
+ "mouseup",
592
+ () => this.tooltip.popEnabledState(),
593
+ { once: true }
594
+ );
595
+ this.tooltip.pushEnabledState(false);
596
+ });
597
+
598
+ // Prevent text selections etc while dragging
599
+ canvas.addEventListener("dragstart", (event) =>
600
+ event.stopPropagation()
601
+ );
602
+ }
603
+
604
+ /**
605
+ * @param {number} x
606
+ * @param {number} y
607
+ */
608
+ _handlePicking(x, y) {
609
+ const pixelValue = this._glHelper.readPickingPixel(x, y);
610
+
611
+ const uniqueId =
612
+ pixelValue[0] | (pixelValue[1] << 8) | (pixelValue[2] << 16);
613
+
614
+ if (uniqueId == 0) {
615
+ this._currentHover = null;
616
+ return;
617
+ }
618
+
619
+ if (uniqueId !== this._currentHover?.uniqueId) {
620
+ this._currentHover = null;
621
+ }
622
+
623
+ if (!this._currentHover) {
624
+ // We are doing an exhaustive search of the data. This is a bit slow with
625
+ // millions of items.
626
+ // TODO: Optimize by indexing or something
627
+
628
+ this.viewRoot.visit((view) => {
629
+ if (view instanceof UnitView) {
630
+ if (view.mark.isPickingParticipant()) {
631
+ const accessor = view.mark.encoders.uniqueId.accessor;
632
+ view.getCollector().visitData((d) => {
633
+ if (accessor(d) == uniqueId) {
634
+ this._currentHover = {
635
+ mark: view.mark,
636
+ datum: d,
637
+ uniqueId,
638
+ };
639
+ }
640
+ });
641
+ }
642
+ if (this._currentHover) {
643
+ return VISIT_STOP;
644
+ }
645
+ }
646
+ });
647
+ }
648
+
649
+ if (this._currentHover) {
650
+ const mark = this._currentHover.mark;
651
+ this.updateTooltip(this._currentHover.datum, async (datum) => {
652
+ if (!mark.isPickingParticipant()) {
653
+ return;
654
+ }
655
+
656
+ const tooltipProps = mark.properties.tooltip;
657
+
658
+ if (tooltipProps !== null) {
659
+ const handlerName = tooltipProps?.handler ?? "default";
660
+ const handler = this.tooltipHandlers[handlerName];
661
+ if (!handler) {
662
+ throw new Error(
663
+ "No such tooltip handler: " + handlerName
664
+ );
665
+ }
666
+
667
+ return handler(datum, mark, tooltipProps?.params);
668
+ }
669
+ });
670
+ }
671
+ }
672
+
673
+ /**
674
+ * This method should be called in a mouseMove handler. If not called, the
675
+ * tooltip will be hidden.
676
+ *
677
+ * @param {T} datum
678
+ * @param {function(T):Promise<string | HTMLElement | import("lit").TemplateResult>} [converter]
679
+ * @template T
680
+ */
681
+ updateTooltip(datum, converter) {
682
+ if (!this._tooltipUpdateRequested || !datum) {
683
+ this.tooltip.updateWithDatum(datum, converter);
684
+ this._tooltipUpdateRequested = true;
685
+ } else {
686
+ throw new Error(
687
+ "Tooltip has already been updated! Duplicate event handler?"
688
+ );
689
+ }
690
+ }
691
+
692
+ computeLayout() {
693
+ const root = this.viewRoot;
694
+ if (!root) {
695
+ return;
696
+ }
697
+
698
+ this.broadcast("layout");
699
+
700
+ const canvasSize = this._glHelper.getLogicalCanvasSize();
701
+
702
+ if (isNaN(canvasSize.width) || isNaN(canvasSize.height)) {
703
+ // TODO: Figure out what causes this
704
+ console.log(
705
+ `NaN in canvas size: ${canvasSize.width}x${canvasSize.height}. Skipping computeLayout().`
706
+ );
707
+ return;
708
+ }
709
+
710
+ this._renderingContext = new BufferedViewRenderingContext(
711
+ {
712
+ picking: false,
713
+ },
714
+ this._glHelper
715
+ );
716
+ this._pickingContext = new BufferedViewRenderingContext(
717
+ {
718
+ picking: true,
719
+ },
720
+ this._glHelper
721
+ );
722
+
723
+ root.render(
724
+ new CompositeViewRenderingContext(
725
+ this._renderingContext,
726
+ this._pickingContext
727
+ ),
728
+ // Canvas should now be sized based on the root view or the container
729
+ Rectangle.create(0, 0, canvasSize.width, canvasSize.height)
730
+ );
731
+
732
+ this.broadcast("layoutComputed");
733
+ }
734
+
735
+ renderAll() {
736
+ this._renderingContext?.render();
737
+
738
+ this._dirtyPickingBuffer = true;
739
+ }
740
+
741
+ renderPickingFramebuffer() {
742
+ if (!this._dirtyPickingBuffer) {
743
+ return;
744
+ }
745
+
746
+ this._pickingContext.render();
747
+ this._dirtyPickingBuffer = false;
748
+ }
749
+
750
+ getSearchableViews() {
751
+ /** @type {UnitView[]} */
752
+ const views = [];
753
+ this.viewRoot.visit((view) => {
754
+ if (view instanceof UnitView && view.getAccessor("search")) {
755
+ views.push(view);
756
+ }
757
+ });
758
+ return views;
759
+ }
760
+
761
+ getNamedScaleResolutions() {
762
+ /** @type {Map<string, import("./view/scaleResolution").default>} */
763
+ const resolutions = new Map();
764
+ this.viewRoot.visit((view) => {
765
+ for (const resolution of Object.values(view.resolutions.scale)) {
766
+ if (resolution.name) {
767
+ resolutions.set(resolution.name, resolution);
768
+ }
769
+ }
770
+ });
771
+ return resolutions;
772
+ }
773
+ }
774
+
775
+ /**
776
+ *
777
+ * @param {HTMLElement} container
778
+ * @param {string} message
779
+ */
780
+ function createMessageBox(container, message) {
781
+ // Uh, need a templating thingy
782
+ const messageBox = document.createElement("div");
783
+ messageBox.className = "message-box";
784
+ const messageText = document.createElement("div");
785
+ messageText.textContent = message;
786
+ messageBox.appendChild(messageText);
787
+ container.appendChild(messageBox);
788
+ }