@genome-spy/core 0.72.0 → 0.74.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 (396) hide show
  1. package/LICENSE +1 -1
  2. package/dist/bundle/AbortablePromiseCache-3gHJdF3E.js +96 -0
  3. package/dist/bundle/browser-BTgw5ieH.js +126 -0
  4. package/dist/bundle/chunk-DmhlhrBa.js +11 -0
  5. package/dist/bundle/esm-BDFRLEuD.js +1248 -0
  6. package/dist/bundle/esm-BygJiwh0.js +573 -0
  7. package/dist/bundle/esm-CGX-qz1d.js +155 -0
  8. package/dist/bundle/esm-CgfVIRJ-.js +121 -0
  9. package/dist/bundle/esm-CuMSzCHy.js +298 -0
  10. package/dist/bundle/esm-DMXpJXM4.js +369 -0
  11. package/dist/bundle/esm-DQiq2Zhd.js +1426 -0
  12. package/dist/bundle/esm-DtE8VqAv.js +1015 -0
  13. package/dist/bundle/esm-sIoQYZ21.js +461 -0
  14. package/dist/bundle/index.es.js +21078 -24556
  15. package/dist/bundle/index.js +379 -383
  16. package/dist/bundle/parquetRead-DG_-F5j5.js +1609 -0
  17. package/dist/schema.json +13349 -7082
  18. package/dist/src/config/axisConfig.d.ts +16 -0
  19. package/dist/src/config/axisConfig.d.ts.map +1 -0
  20. package/dist/src/config/axisConfig.js +84 -0
  21. package/dist/src/config/defaultConfig.d.ts +3 -0
  22. package/dist/src/config/defaultConfig.d.ts.map +1 -0
  23. package/dist/src/config/defaultConfig.js +38 -0
  24. package/dist/src/config/defaults/axisDefaults.d.ts +5 -0
  25. package/dist/src/config/defaults/axisDefaults.d.ts.map +1 -0
  26. package/dist/src/config/defaults/axisDefaults.js +72 -0
  27. package/dist/src/config/defaults/markDefaults.d.ts +15 -0
  28. package/dist/src/config/defaults/markDefaults.d.ts.map +1 -0
  29. package/dist/src/config/defaults/markDefaults.js +121 -0
  30. package/dist/src/config/defaults/scaleDefaults.d.ts +5 -0
  31. package/dist/src/config/defaults/scaleDefaults.d.ts.map +1 -0
  32. package/dist/src/config/defaults/scaleDefaults.js +18 -0
  33. package/dist/src/config/defaults/titleDefaults.d.ts +5 -0
  34. package/dist/src/config/defaults/titleDefaults.d.ts.map +1 -0
  35. package/dist/src/config/defaults/titleDefaults.js +47 -0
  36. package/dist/src/config/defaults/viewDefaults.d.ts +3 -0
  37. package/dist/src/config/defaults/viewDefaults.d.ts.map +1 -0
  38. package/dist/src/config/defaults/viewDefaults.js +2 -0
  39. package/dist/src/config/markConfig.d.ts +8 -0
  40. package/dist/src/config/markConfig.d.ts.map +1 -0
  41. package/dist/src/config/markConfig.js +27 -0
  42. package/dist/src/config/mergeConfig.d.ts +8 -0
  43. package/dist/src/config/mergeConfig.d.ts.map +1 -0
  44. package/dist/src/config/mergeConfig.js +81 -0
  45. package/dist/src/config/resolveConfig.d.ts +22 -0
  46. package/dist/src/config/resolveConfig.d.ts.map +1 -0
  47. package/dist/src/config/resolveConfig.js +32 -0
  48. package/dist/src/config/scaleConfig.d.ts +40 -0
  49. package/dist/src/config/scaleConfig.d.ts.map +1 -0
  50. package/dist/src/config/scaleConfig.js +220 -0
  51. package/dist/src/config/styleUtils.d.ts +6 -0
  52. package/dist/src/config/styleUtils.d.ts.map +1 -0
  53. package/dist/src/config/styleUtils.js +10 -0
  54. package/dist/src/config/themes.d.ts +15 -0
  55. package/dist/src/config/themes.d.ts.map +1 -0
  56. package/dist/src/config/themes.js +293 -0
  57. package/dist/src/config/titleConfig.d.ts +12 -0
  58. package/dist/src/config/titleConfig.d.ts.map +1 -0
  59. package/dist/src/config/titleConfig.js +42 -0
  60. package/dist/src/config/viewConfig.d.ts +7 -0
  61. package/dist/src/config/viewConfig.d.ts.map +1 -0
  62. package/dist/src/config/viewConfig.js +29 -0
  63. package/dist/src/data/flowNode.d.ts +22 -1
  64. package/dist/src/data/flowNode.d.ts.map +1 -1
  65. package/dist/src/data/flowNode.js +37 -1
  66. package/dist/src/data/formats/bed.d.ts +8 -0
  67. package/dist/src/data/formats/bed.d.ts.map +1 -0
  68. package/dist/src/data/formats/bed.js +58 -0
  69. package/dist/src/data/formats/bedpe.d.ts +8 -0
  70. package/dist/src/data/formats/bedpe.d.ts.map +1 -0
  71. package/dist/src/data/formats/bedpe.js +164 -0
  72. package/dist/src/data/formats/fasta.d.ts.map +1 -1
  73. package/dist/src/data/formats/fasta.js +4 -0
  74. package/dist/src/data/formats/parquet.d.ts.map +1 -1
  75. package/dist/src/data/formats/parquet.js +4 -0
  76. package/dist/src/data/sources/dataSourceFactory.d.ts +2 -13
  77. package/dist/src/data/sources/dataSourceFactory.d.ts.map +1 -1
  78. package/dist/src/data/sources/dataSourceFactory.js +5 -141
  79. package/dist/src/data/sources/dataUtils.d.ts +16 -0
  80. package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
  81. package/dist/src/data/sources/dataUtils.js +53 -3
  82. package/dist/src/data/sources/lazy/axisGenomeSource.d.ts.map +1 -1
  83. package/dist/src/data/sources/lazy/axisGenomeSource.js +11 -0
  84. package/dist/src/data/sources/lazy/axisTickSource.d.ts +1 -1
  85. package/dist/src/data/sources/lazy/axisTickSource.d.ts.map +1 -1
  86. package/dist/src/data/sources/lazy/axisTickSource.js +19 -8
  87. package/dist/src/data/sources/lazy/bamSource.d.ts.map +1 -1
  88. package/dist/src/data/sources/lazy/bamSource.js +11 -0
  89. package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
  90. package/dist/src/data/sources/lazy/bigBedSource.js +12 -1
  91. package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
  92. package/dist/src/data/sources/lazy/bigWigSource.js +11 -0
  93. package/dist/src/data/sources/lazy/gff3Source.d.ts.map +1 -1
  94. package/dist/src/data/sources/lazy/gff3Source.js +12 -1
  95. package/dist/src/data/sources/lazy/indexedFastaSource.d.ts.map +1 -1
  96. package/dist/src/data/sources/lazy/indexedFastaSource.js +11 -0
  97. package/dist/src/data/sources/lazy/lazyDataSourceRegistry.d.ts +27 -0
  98. package/dist/src/data/sources/lazy/lazyDataSourceRegistry.d.ts.map +1 -0
  99. package/dist/src/data/sources/lazy/lazyDataSourceRegistry.js +65 -0
  100. package/dist/src/data/sources/lazy/registerBuiltInLazySources.d.ts +2 -0
  101. package/dist/src/data/sources/lazy/registerBuiltInLazySources.d.ts.map +1 -0
  102. package/dist/src/data/sources/lazy/registerBuiltInLazySources.js +8 -0
  103. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  104. package/dist/src/data/sources/lazy/singleAxisLazySource.js +11 -2
  105. package/dist/src/data/sources/lazy/vcfSource.d.ts.map +1 -1
  106. package/dist/src/data/sources/lazy/vcfSource.js +11 -0
  107. package/dist/src/data/sources/urlSource.d.ts +4 -0
  108. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  109. package/dist/src/data/sources/urlSource.js +138 -16
  110. package/dist/src/data/transforms/aggregate.d.ts +1 -0
  111. package/dist/src/data/transforms/aggregate.d.ts.map +1 -1
  112. package/dist/src/data/transforms/aggregate.js +30 -8
  113. package/dist/src/data/transforms/aggregateOps.d.ts.map +1 -1
  114. package/dist/src/data/transforms/aggregateOps.js +12 -1
  115. package/dist/src/data/transforms/coverage.js +2 -2
  116. package/dist/src/data/transforms/filter.js +1 -1
  117. package/dist/src/data/transforms/filterScoredLabels.d.ts +6 -0
  118. package/dist/src/data/transforms/filterScoredLabels.d.ts.map +1 -1
  119. package/dist/src/data/transforms/filterScoredLabels.js +9 -0
  120. package/dist/src/data/transforms/measureText.d.ts +1 -0
  121. package/dist/src/data/transforms/measureText.d.ts.map +1 -1
  122. package/dist/src/data/transforms/measureText.js +14 -5
  123. package/dist/src/data/transforms/pileup.d.ts.map +1 -1
  124. package/dist/src/data/transforms/pileup.js +1 -2
  125. package/dist/src/data/transforms/regexFold.d.ts.map +1 -1
  126. package/dist/src/data/transforms/regexFold.js +0 -1
  127. package/dist/src/embedFactory.d.ts +13 -0
  128. package/dist/src/embedFactory.d.ts.map +1 -0
  129. package/dist/src/embedFactory.js +127 -0
  130. package/dist/src/encoder/accessor.d.ts +3 -12
  131. package/dist/src/encoder/accessor.d.ts.map +1 -1
  132. package/dist/src/encoder/accessor.js +10 -65
  133. package/dist/src/encoder/encoder.d.ts +51 -8
  134. package/dist/src/encoder/encoder.d.ts.map +1 -1
  135. package/dist/src/encoder/encoder.js +179 -55
  136. package/dist/src/fonts/bmFontManager.js +1 -1
  137. package/dist/src/full.d.ts +2 -0
  138. package/dist/src/full.d.ts.map +1 -0
  139. package/dist/src/full.js +2 -0
  140. package/dist/src/genome/assemblyPreflight.d.ts +31 -0
  141. package/dist/src/genome/assemblyPreflight.d.ts.map +1 -0
  142. package/dist/src/genome/assemblyPreflight.js +99 -0
  143. package/dist/src/genome/genome.d.ts +10 -2
  144. package/dist/src/genome/genome.d.ts.map +1 -1
  145. package/dist/src/genome/genome.js +20 -2
  146. package/dist/src/genome/genomeStore.d.ts +34 -3
  147. package/dist/src/genome/genomeStore.d.ts.map +1 -1
  148. package/dist/src/genome/genomeStore.js +409 -18
  149. package/dist/src/genome/rootGenomeConfig.d.ts +26 -0
  150. package/dist/src/genome/rootGenomeConfig.d.ts.map +1 -0
  151. package/dist/src/genome/rootGenomeConfig.js +98 -0
  152. package/dist/src/genome/scaleLocus.d.ts.map +1 -1
  153. package/dist/src/genome/scaleLocus.js +26 -7
  154. package/dist/src/genomeSpy/cursorManager.d.ts +69 -0
  155. package/dist/src/genomeSpy/cursorManager.d.ts.map +1 -0
  156. package/dist/src/genomeSpy/cursorManager.js +131 -0
  157. package/dist/src/genomeSpy/headlessBootstrap.d.ts +113 -0
  158. package/dist/src/genomeSpy/headlessBootstrap.d.ts.map +1 -0
  159. package/dist/src/genomeSpy/headlessBootstrap.js +246 -0
  160. package/dist/src/genomeSpy/interactionController.d.ts +10 -1
  161. package/dist/src/genomeSpy/interactionController.d.ts.map +1 -1
  162. package/dist/src/genomeSpy/interactionController.js +448 -40
  163. package/dist/src/genomeSpy/interactionDispatcher.d.ts +50 -0
  164. package/dist/src/genomeSpy/interactionDispatcher.d.ts.map +1 -0
  165. package/dist/src/genomeSpy/interactionDispatcher.js +203 -0
  166. package/dist/src/genomeSpy/renderCoordinator.js +1 -1
  167. package/dist/src/genomeSpy/viewContextFactory.d.ts +4 -2
  168. package/dist/src/genomeSpy/viewContextFactory.d.ts.map +1 -1
  169. package/dist/src/genomeSpy/viewContextFactory.js +12 -4
  170. package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -1
  171. package/dist/src/genomeSpy/viewDataInit.js +7 -3
  172. package/dist/src/genomeSpy.d.ts +1 -114
  173. package/dist/src/genomeSpy.d.ts.map +1 -1
  174. package/dist/src/genomeSpy.js +7 -614
  175. package/dist/src/genomeSpyBase.d.ts +133 -0
  176. package/dist/src/genomeSpyBase.d.ts.map +1 -0
  177. package/dist/src/genomeSpyBase.js +719 -0
  178. package/dist/src/gl/arrayBuilder.d.ts.map +1 -1
  179. package/dist/src/gl/arrayBuilder.js +0 -3
  180. package/dist/src/gl/canvasSizeHelper.d.ts +74 -0
  181. package/dist/src/gl/canvasSizeHelper.d.ts.map +1 -0
  182. package/dist/src/gl/canvasSizeHelper.js +203 -0
  183. package/dist/src/gl/colorUtils.d.ts.map +1 -1
  184. package/dist/src/gl/colorUtils.js +3 -0
  185. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  186. package/dist/src/gl/dataToVertices.js +13 -8
  187. package/dist/src/gl/glslScaleGenerator.d.ts +2 -2
  188. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
  189. package/dist/src/gl/glslScaleGenerator.js +5 -7
  190. package/dist/src/gl/webGLHelper.d.ts +25 -11
  191. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  192. package/dist/src/gl/webGLHelper.js +59 -33
  193. package/dist/src/index.d.ts +3 -9
  194. package/dist/src/index.d.ts.map +1 -1
  195. package/dist/src/index.js +5 -111
  196. package/dist/src/marks/__snapshots__/shaderSnapshot.test.js.snap +4462 -0
  197. package/dist/src/marks/link.d.ts.map +1 -1
  198. package/dist/src/marks/link.js +5 -26
  199. package/dist/src/marks/mark.d.ts +8 -1
  200. package/dist/src/marks/mark.d.ts.map +1 -1
  201. package/dist/src/marks/mark.js +67 -21
  202. package/dist/src/marks/markUtils.d.ts +18 -1
  203. package/dist/src/marks/markUtils.d.ts.map +1 -1
  204. package/dist/src/marks/markUtils.js +52 -4
  205. package/dist/src/marks/point.d.ts.map +1 -1
  206. package/dist/src/marks/point.js +6 -26
  207. package/dist/src/marks/rect.d.ts.map +1 -1
  208. package/dist/src/marks/rect.js +13 -21
  209. package/dist/src/marks/rule.d.ts +7 -2
  210. package/dist/src/marks/rule.d.ts.map +1 -1
  211. package/dist/src/marks/rule.js +125 -16
  212. package/dist/src/marks/text.d.ts.map +1 -1
  213. package/dist/src/marks/text.js +5 -47
  214. package/dist/src/minimal.d.ts +8 -0
  215. package/dist/src/minimal.d.ts.map +1 -0
  216. package/dist/src/minimal.js +21 -0
  217. package/dist/src/paramRuntime/viewParamRuntime.d.ts +19 -0
  218. package/dist/src/paramRuntime/viewParamRuntime.d.ts.map +1 -1
  219. package/dist/src/paramRuntime/viewParamRuntime.js +35 -0
  220. package/dist/src/scale/scale.d.ts.map +1 -1
  221. package/dist/src/scale/scale.js +13 -7
  222. package/dist/src/scales/axisResolution.d.ts.map +1 -1
  223. package/dist/src/scales/axisResolution.js +9 -5
  224. package/dist/src/scales/domainPlanner.d.ts +58 -7
  225. package/dist/src/scales/domainPlanner.d.ts.map +1 -1
  226. package/dist/src/scales/domainPlanner.js +395 -40
  227. package/dist/src/scales/indexLikeDomainUtils.d.ts +29 -0
  228. package/dist/src/scales/indexLikeDomainUtils.d.ts.map +1 -0
  229. package/dist/src/scales/indexLikeDomainUtils.js +67 -0
  230. package/dist/src/scales/resolutionMemberOrder.d.ts +15 -0
  231. package/dist/src/scales/resolutionMemberOrder.d.ts.map +1 -0
  232. package/dist/src/scales/resolutionMemberOrder.js +22 -0
  233. package/dist/src/scales/scaleInstanceManager.d.ts +2 -1
  234. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
  235. package/dist/src/scales/scaleInstanceManager.js +10 -11
  236. package/dist/src/scales/scaleInteractionController.d.ts.map +1 -1
  237. package/dist/src/scales/scaleInteractionController.js +59 -18
  238. package/dist/src/scales/scalePropsResolver.d.ts +3 -1
  239. package/dist/src/scales/scalePropsResolver.d.ts.map +1 -1
  240. package/dist/src/scales/scalePropsResolver.js +83 -6
  241. package/dist/src/scales/scaleResolution.d.ts +39 -0
  242. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  243. package/dist/src/scales/scaleResolution.js +504 -82
  244. package/dist/src/scales/scaleResolutionTestUtils.d.ts +21 -0
  245. package/dist/src/scales/scaleResolutionTestUtils.d.ts.map +1 -0
  246. package/dist/src/scales/scaleResolutionTestUtils.js +37 -0
  247. package/dist/src/scales/scaleRules.d.ts.map +1 -1
  248. package/dist/src/scales/scaleRules.js +16 -2
  249. package/dist/src/scales/selectionDomainUtils.d.ts +52 -0
  250. package/dist/src/scales/selectionDomainUtils.d.ts.map +1 -0
  251. package/dist/src/scales/selectionDomainUtils.js +194 -0
  252. package/dist/src/scales/zoomDomainUtils.d.ts +18 -0
  253. package/dist/src/scales/zoomDomainUtils.d.ts.map +1 -0
  254. package/dist/src/scales/zoomDomainUtils.js +69 -0
  255. package/dist/src/screenshotHarness.d.ts +16 -0
  256. package/dist/src/screenshotHarness.d.ts.map +1 -0
  257. package/dist/src/screenshotHarness.js +241 -0
  258. package/dist/src/singlePageApp.js +1 -1
  259. package/dist/src/spec/axis.d.ts +41 -30
  260. package/dist/src/spec/channel.d.ts +15 -9
  261. package/dist/src/spec/config.d.ts +264 -0
  262. package/dist/src/spec/data.d.ts +30 -3
  263. package/dist/src/spec/decoration.d.ts +51 -0
  264. package/dist/src/spec/exampleFiles.d.ts +12 -0
  265. package/dist/src/spec/exampleFiles.d.ts.map +1 -0
  266. package/dist/src/spec/exampleFiles.js +52 -0
  267. package/dist/src/spec/font.d.ts +1 -1
  268. package/dist/src/spec/genome.d.ts +22 -2
  269. package/dist/src/spec/mark.d.ts +97 -13
  270. package/dist/src/spec/parameter.d.ts +62 -5
  271. package/dist/src/spec/root.d.ts +34 -1
  272. package/dist/src/spec/scale.d.ts +46 -5
  273. package/dist/src/spec/title.d.ts +13 -2
  274. package/dist/src/spec/tooltip.d.ts +1 -1
  275. package/dist/src/spec/transform.d.ts +39 -4
  276. package/dist/src/spec/view.d.ts +67 -19
  277. package/dist/src/styles/genome-spy.css +63 -55
  278. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  279. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  280. package/dist/src/styles/genome-spy.css.js +31 -22
  281. package/dist/src/testSetup.d.ts +2 -0
  282. package/dist/src/testSetup.d.ts.map +1 -0
  283. package/dist/src/testSetup.js +5 -0
  284. package/dist/src/tooltip/dataTooltipHandler.js +66 -11
  285. package/dist/src/tooltip/tooltipContext.d.ts.map +1 -1
  286. package/dist/src/tooltip/tooltipContext.js +3 -2
  287. package/dist/src/types/embedApi.d.ts +26 -0
  288. package/dist/src/types/encoder.d.ts +17 -15
  289. package/dist/src/types/scaleResolutionApi.d.ts +20 -0
  290. package/dist/src/types/viewContext.d.ts +23 -1
  291. package/dist/src/utils/expression.d.ts +2 -2
  292. package/dist/src/utils/expression.d.ts.map +1 -1
  293. package/dist/src/utils/expression.js +63 -8
  294. package/dist/src/utils/field.d.ts.map +1 -1
  295. package/dist/src/utils/field.js +0 -1
  296. package/dist/src/utils/inertia.d.ts.map +1 -1
  297. package/dist/src/utils/inertia.js +0 -1
  298. package/dist/src/utils/inferSpecBaseUrl.d.ts +14 -0
  299. package/dist/src/utils/inferSpecBaseUrl.d.ts.map +1 -0
  300. package/dist/src/utils/inferSpecBaseUrl.js +73 -0
  301. package/dist/src/utils/inputBinding.d.ts +1 -1
  302. package/dist/src/utils/interaction.d.ts +109 -0
  303. package/dist/src/utils/interaction.d.ts.map +1 -0
  304. package/dist/src/utils/interaction.js +200 -0
  305. package/dist/src/utils/interactionEvent.d.ts +62 -33
  306. package/dist/src/utils/interactionEvent.d.ts.map +1 -1
  307. package/dist/src/utils/interactionEvent.js +86 -48
  308. package/dist/src/utils/kWayMerge.js +1 -1
  309. package/dist/src/utils/mergeObjects.d.ts.map +1 -1
  310. package/dist/src/utils/mergeObjects.js +0 -2
  311. package/dist/src/utils/radixSort.d.ts.map +1 -1
  312. package/dist/src/utils/radixSort.js +0 -2
  313. package/dist/src/utils/throttle.d.ts.map +1 -1
  314. package/dist/src/utils/throttle.js +0 -2
  315. package/dist/src/utils/ui/tooltip.d.ts +1 -0
  316. package/dist/src/utils/ui/tooltip.d.ts.map +1 -1
  317. package/dist/src/utils/ui/tooltip.js +1 -0
  318. package/dist/src/utils/url.js +1 -1
  319. package/dist/src/view/axisGridView.d.ts +1 -1
  320. package/dist/src/view/axisGridView.d.ts.map +1 -1
  321. package/dist/src/view/axisGridView.js +2 -47
  322. package/dist/src/view/axisView.d.ts +2 -3
  323. package/dist/src/view/axisView.d.ts.map +1 -1
  324. package/dist/src/view/axisView.js +251 -106
  325. package/dist/src/view/concatView.d.ts +2 -1
  326. package/dist/src/view/concatView.d.ts.map +1 -1
  327. package/dist/src/view/concatView.js +4 -2
  328. package/dist/src/view/containerMutationHelper.d.ts +3 -0
  329. package/dist/src/view/containerMutationHelper.d.ts.map +1 -1
  330. package/dist/src/view/containerMutationHelper.js +12 -1
  331. package/dist/src/view/dataReadiness.d.ts +2 -2
  332. package/dist/src/view/dataReadiness.d.ts.map +1 -1
  333. package/dist/src/view/dataReadiness.js +63 -58
  334. package/dist/src/view/facetView.d.ts +1 -1
  335. package/dist/src/view/facetView.js +4 -4
  336. package/dist/src/view/flowBuilder.js +2 -2
  337. package/dist/src/view/gridView/gridChild.d.ts +13 -0
  338. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  339. package/dist/src/view/gridView/gridChild.js +247 -49
  340. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  341. package/dist/src/view/gridView/gridView.js +296 -99
  342. package/dist/src/view/gridView/keyboardZoomController.d.ts +2 -2
  343. package/dist/src/view/gridView/keyboardZoomController.d.ts.map +1 -1
  344. package/dist/src/view/gridView/keyboardZoomController.js +1 -1
  345. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  346. package/dist/src/view/gridView/scrollbar.js +4 -2
  347. package/dist/src/view/gridView/selectionRect.d.ts +4 -0
  348. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  349. package/dist/src/view/gridView/selectionRect.js +20 -1
  350. package/dist/src/view/gridView/separatorView.d.ts +1 -0
  351. package/dist/src/view/gridView/separatorView.d.ts.map +1 -1
  352. package/dist/src/view/gridView/separatorView.js +9 -0
  353. package/dist/src/view/interactionRouting.d.ts +20 -0
  354. package/dist/src/view/interactionRouting.d.ts.map +1 -0
  355. package/dist/src/view/interactionRouting.js +53 -0
  356. package/dist/src/view/layerView.d.ts.map +1 -1
  357. package/dist/src/view/layerView.js +12 -9
  358. package/dist/src/view/layout/grid.js +1 -1
  359. package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts.map +1 -1
  360. package/dist/src/view/renderingContext/bufferedViewRenderingContext.js +0 -2
  361. package/dist/src/view/testUtils.d.ts +17 -3
  362. package/dist/src/view/testUtils.d.ts.map +1 -1
  363. package/dist/src/view/testUtils.js +62 -69
  364. package/dist/src/view/title.d.ts +8 -1
  365. package/dist/src/view/title.d.ts.map +1 -1
  366. package/dist/src/view/title.js +66 -76
  367. package/dist/src/view/unitView.d.ts +1 -1
  368. package/dist/src/view/unitView.d.ts.map +1 -1
  369. package/dist/src/view/unitView.js +67 -17
  370. package/dist/src/view/view.d.ts +76 -30
  371. package/dist/src/view/view.d.ts.map +1 -1
  372. package/dist/src/view/view.js +136 -47
  373. package/dist/src/view/viewFactory.d.ts +11 -3
  374. package/dist/src/view/viewFactory.d.ts.map +1 -1
  375. package/dist/src/view/viewFactory.js +37 -11
  376. package/dist/src/view/viewUtils.d.ts.map +1 -1
  377. package/dist/src/view/viewUtils.js +41 -5
  378. package/dist/src/view/zoom.d.ts +15 -3
  379. package/dist/src/view/zoom.d.ts.map +1 -1
  380. package/dist/src/view/zoom.js +375 -80
  381. package/package.json +20 -10
  382. package/dist/bundle/AbortablePromiseCache-Dj0vzLnp.js +0 -149
  383. package/dist/bundle/browser-0iNU5Wit.js +0 -138
  384. package/dist/bundle/index-BYsZN7b0.js +0 -1597
  385. package/dist/bundle/index-C3kClAEN.js +0 -1771
  386. package/dist/bundle/index-C7wOh6y1.js +0 -657
  387. package/dist/bundle/index-CRaQAuki.js +0 -326
  388. package/dist/bundle/index-D9v1PCj9.js +0 -507
  389. package/dist/bundle/index-GDOuv_D5.js +0 -266
  390. package/dist/bundle/index-Gt44EOIH.js +0 -628
  391. package/dist/bundle/inflate-GtwLkvSP.js +0 -1048
  392. package/dist/bundle/parquetRead-BnAGCa4_.js +0 -1663
  393. package/dist/bundle/unzip-Bac01w6X.js +0 -1492
  394. package/dist/src/config/scaleDefaults.d.ts +0 -8
  395. package/dist/src/config/scaleDefaults.d.ts.map +0 -1
  396. package/dist/src/config/scaleDefaults.js +0 -45
@@ -0,0 +1,719 @@
1
+ import {
2
+ createContainerUi,
3
+ createMessageBox,
4
+ } from "./genomeSpy/containerUi.js";
5
+ import LoadingIndicatorManager from "./genomeSpy/loadingIndicatorManager.js";
6
+ import LoadingStatusRegistry from "./genomeSpy/loadingStatusRegistry.js";
7
+ import { createViewHighlighter } from "./genomeSpy/viewHighlight.js";
8
+ import KeyboardListenerManager from "./genomeSpy/keyboardListenerManager.js";
9
+ import EventListenerRegistry from "./genomeSpy/eventListenerRegistry.js";
10
+ import InputBindingManager from "./genomeSpy/inputBindingManager.js";
11
+
12
+ import { calculateCanvasSize } from "./view/viewUtils.js";
13
+ import {
14
+ initializeViewData,
15
+ initializeVisibleViewData,
16
+ } from "./genomeSpy/viewDataInit.js";
17
+ import UnitView from "./view/unitView.js";
18
+
19
+ import WebGLHelper from "./gl/webGLHelper.js";
20
+ import Animator from "./utils/animator.js";
21
+ import DataFlow from "./data/dataFlow.js";
22
+ import GenomeStore from "./genome/genomeStore.js";
23
+ import BmFontManager from "./fonts/bmFontManager.js";
24
+ import refseqGeneTooltipHandler from "./tooltip/refseqGeneTooltipHandler.js";
25
+ import dataTooltipHandler from "./tooltip/dataTooltipHandler.js";
26
+ import { invalidatePrefix } from "./utils/propertyCacher.js";
27
+ import { VIEW_ROOT_NAME, ViewFactory } from "./view/viewFactory.js";
28
+ import InteractionController from "./genomeSpy/interactionController.js";
29
+ import RenderCoordinator from "./genomeSpy/renderCoordinator.js";
30
+ import { createViewContext } from "./genomeSpy/viewContextFactory.js";
31
+ import { prepareViewHierarchy } from "./genomeSpy/headlessBootstrap.js";
32
+ import { exportCanvas } from "./genomeSpy/canvasExport.js";
33
+ import { validateSelectorConstraints } from "./view/viewSelectors.js";
34
+ import SingleAxisWindowedSource from "./data/sources/lazy/singleAxisWindowedSource.js";
35
+ import { ensureAssembliesForView } from "./genome/assemblyPreflight.js";
36
+ import { resolveRootGenomeConfig } from "./genome/rootGenomeConfig.js";
37
+ import { awaitSubtreeLazyReady } from "./view/dataReadiness.js";
38
+ import { INTERNAL_DEFAULT_CONFIG } from "./config/defaultConfig.js";
39
+ import { mergeConfigScopes } from "./config/mergeConfig.js";
40
+ import { resolveBaseConfig } from "./config/resolveConfig.js";
41
+ import {
42
+ DEFAULT_THEME_NAME,
43
+ getBuiltInThemeBackground,
44
+ resolveThemeSelection,
45
+ } from "./config/themes.js";
46
+
47
+ /**
48
+ * Events that are broadcasted to all views.
49
+ * @typedef {"dataFlowBuilt" | "layout" | "layoutComputed" | "subtreeDataReady"} BroadcastEventType
50
+ */
51
+
52
+ export default class GenomeSpy {
53
+ /** @type {(() => void)[]} */
54
+ #destructionCallbacks = [];
55
+ /** @type {RenderCoordinator} */
56
+ #renderCoordinator;
57
+ /** @type {LoadingIndicatorManager} */
58
+ #loadingIndicatorManager;
59
+ /** @type {LoadingStatusRegistry} */
60
+ #loadingStatusRegistry;
61
+ /** @type {InputBindingManager} */
62
+ #inputBindingManager;
63
+ /** @type {InteractionController} */
64
+ #interactionController;
65
+ /** @type {WebGLHelper} */
66
+ #glHelper;
67
+
68
+ #keyboardListenerManager = new KeyboardListenerManager();
69
+ #eventListeners = new EventListenerRegistry();
70
+ #extraBroadcastListeners = new EventListenerRegistry();
71
+
72
+ /**
73
+ * @typedef {import("./view/view.js").default} View
74
+ * @typedef {import("./spec/view.js").ViewSpec} ViewSpec
75
+ * @typedef {import("./spec/root.js").RootSpec} RootSpec
76
+ * @typedef {import("./spec/root.js").RootConfig} RootConfig
77
+ */
78
+
79
+ /**
80
+ *
81
+ * @param {HTMLElement} container
82
+ * @param {RootSpec} spec
83
+ * @param {import("./types/embedApi.js").EmbedOptions} [options]
84
+ */
85
+ constructor(container, spec, options = {}) {
86
+ this.container = container;
87
+ this.options = options;
88
+
89
+ options.inputBindingContainer ??= "default";
90
+
91
+ /** Root level configuration object */
92
+ this.spec = spec;
93
+
94
+ this.viewFactory = new ViewFactory();
95
+
96
+ /** @type {(function(string):object[])[]} */
97
+ this.namedDataProviders = [];
98
+
99
+ this.animator = new Animator(() => this.renderAll());
100
+
101
+ /** @type {GenomeStore} */
102
+ this.genomeStore = undefined;
103
+
104
+ /**
105
+ * View visibility is checked using a predicate that can be overridden
106
+ * for more dynamic visibility management.
107
+ *
108
+ * @type {(view: View) => boolean}
109
+ */
110
+ this.viewVisibilityPredicate = (view) => view.isVisibleInSpec();
111
+
112
+ /** @type {Record<string, import("./tooltip/tooltipHandler.js").TooltipHandler>}> */
113
+ this.tooltipHandlers = {
114
+ default: dataTooltipHandler,
115
+ refseqgene: refseqGeneTooltipHandler,
116
+ ...(options.tooltipHandlers ?? {}),
117
+ };
118
+
119
+ /** @type {View} */
120
+ this.viewRoot = undefined;
121
+
122
+ this.#inputBindingManager = new InputBindingManager(container, options);
123
+
124
+ this.dpr = window.devicePixelRatio;
125
+ }
126
+
127
+ get #canvasWrapper() {
128
+ return /** @type {HTMLElement} */ (
129
+ this.container.querySelector(".canvas-wrapper")
130
+ );
131
+ }
132
+
133
+ #initializeParameterBindings() {
134
+ this.#inputBindingManager.initialize(this.viewRoot);
135
+ }
136
+
137
+ /**
138
+ *
139
+ * @param {(name: string) => any[]} provider
140
+ */
141
+ registerNamedDataProvider(provider) {
142
+ this.namedDataProviders.unshift(provider);
143
+ }
144
+
145
+ /**
146
+ * @param {string} name
147
+ */
148
+ getNamedDataFromProvider(name) {
149
+ for (const provider of this.namedDataProviders) {
150
+ const data = provider(name);
151
+ if (data) {
152
+ return data;
153
+ }
154
+ }
155
+ }
156
+
157
+ /**
158
+ *
159
+ * @param {string} name
160
+ * @param {any[]} data
161
+ */
162
+ updateNamedData(name, data) {
163
+ const namedSource =
164
+ this.viewRoot.context.dataFlow.findNamedDataSource(name);
165
+ if (!namedSource) {
166
+ throw new Error("No such named data source: " + name);
167
+ }
168
+
169
+ namedSource.dataSource.updateDynamicData(data);
170
+
171
+ this.animator.requestRender();
172
+ }
173
+
174
+ /**
175
+ * @param {string} type
176
+ * @param {(event: any) => void} listener
177
+ */
178
+ addEventListener(type, listener) {
179
+ this.#eventListeners.add(type, listener);
180
+ }
181
+
182
+ /**
183
+ * @param {string} type
184
+ * @param {(event: any) => void} listener
185
+ */
186
+ removeEventListener(type, listener) {
187
+ this.#eventListeners.remove(type, listener);
188
+ }
189
+
190
+ /**
191
+ * Broadcast a message to all views
192
+
193
+ * @param {BroadcastEventType} type
194
+ * @param {any} [payload]
195
+ */
196
+ broadcast(type, payload) {
197
+ const message = { type, payload };
198
+ this.viewRoot.visit((view) => view.handleBroadcast(message));
199
+ this.#extraBroadcastListeners.emit(type, message);
200
+ }
201
+
202
+ #setupDpr() {
203
+ this.dpr = this.#glHelper.getDevicePixelRatio();
204
+
205
+ const dprSetter = this.viewRoot.paramRuntime.allocateSetter(
206
+ "devicePixelRatio",
207
+ this.dpr
208
+ );
209
+
210
+ const resizeCallback = () => {
211
+ this.#glHelper.invalidateSize();
212
+ this.dpr = this.#glHelper.getDevicePixelRatio();
213
+ dprSetter(this.dpr);
214
+ this.computeLayout();
215
+ // Render immediately, without RAF
216
+ this.renderAll();
217
+ };
218
+
219
+ if (this.viewRoot.getSize().isGrowing()) {
220
+ // TODO: Size should be observed only if the content is not absolutely sized
221
+ const resizeObserver = new ResizeObserver(resizeCallback);
222
+ resizeObserver.observe(this.container);
223
+ this.#destructionCallbacks.push(() => resizeObserver.disconnect());
224
+ }
225
+
226
+ /** @type {() => void} */
227
+ let remove = null;
228
+
229
+ const updatePixelRatio = () => {
230
+ if (remove != null) {
231
+ remove();
232
+ resizeCallback();
233
+ }
234
+ const media = matchMedia(
235
+ `(resolution: ${window.devicePixelRatio}dppx)`
236
+ );
237
+ media.addEventListener("change", updatePixelRatio);
238
+ remove = () => {
239
+ media.removeEventListener("change", updatePixelRatio);
240
+ };
241
+ };
242
+ updatePixelRatio();
243
+
244
+ if (remove) {
245
+ this.#destructionCallbacks.push(remove);
246
+ }
247
+ }
248
+
249
+ #prepareContainer() {
250
+ const { canvasWrapper, loadingIndicatorsElement, tooltip } =
251
+ createContainerUi(this.container);
252
+
253
+ this.#glHelper = new WebGLHelper(
254
+ canvasWrapper,
255
+ () =>
256
+ this.viewRoot
257
+ ? calculateCanvasSize(this.viewRoot)
258
+ : { width: undefined, height: undefined },
259
+ { powerPreference: this.options.powerPreference ?? "default" }
260
+ );
261
+
262
+ canvasWrapper.appendChild(loadingIndicatorsElement);
263
+
264
+ this.tooltip = tooltip;
265
+ this.#loadingStatusRegistry = new LoadingStatusRegistry();
266
+ this.#loadingIndicatorManager = new LoadingIndicatorManager(
267
+ loadingIndicatorsElement,
268
+ this.#loadingStatusRegistry
269
+ );
270
+ }
271
+
272
+ /**
273
+ * Unregisters all listeners, removes all created dom elements, removes all css classes from the container
274
+ */
275
+ destroy() {
276
+ // TODO: There's a memory leak somewhere
277
+
278
+ const canvasWrapper = this.#canvasWrapper;
279
+
280
+ this.container.classList.remove("genome-spy");
281
+ canvasWrapper.classList.remove("loading");
282
+
283
+ this.#keyboardListenerManager.removeAll();
284
+
285
+ this.#destructionCallbacks.forEach((callback) => callback());
286
+
287
+ this.#glHelper.finalize();
288
+
289
+ this.#inputBindingManager.remove();
290
+
291
+ this.#loadingIndicatorManager.destroy();
292
+
293
+ while (this.container.firstChild) {
294
+ this.container.firstChild.remove();
295
+ }
296
+ }
297
+
298
+ async #prepareViewsAndData() {
299
+ await this.#initializeGenomeStore();
300
+ const context = this.#createViewContext();
301
+ await this.#initializeViewHierarchy(context);
302
+ await initializeViewData(
303
+ this.viewRoot,
304
+ context.dataFlow,
305
+ context.fontManager,
306
+ (flow) => this.broadcast("dataFlowBuilt", flow)
307
+ );
308
+ this.#finalizeViewInitialization(context);
309
+ }
310
+
311
+ async #initializeGenomeStore() {
312
+ this.genomeStore = new GenomeStore(this.spec.baseUrl);
313
+
314
+ const { genomesByName, defaultAssembly, deprecationWarning } =
315
+ resolveRootGenomeConfig(this.spec);
316
+ this.genomeStore.configureGenomes(genomesByName, defaultAssembly);
317
+
318
+ if (deprecationWarning) {
319
+ console.warn(deprecationWarning);
320
+ }
321
+ }
322
+
323
+ #createViewContext() {
324
+ const dataFlow = new DataFlow();
325
+ dataFlow.loadingStatusRegistry = this.#loadingStatusRegistry;
326
+ const baseConfig = resolveBaseConfig({
327
+ defaultConfig: INTERNAL_DEFAULT_CONFIG,
328
+ builtInTheme: resolveThemeSelection(DEFAULT_THEME_NAME),
329
+ theme: mergeConfigScopes([
330
+ this.options.theme,
331
+ resolveThemeSelection(this.spec.theme),
332
+ ]),
333
+ });
334
+
335
+ return createViewContext({
336
+ dataFlow,
337
+ glHelper: this.#glHelper,
338
+ animator: this.animator,
339
+ genomeStore: this.genomeStore,
340
+ fontManager: new BmFontManager(this.#glHelper),
341
+ updateTooltip: this.updateTooltip.bind(this),
342
+ getNamedDataFromProvider: this.getNamedDataFromProvider.bind(this),
343
+ getCurrentHover: () =>
344
+ this.#interactionController.getCurrentHover(),
345
+ suspendHoverTracking: () =>
346
+ this.#interactionController?.suspendHoverTracking(),
347
+ resumeHoverTracking: (event) =>
348
+ this.#interactionController?.resumeHoverTracking(event),
349
+ addKeyboardListener: (type, listener) => {
350
+ this.#keyboardListenerManager.add(type, (event) => {
351
+ if (this.#shouldDispatchKeyboardEvent(type, event)) {
352
+ listener(event);
353
+ }
354
+ });
355
+ },
356
+ addBroadcastListener: (type, listener) =>
357
+ this.#extraBroadcastListeners.add(type, listener),
358
+ removeBroadcastListener: (type, listener) =>
359
+ this.#extraBroadcastListeners.remove(type, listener),
360
+ isViewConfiguredVisible: this.viewVisibilityPredicate,
361
+ isViewSpec: (spec) => this.viewFactory.isViewSpec(spec),
362
+ getBaseConfig: () => baseConfig,
363
+ createOrImportViewWithContext: (
364
+ ctx,
365
+ spec,
366
+ layoutParent,
367
+ dataParent,
368
+ defaultName,
369
+ validator,
370
+ options
371
+ ) =>
372
+ this.viewFactory.createOrImportView(
373
+ spec,
374
+ ctx,
375
+ layoutParent,
376
+ dataParent,
377
+ defaultName,
378
+ validator,
379
+ options
380
+ ),
381
+ highlightView: createViewHighlighter(this.container),
382
+ });
383
+ }
384
+
385
+ /**
386
+ * Scopes keydown events to the active embed (focused container or hovered container).
387
+ * Keyup is always dispatched so key-state machines can reliably release keys.
388
+ *
389
+ * @param {"keydown" | "keyup"} type
390
+ * @param {KeyboardEvent} event
391
+ */
392
+ #shouldDispatchKeyboardEvent(type, event) {
393
+ if (type === "keyup") {
394
+ return true;
395
+ }
396
+
397
+ const activeElement = document.activeElement;
398
+ if (activeElement && activeElement !== document.body) {
399
+ return this.container.contains(activeElement);
400
+ } else {
401
+ return this.container.matches(":hover");
402
+ }
403
+ }
404
+
405
+ /**
406
+ * @param {import("./types/viewContext.js").default} context
407
+ */
408
+ async #initializeViewHierarchy(context) {
409
+ /** @type {ViewSpec & RootConfig} */
410
+ const rootSpec = this.spec;
411
+
412
+ if (rootSpec.datasets) {
413
+ this.registerNamedDataProvider((name) => rootSpec.datasets[name]);
414
+ }
415
+
416
+ // Create the view hierarchy.
417
+ // This also resolves scales and axes.
418
+ this.viewRoot = await context.createOrImportView(
419
+ rootSpec,
420
+ null,
421
+ null,
422
+ VIEW_ROOT_NAME
423
+ );
424
+
425
+ // Reminder: assemblies must be ensured after view creation (imports and
426
+ // inheritance resolved), but before any code path that may touch scales
427
+ // (e.g. step-based sizes, dynamic opacity, encoder initialization).
428
+ await ensureAssembliesForView(this.viewRoot, this.genomeStore);
429
+
430
+ this.#loadingStatusRegistry.set(this.viewRoot, "loading");
431
+
432
+ this.#canvasWrapper.style.flexGrow =
433
+ this.viewRoot.getSize().height.grow > 0 ? "1" : "0";
434
+
435
+ this.#initializeParameterBindings();
436
+
437
+ prepareViewHierarchy(this.viewRoot);
438
+ this.#logSelectorConstraintWarnings();
439
+
440
+ // We should now have a complete view hierarchy. Let's update the canvas size
441
+ // and ensure that the loading message is visible.
442
+ this.#glHelper.invalidateSize();
443
+ const selectedThemes = this.spec.theme
444
+ ? Array.isArray(this.spec.theme)
445
+ ? this.spec.theme
446
+ : [this.spec.theme]
447
+ : [];
448
+ this.#renderCoordinator = new RenderCoordinator({
449
+ viewRoot: this.viewRoot,
450
+ glHelper: this.#glHelper,
451
+ getBackground: () => {
452
+ if (this.spec.background !== undefined) {
453
+ return this.spec.background;
454
+ }
455
+
456
+ let background;
457
+ for (const themeName of selectedThemes) {
458
+ const value = getBuiltInThemeBackground(themeName);
459
+ if (value !== undefined) {
460
+ background = value;
461
+ }
462
+ }
463
+
464
+ return background;
465
+ },
466
+ broadcast: this.broadcast.bind(this),
467
+ onLayoutComputed: () =>
468
+ this.#loadingIndicatorManager.updateLayout(),
469
+ });
470
+
471
+ // Allow early layout requests from view subscriptions created during initialization.
472
+ // Layout will be recomputed anyway once launch completes.
473
+ context.requestLayoutReflow = this.computeLayout.bind(this);
474
+
475
+ this.#setupDpr();
476
+ }
477
+
478
+ #logSelectorConstraintWarnings() {
479
+ const issues = validateSelectorConstraints(this.viewRoot);
480
+ if (!issues.length) {
481
+ return;
482
+ }
483
+
484
+ for (const issue of issues) {
485
+ console.warn("Selector constraints warning:", issue.message);
486
+ }
487
+ }
488
+
489
+ /**
490
+ * @param {import("./types/viewContext.js").default} context
491
+ */
492
+ #finalizeViewInitialization(context) {
493
+ // Allow layout computation (in case a custom context overrode the early assignment).
494
+ context.requestLayoutReflow = this.computeLayout.bind(this);
495
+
496
+ // Invalidate cached sizes to ensure that step-based sizes are current.
497
+ // TODO: This should be done automatically when the domains of band/point scales are updated.
498
+ this.viewRoot.visit((view) => invalidatePrefix(view, "size"));
499
+ this.#glHelper.invalidateSize();
500
+
501
+ this.#interactionController = new InteractionController({
502
+ viewRoot: this.viewRoot,
503
+ glHelper: this.#glHelper,
504
+ tooltip: this.tooltip,
505
+ animator: this.animator,
506
+ emitEvent: this.#eventListeners.emit.bind(this.#eventListeners),
507
+ tooltipHandlers: this.tooltipHandlers,
508
+ renderPickingFramebuffer: this.renderPickingFramebuffer.bind(this),
509
+ getDevicePixelRatio: () => this.dpr,
510
+ });
511
+ }
512
+
513
+ /**
514
+ * TODO: Come up with a sensible name. And maybe this should be called at the end of the constructor.
515
+ * @returns {Promise<boolean>} true if the launch was successful
516
+ */
517
+ async launch() {
518
+ let launched = false;
519
+ try {
520
+ this.#prepareContainer();
521
+
522
+ await this.#prepareViewsAndData();
523
+
524
+ this.#interactionController.registerInteractionEvents();
525
+
526
+ this.computeLayout();
527
+ this.animator.requestRender();
528
+
529
+ launched = true;
530
+ return true;
531
+ } catch (reason) {
532
+ const message = `${
533
+ reason.view ? `At "${reason.view.getPathString()}": ` : ""
534
+ }${reason.toString()}`;
535
+ console.error(reason.stack);
536
+ const handled = this.options.onError?.(reason, this.container);
537
+ if (!handled) {
538
+ createMessageBox(this.container, message);
539
+ }
540
+
541
+ if (this.viewRoot) {
542
+ this.#loadingStatusRegistry.set(
543
+ this.viewRoot,
544
+ "error",
545
+ message
546
+ );
547
+ }
548
+
549
+ return false;
550
+ } finally {
551
+ this.#canvasWrapper.classList.remove("loading");
552
+ if (launched && this.viewRoot) {
553
+ this.#loadingStatusRegistry.set(this.viewRoot, "complete");
554
+ }
555
+ }
556
+ }
557
+
558
+ async initializeVisibleViewData() {
559
+ if (!this.viewRoot) {
560
+ return;
561
+ }
562
+
563
+ await initializeVisibleViewData(
564
+ this.viewRoot,
565
+ this.viewRoot.context.dataFlow,
566
+ this.viewRoot.context.fontManager
567
+ );
568
+
569
+ // Visibility toggles can change sizes; ensure layout is recomputed even
570
+ // when callers don't explicitly request it.
571
+ this.viewRoot._invalidateCacheByPrefix("size", "progeny");
572
+ this.#glHelper.invalidateSize();
573
+ this.computeLayout();
574
+ this.animator.requestRender();
575
+ }
576
+
577
+ /**
578
+ * Waits until lazy sources under the root view have loaded data for the
579
+ * current visible positional domain.
580
+ *
581
+ * @param {AbortSignal} [signal]
582
+ */
583
+ async awaitVisibleLazyData(signal) {
584
+ if (!this.viewRoot) {
585
+ return;
586
+ }
587
+
588
+ await awaitSubtreeLazyReady(
589
+ this.viewRoot.context,
590
+ this.viewRoot,
591
+ undefined,
592
+ signal,
593
+ (view) =>
594
+ view.isConfiguredVisible() && hasWindowedLazyDataSource(view)
595
+ );
596
+ }
597
+
598
+ /**
599
+ * This method should be called in a mouseMove handler. If not called, the
600
+ * tooltip will be hidden.
601
+ *
602
+ * @param {T} datum
603
+ * @param {function(T):Promise<string | HTMLElement | import("lit").TemplateResult>} [converter]
604
+ * @template T
605
+ */
606
+ updateTooltip(datum, converter) {
607
+ this.#interactionController.updateTooltip(datum, converter);
608
+ }
609
+
610
+ /**
611
+ * Returns a PNG data URL of the current canvas.
612
+ *
613
+ * @param {number} [logicalWidth] defaults to canvas width
614
+ * @param {number} [logicalHeight] defaults to canvas height
615
+ * @param {number} [devicePixelRatio] defaults to window.devicePixelRatio
616
+ * @param {string} [clearColor] null for transparent
617
+ * @returns A PNG data Url
618
+ */
619
+ exportCanvas(
620
+ logicalWidth,
621
+ logicalHeight,
622
+ devicePixelRatio,
623
+ clearColor = "white"
624
+ ) {
625
+ const pngUrl = exportCanvas({
626
+ glHelper: this.#glHelper,
627
+ viewRoot: this.viewRoot,
628
+ logicalWidth,
629
+ logicalHeight,
630
+ devicePixelRatio,
631
+ clearColor,
632
+ });
633
+
634
+ // Clean up
635
+ this.computeLayout();
636
+ this.renderAll();
637
+
638
+ return pngUrl;
639
+ }
640
+
641
+ getLogicalCanvasSize() {
642
+ return this.#glHelper.getLogicalCanvasSize();
643
+ }
644
+
645
+ getRenderedBounds() {
646
+ /** @type {{ width: number | undefined, height: number | undefined }} */
647
+ const bounds = {
648
+ width: undefined,
649
+ height: undefined,
650
+ };
651
+
652
+ this.viewRoot.visit((view) => {
653
+ for (const coords of view.facetCoords.values()) {
654
+ bounds.width = Math.max(bounds.width ?? 0, coords.x2);
655
+ bounds.height = Math.max(bounds.height ?? 0, coords.y2);
656
+ }
657
+ });
658
+
659
+ return bounds;
660
+ }
661
+
662
+ computeLayout() {
663
+ this.#renderCoordinator.computeLayout();
664
+ this.#glHelper.invalidateSize();
665
+ }
666
+
667
+ renderAll() {
668
+ this.#renderCoordinator.renderAll();
669
+ }
670
+
671
+ renderPickingFramebuffer() {
672
+ this.#renderCoordinator.renderPickingFramebuffer();
673
+ }
674
+
675
+ getSearchableViews() {
676
+ /** @type {UnitView[]} */
677
+ const views = [];
678
+ this.viewRoot.visit((view) => {
679
+ if (
680
+ view instanceof UnitView &&
681
+ view.getSearchAccessors().length > 0
682
+ ) {
683
+ views.push(view);
684
+ }
685
+ });
686
+ return views;
687
+ }
688
+
689
+ getNamedScaleResolutions() {
690
+ /** @type {Map<string, import("./scales/scaleResolution.js").default>} */
691
+ const resolutions = new Map();
692
+ this.viewRoot.visit((view) => {
693
+ for (const resolution of Object.values(view.resolutions.scale)) {
694
+ if (resolution.name) {
695
+ resolutions.set(resolution.name, resolution);
696
+ }
697
+ }
698
+ });
699
+ return resolutions;
700
+ }
701
+ }
702
+
703
+ /**
704
+ * @param {View} view
705
+ */
706
+ function hasWindowedLazyDataSource(view) {
707
+ /** @type {View | null} */
708
+ let current = view;
709
+
710
+ while (current) {
711
+ const dataSource = current.flowHandle?.dataSource;
712
+ if (dataSource) {
713
+ return dataSource instanceof SingleAxisWindowedSource;
714
+ }
715
+ current = current.dataParent;
716
+ }
717
+
718
+ return false;
719
+ }