@genome-spy/core 0.37.3 → 0.38.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 (356) hide show
  1. package/dist/bundle/__vite-browser-external-ENoMJThg.js +8 -0
  2. package/dist/bundle/_commonjsHelpers-QtkX90xp.js +30 -0
  3. package/dist/bundle/index-1QVesMzU.js +1074 -0
  4. package/dist/bundle/index-Cbz74kpR.js +638 -0
  5. package/dist/bundle/index-LD6yPc3X.js +515 -0
  6. package/dist/bundle/index-Pv3tKJ1W.js +2190 -0
  7. package/dist/bundle/index-UyrC0vvF.js +72 -0
  8. package/dist/bundle/index-Y-LdHNIz.js +501 -0
  9. package/dist/bundle/index-gn8bhQ8w.js +4050 -0
  10. package/dist/bundle/index-lmJu1tfP.js +1372 -0
  11. package/dist/bundle/index-z4Cs62EO.js +279 -0
  12. package/dist/bundle/index.es.js +6448 -20571
  13. package/dist/bundle/index.js +93 -112
  14. package/dist/bundle/long-Veu0zKh9.js +2382 -0
  15. package/dist/bundle/remoteFile-Ur-gRKsH.js +96 -0
  16. package/dist/schema.json +492 -108
  17. package/dist/src/data/collector.d.ts +11 -11
  18. package/dist/src/data/collector.d.ts.map +1 -1
  19. package/dist/src/data/collector.js +8 -8
  20. package/dist/src/data/dataFlow.d.ts +18 -18
  21. package/dist/src/data/dataFlow.d.ts.map +1 -1
  22. package/dist/src/data/dataFlow.js +7 -7
  23. package/dist/src/data/flowNode.d.ts +9 -9
  24. package/dist/src/data/flowNode.d.ts.map +1 -1
  25. package/dist/src/data/flowNode.js +5 -5
  26. package/dist/src/data/flowOptimizer.d.ts +11 -11
  27. package/dist/src/data/flowOptimizer.d.ts.map +1 -1
  28. package/dist/src/data/flowOptimizer.js +7 -7
  29. package/dist/src/data/flowTestUtils.d.ts +2 -2
  30. package/dist/src/data/flowTestUtils.d.ts.map +1 -1
  31. package/dist/src/data/flowTestUtils.js +1 -1
  32. package/dist/src/data/sources/dataSource.js +1 -1
  33. package/dist/src/data/sources/dataSourceFactory.d.ts +3 -3
  34. package/dist/src/data/sources/dataSourceFactory.d.ts.map +1 -1
  35. package/dist/src/data/sources/dataSourceFactory.js +20 -20
  36. package/dist/src/data/sources/dataUtils.d.ts +20 -20
  37. package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
  38. package/dist/src/data/sources/dataUtils.js +11 -11
  39. package/dist/src/data/sources/dynamic/axisGenomeSource.d.ts +3 -3
  40. package/dist/src/data/sources/dynamic/axisGenomeSource.d.ts.map +1 -1
  41. package/dist/src/data/sources/dynamic/axisGenomeSource.js +2 -2
  42. package/dist/src/data/sources/dynamic/axisTickSource.d.ts +6 -6
  43. package/dist/src/data/sources/dynamic/axisTickSource.d.ts.map +1 -1
  44. package/dist/src/data/sources/dynamic/axisTickSource.js +4 -4
  45. package/dist/src/data/sources/dynamic/bamSource.d.ts +7 -13
  46. package/dist/src/data/sources/dynamic/bamSource.d.ts.map +1 -1
  47. package/dist/src/data/sources/dynamic/bamSource.js +35 -27
  48. package/dist/src/data/sources/dynamic/bigBedSource.d.ts +9 -9
  49. package/dist/src/data/sources/dynamic/bigBedSource.d.ts.map +1 -1
  50. package/dist/src/data/sources/dynamic/bigBedSource.js +31 -18
  51. package/dist/src/data/sources/dynamic/bigWigSource.d.ts +7 -7
  52. package/dist/src/data/sources/dynamic/bigWigSource.d.ts.map +1 -1
  53. package/dist/src/data/sources/dynamic/bigWigSource.js +33 -26
  54. package/dist/src/data/sources/dynamic/gff3Source.d.ts +9 -0
  55. package/dist/src/data/sources/dynamic/gff3Source.d.ts.map +1 -1
  56. package/dist/src/data/sources/dynamic/gff3Source.js +17 -2
  57. package/dist/src/data/sources/dynamic/indexedFastaSource.d.ts +6 -9
  58. package/dist/src/data/sources/dynamic/indexedFastaSource.d.ts.map +1 -1
  59. package/dist/src/data/sources/dynamic/indexedFastaSource.js +28 -18
  60. package/dist/src/data/sources/dynamic/singleAxisLazySource.d.ts +10 -10
  61. package/dist/src/data/sources/dynamic/singleAxisLazySource.d.ts.map +1 -1
  62. package/dist/src/data/sources/dynamic/singleAxisLazySource.js +6 -6
  63. package/dist/src/data/sources/dynamic/tabixSource.d.ts +11 -8
  64. package/dist/src/data/sources/dynamic/tabixSource.d.ts.map +1 -1
  65. package/dist/src/data/sources/dynamic/tabixSource.js +31 -17
  66. package/dist/src/data/sources/inlineSource.d.ts +7 -7
  67. package/dist/src/data/sources/inlineSource.d.ts.map +1 -1
  68. package/dist/src/data/sources/inlineSource.js +5 -5
  69. package/dist/src/data/sources/namedSource.d.ts +9 -9
  70. package/dist/src/data/sources/namedSource.d.ts.map +1 -1
  71. package/dist/src/data/sources/namedSource.js +6 -6
  72. package/dist/src/data/sources/sequenceSource.d.ts +7 -7
  73. package/dist/src/data/sources/sequenceSource.d.ts.map +1 -1
  74. package/dist/src/data/sources/sequenceSource.js +4 -4
  75. package/dist/src/data/sources/urlSource.d.ts +7 -7
  76. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  77. package/dist/src/data/sources/urlSource.js +4 -4
  78. package/dist/src/data/transforms/aggregate.d.ts +3 -3
  79. package/dist/src/data/transforms/aggregate.d.ts.map +1 -1
  80. package/dist/src/data/transforms/aggregate.js +2 -2
  81. package/dist/src/data/transforms/clone.d.ts +2 -2
  82. package/dist/src/data/transforms/clone.d.ts.map +1 -1
  83. package/dist/src/data/transforms/clone.js +1 -1
  84. package/dist/src/data/transforms/coverage.d.ts +3 -3
  85. package/dist/src/data/transforms/coverage.d.ts.map +1 -1
  86. package/dist/src/data/transforms/coverage.js +1 -1
  87. package/dist/src/data/transforms/coverage.test.js +1 -1
  88. package/dist/src/data/transforms/filter.d.ts +3 -3
  89. package/dist/src/data/transforms/filter.d.ts.map +1 -1
  90. package/dist/src/data/transforms/filter.js +2 -2
  91. package/dist/src/data/transforms/filter.test.js +1 -1
  92. package/dist/src/data/transforms/filterScoredLabels.d.ts +4 -4
  93. package/dist/src/data/transforms/filterScoredLabels.d.ts.map +1 -1
  94. package/dist/src/data/transforms/filterScoredLabels.js +3 -3
  95. package/dist/src/data/transforms/flatten.d.ts +2 -2
  96. package/dist/src/data/transforms/flatten.d.ts.map +1 -1
  97. package/dist/src/data/transforms/flatten.js +3 -3
  98. package/dist/src/data/transforms/flatten.test.js +6 -6
  99. package/dist/src/data/transforms/flattenCompressedExons.d.ts +2 -2
  100. package/dist/src/data/transforms/flattenCompressedExons.d.ts.map +1 -1
  101. package/dist/src/data/transforms/flattenCompressedExons.js +1 -1
  102. package/dist/src/data/transforms/flattenDelimited.d.ts +2 -2
  103. package/dist/src/data/transforms/flattenDelimited.d.ts.map +1 -1
  104. package/dist/src/data/transforms/flattenDelimited.js +2 -2
  105. package/dist/src/data/transforms/flattenDelimited.test.js +5 -5
  106. package/dist/src/data/transforms/flattenSequence.d.ts +2 -2
  107. package/dist/src/data/transforms/flattenSequence.d.ts.map +1 -1
  108. package/dist/src/data/transforms/flattenSequence.js +1 -1
  109. package/dist/src/data/transforms/flattenSequence.test.js +1 -1
  110. package/dist/src/data/transforms/formula.d.ts +3 -3
  111. package/dist/src/data/transforms/formula.d.ts.map +1 -1
  112. package/dist/src/data/transforms/formula.js +2 -2
  113. package/dist/src/data/transforms/identifier.d.ts +3 -3
  114. package/dist/src/data/transforms/identifier.d.ts.map +1 -1
  115. package/dist/src/data/transforms/identifier.js +2 -2
  116. package/dist/src/data/transforms/linearizeGenomicCoordinate.d.ts +3 -3
  117. package/dist/src/data/transforms/linearizeGenomicCoordinate.d.ts.map +1 -1
  118. package/dist/src/data/transforms/linearizeGenomicCoordinate.js +2 -2
  119. package/dist/src/data/transforms/measureText.d.ts +2 -2
  120. package/dist/src/data/transforms/measureText.d.ts.map +1 -1
  121. package/dist/src/data/transforms/measureText.js +1 -1
  122. package/dist/src/data/transforms/pileup.d.ts +3 -3
  123. package/dist/src/data/transforms/pileup.d.ts.map +1 -1
  124. package/dist/src/data/transforms/pileup.js +1 -1
  125. package/dist/src/data/transforms/pileup.test.js +1 -1
  126. package/dist/src/data/transforms/project.d.ts +2 -2
  127. package/dist/src/data/transforms/project.d.ts.map +1 -1
  128. package/dist/src/data/transforms/project.js +1 -1
  129. package/dist/src/data/transforms/project.test.js +1 -1
  130. package/dist/src/data/transforms/regexExtract.d.ts +2 -2
  131. package/dist/src/data/transforms/regexExtract.d.ts.map +1 -1
  132. package/dist/src/data/transforms/regexExtract.js +1 -1
  133. package/dist/src/data/transforms/regexExtract.test.js +3 -3
  134. package/dist/src/data/transforms/regexFold.d.ts +2 -2
  135. package/dist/src/data/transforms/regexFold.d.ts.map +1 -1
  136. package/dist/src/data/transforms/regexFold.js +2 -2
  137. package/dist/src/data/transforms/regexFold.test.js +3 -3
  138. package/dist/src/data/transforms/sample.d.ts +2 -2
  139. package/dist/src/data/transforms/sample.d.ts.map +1 -1
  140. package/dist/src/data/transforms/sample.js +2 -2
  141. package/dist/src/data/transforms/stack.d.ts +3 -3
  142. package/dist/src/data/transforms/stack.d.ts.map +1 -1
  143. package/dist/src/data/transforms/stack.js +2 -2
  144. package/dist/src/data/transforms/stack.test.js +2 -2
  145. package/dist/src/data/transforms/transformFactory.d.ts +5 -5
  146. package/dist/src/data/transforms/transformFactory.d.ts.map +1 -1
  147. package/dist/src/data/transforms/transformFactory.js +3 -3
  148. package/dist/src/encoder/accessor.d.ts +6 -6
  149. package/dist/src/encoder/accessor.d.ts.map +1 -1
  150. package/dist/src/encoder/accessor.js +4 -4
  151. package/dist/src/encoder/encoder.d.ts +59 -59
  152. package/dist/src/encoder/encoder.d.ts.map +1 -1
  153. package/dist/src/encoder/encoder.js +40 -40
  154. package/dist/src/encoder/encoder.test.js +4 -4
  155. package/dist/src/fonts/bmFontManager.d.ts +7 -7
  156. package/dist/src/fonts/bmFontManager.d.ts.map +1 -1
  157. package/dist/src/fonts/bmFontManager.js +3 -3
  158. package/dist/src/fonts/bmFontMetrics.d.ts +6 -6
  159. package/dist/src/fonts/bmFontMetrics.d.ts.map +1 -1
  160. package/dist/src/fonts/bmFontMetrics.js +4 -4
  161. package/dist/src/genome/genome.d.ts +7 -7
  162. package/dist/src/genome/genome.d.ts.map +1 -1
  163. package/dist/src/genome/genome.js +2 -2
  164. package/dist/src/genome/genomeStore.d.ts +2 -2
  165. package/dist/src/genome/genomeStore.d.ts.map +1 -1
  166. package/dist/src/genome/genomeStore.js +1 -1
  167. package/dist/src/genome/locusFormat.d.ts +7 -7
  168. package/dist/src/genome/locusFormat.d.ts.map +1 -1
  169. package/dist/src/genome/locusFormat.js +4 -4
  170. package/dist/src/genome/scaleIndex.d.ts +1 -1
  171. package/dist/src/genome/scaleIndex.d.ts.map +1 -1
  172. package/dist/src/genome/scaleIndex.js +1 -1
  173. package/dist/src/genome/scaleLocus.d.ts +2 -2
  174. package/dist/src/genome/scaleLocus.d.ts.map +1 -1
  175. package/dist/src/genome/scaleLocus.js +3 -3
  176. package/dist/src/genomeSpy.d.ts +12 -12
  177. package/dist/src/genomeSpy.d.ts.map +1 -1
  178. package/dist/src/genomeSpy.js +52 -35
  179. package/dist/src/gl/arrayBuilder.d.ts.map +1 -1
  180. package/dist/src/gl/dataToVertices.d.ts +18 -18
  181. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  182. package/dist/src/gl/dataToVertices.js +10 -10
  183. package/dist/src/gl/webGLHelper.d.ts +4 -4
  184. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  185. package/dist/src/gl/webGLHelper.js +2 -2
  186. package/dist/src/index.d.ts.map +1 -1
  187. package/dist/src/index.js +1 -1
  188. package/dist/src/marks/link.js +5 -5
  189. package/dist/src/marks/mark.d.ts +35 -32
  190. package/dist/src/marks/mark.d.ts.map +1 -1
  191. package/dist/src/marks/mark.js +26 -23
  192. package/dist/src/marks/markUtils.d.ts +10 -10
  193. package/dist/src/marks/markUtils.d.ts.map +1 -1
  194. package/dist/src/marks/markUtils.js +5 -5
  195. package/dist/src/marks/pointMark.d.ts +1 -1
  196. package/dist/src/marks/pointMark.d.ts.map +1 -1
  197. package/dist/src/marks/pointMark.js +7 -7
  198. package/dist/src/marks/rectMark.d.ts +2 -2
  199. package/dist/src/marks/rectMark.d.ts.map +1 -1
  200. package/dist/src/marks/rectMark.js +7 -7
  201. package/dist/src/marks/rule.js +6 -6
  202. package/dist/src/marks/text.d.ts +1 -1
  203. package/dist/src/marks/text.d.ts.map +1 -1
  204. package/dist/src/marks/text.js +6 -6
  205. package/dist/src/scale/colorUtils.d.ts +4 -4
  206. package/dist/src/scale/colorUtils.d.ts.map +1 -1
  207. package/dist/src/scale/colorUtils.js +2 -2
  208. package/dist/src/scale/glslScaleGenerator.d.ts +3 -3
  209. package/dist/src/scale/glslScaleGenerator.d.ts.map +1 -1
  210. package/dist/src/scale/glslScaleGenerator.js +2 -2
  211. package/dist/src/scale/scale.d.ts +3 -3
  212. package/dist/src/scale/scale.d.ts.map +1 -1
  213. package/dist/src/scale/scale.js +2 -2
  214. package/dist/src/scale/ticks.d.ts +4 -4
  215. package/dist/src/scale/ticks.js +4 -4
  216. package/dist/src/spec/axis.d.ts +1 -1
  217. package/dist/src/spec/channel.d.ts +2 -2
  218. package/dist/src/spec/data.d.ts +2 -2
  219. package/dist/src/spec/mark.d.ts +3 -3
  220. package/dist/src/spec/root.d.ts +2 -2
  221. package/dist/src/spec/sampleView.d.ts +5 -5
  222. package/dist/src/spec/scale.d.ts +1 -1
  223. package/dist/src/spec/title.d.ts +1 -1
  224. package/dist/src/spec/view.d.ts +36 -9
  225. package/dist/src/tooltip/dataTooltipHandler.js +1 -1
  226. package/dist/src/tooltip/refseqGeneTooltipHandler.d.ts.map +1 -1
  227. package/dist/src/tooltip/refseqGeneTooltipHandler.js +1 -1
  228. package/dist/src/tooltip/tooltipHandler.d.ts +1 -1
  229. package/dist/src/tooltip/tooltipHandler.d.ts.map +1 -1
  230. package/dist/src/tooltip/tooltipHandler.ts +1 -1
  231. package/dist/src/types/embedApi.d.ts +3 -3
  232. package/dist/src/types/encoder.d.ts +4 -4
  233. package/dist/src/types/flowBatch.d.ts +1 -1
  234. package/dist/src/types/rendering.d.ts +3 -3
  235. package/dist/src/types/scaleResolutionApi.d.ts +2 -2
  236. package/dist/src/types/viewContext.d.ts +41 -12
  237. package/dist/src/utils/animator.d.ts +2 -2
  238. package/dist/src/utils/animator.d.ts.map +1 -1
  239. package/dist/src/utils/animator.js +1 -1
  240. package/dist/src/utils/inertia.d.ts +3 -3
  241. package/dist/src/utils/inertia.d.ts.map +1 -1
  242. package/dist/src/utils/inertia.js +1 -1
  243. package/dist/src/utils/interactionEvent.d.ts +5 -5
  244. package/dist/src/utils/interactionEvent.d.ts.map +1 -1
  245. package/dist/src/utils/interactionEvent.js +2 -2
  246. package/dist/src/utils/trees.js +1 -1
  247. package/dist/src/view/axisGridView.d.ts +17 -16
  248. package/dist/src/view/axisGridView.d.ts.map +1 -1
  249. package/dist/src/view/axisGridView.js +24 -20
  250. package/dist/src/view/axisResolution.d.ts +10 -10
  251. package/dist/src/view/axisResolution.d.ts.map +1 -1
  252. package/dist/src/view/axisResolution.js +6 -6
  253. package/dist/src/view/axisResolution.test.js +1 -1
  254. package/dist/src/view/axisView.d.ts +18 -17
  255. package/dist/src/view/axisView.d.ts.map +1 -1
  256. package/dist/src/view/axisView.js +39 -35
  257. package/dist/src/view/concatView.d.ts +5 -5
  258. package/dist/src/view/concatView.d.ts.map +1 -1
  259. package/dist/src/view/concatView.js +23 -23
  260. package/dist/src/view/containerView.d.ts +10 -8
  261. package/dist/src/view/containerView.d.ts.map +1 -1
  262. package/dist/src/view/containerView.js +18 -13
  263. package/dist/src/view/facetView.d.ts +12 -12
  264. package/dist/src/view/facetView.d.ts.map +1 -1
  265. package/dist/src/view/facetView.js +19 -19
  266. package/dist/src/view/flowBuilder.d.ts +4 -4
  267. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  268. package/dist/src/view/flowBuilder.js +13 -13
  269. package/dist/src/view/flowBuilder.test.js +7 -7
  270. package/dist/src/view/gridView.d.ts +63 -35
  271. package/dist/src/view/gridView.d.ts.map +1 -1
  272. package/dist/src/view/gridView.js +400 -113
  273. package/dist/src/view/layerView.d.ts +12 -14
  274. package/dist/src/view/layerView.d.ts.map +1 -1
  275. package/dist/src/view/layerView.js +55 -26
  276. package/dist/src/{utils → view}/layout/flexLayout.d.ts +6 -6
  277. package/dist/src/view/layout/flexLayout.d.ts.map +1 -0
  278. package/dist/src/{utils → view}/layout/flexLayout.js +4 -4
  279. package/dist/src/view/layout/grid.d.ts.map +1 -0
  280. package/dist/src/{utils → view}/layout/padding.d.ts +4 -4
  281. package/dist/src/view/layout/padding.d.ts.map +1 -0
  282. package/dist/src/{utils → view}/layout/padding.js +2 -2
  283. package/dist/src/view/layout/point.d.ts.map +1 -0
  284. package/dist/src/{utils → view}/layout/rectangle.d.ts +8 -2
  285. package/dist/src/view/layout/rectangle.d.ts.map +1 -0
  286. package/dist/src/{utils → view}/layout/rectangle.js +22 -2
  287. package/dist/src/{utils → view}/layout/rectangle.test.js +8 -0
  288. package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts +10 -10
  289. package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts.map +1 -1
  290. package/dist/src/view/renderingContext/bufferedViewRenderingContext.js +10 -10
  291. package/dist/src/view/renderingContext/compositeViewRenderingContext.d.ts +2 -2
  292. package/dist/src/view/renderingContext/compositeViewRenderingContext.d.ts.map +1 -1
  293. package/dist/src/view/renderingContext/compositeViewRenderingContext.js +4 -4
  294. package/dist/src/view/renderingContext/debuggingViewRenderingContext.d.ts +4 -4
  295. package/dist/src/view/renderingContext/debuggingViewRenderingContext.d.ts.map +1 -1
  296. package/dist/src/view/renderingContext/debuggingViewRenderingContext.js +3 -3
  297. package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.d.ts +8 -8
  298. package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.d.ts.map +1 -1
  299. package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.js +4 -4
  300. package/dist/src/view/renderingContext/simpleViewRenderingContext.d.ts +6 -6
  301. package/dist/src/view/renderingContext/simpleViewRenderingContext.d.ts.map +1 -1
  302. package/dist/src/view/renderingContext/simpleViewRenderingContext.js +7 -7
  303. package/dist/src/view/renderingContext/svgViewRenderingContext.d.ts +4 -4
  304. package/dist/src/view/renderingContext/svgViewRenderingContext.d.ts.map +1 -1
  305. package/dist/src/view/renderingContext/svgViewRenderingContext.js +6 -6
  306. package/dist/src/view/renderingContext/viewRenderingContext.d.ts +10 -10
  307. package/dist/src/view/renderingContext/viewRenderingContext.d.ts.map +1 -1
  308. package/dist/src/view/renderingContext/viewRenderingContext.js +5 -5
  309. package/dist/src/view/scaleResolution.d.ts +21 -17
  310. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  311. package/dist/src/view/scaleResolution.js +29 -24
  312. package/dist/src/view/scaleResolution.test.js +57 -72
  313. package/dist/src/view/testUtils.d.ts +6 -15
  314. package/dist/src/view/testUtils.d.ts.map +1 -1
  315. package/dist/src/view/testUtils.js +40 -44
  316. package/dist/src/view/title.d.ts +3 -3
  317. package/dist/src/view/title.d.ts.map +1 -1
  318. package/dist/src/view/title.js +12 -12
  319. package/dist/src/view/unitView.d.ts +31 -30
  320. package/dist/src/view/unitView.d.ts.map +1 -1
  321. package/dist/src/view/unitView.js +30 -22
  322. package/dist/src/view/view.d.ts +86 -57
  323. package/dist/src/view/view.d.ts.map +1 -1
  324. package/dist/src/view/view.js +148 -103
  325. package/dist/src/view/view.test.js +9 -8
  326. package/dist/src/view/viewError.d.ts +9 -0
  327. package/dist/src/view/viewError.d.ts.map +1 -0
  328. package/dist/src/view/viewError.js +11 -0
  329. package/dist/src/view/viewFactory.d.ts +53 -20
  330. package/dist/src/view/viewFactory.d.ts.map +1 -1
  331. package/dist/src/view/viewFactory.js +148 -33
  332. package/dist/src/view/viewFactory.test.js +8 -0
  333. package/dist/src/view/viewUtils.d.ts +14 -12
  334. package/dist/src/view/viewUtils.d.ts.map +1 -1
  335. package/dist/src/view/viewUtils.js +10 -63
  336. package/dist/src/view/zoom.d.ts +4 -4
  337. package/dist/src/view/zoom.d.ts.map +1 -1
  338. package/dist/src/view/zoom.js +3 -3
  339. package/package.json +7 -5
  340. package/dist/src/utils/layout/flexLayout.d.ts.map +0 -1
  341. package/dist/src/utils/layout/grid.d.ts.map +0 -1
  342. package/dist/src/utils/layout/padding.d.ts.map +0 -1
  343. package/dist/src/utils/layout/point.d.ts.map +0 -1
  344. package/dist/src/utils/layout/rectangle.d.ts.map +0 -1
  345. package/dist/src/view/implicitRootView.d.ts +0 -9
  346. package/dist/src/view/implicitRootView.d.ts.map +0 -1
  347. package/dist/src/view/implicitRootView.js +0 -23
  348. package/dist/src/view/importView.d.ts +0 -17
  349. package/dist/src/view/importView.d.ts.map +0 -1
  350. package/dist/src/view/importView.js +0 -22
  351. /package/dist/src/{utils → view}/layout/flexLayout.test.js +0 -0
  352. /package/dist/src/{utils → view}/layout/grid.d.ts +0 -0
  353. /package/dist/src/{utils → view}/layout/grid.js +0 -0
  354. /package/dist/src/{utils → view}/layout/grid.test.js +0 -0
  355. /package/dist/src/{utils → view}/layout/point.d.ts +0 -0
  356. /package/dist/src/{utils → view}/layout/point.js +0 -0
@@ -6,10 +6,10 @@ import {
6
6
  mapToPixelCoords,
7
7
  parseSizeDef,
8
8
  ZERO_SIZEDEF,
9
- } from "../utils/layout/flexLayout.js";
10
- import Grid from "../utils/layout/grid.js";
11
- import Padding from "../utils/layout/padding.js";
12
- import Rectangle from "../utils/layout/rectangle.js";
9
+ } from "./layout/flexLayout.js";
10
+ import Grid from "./layout/grid.js";
11
+ import Padding from "./layout/padding.js";
12
+ import Rectangle from "./layout/rectangle.js";
13
13
  import AxisGridView from "./axisGridView.js";
14
14
  import AxisView, { CHANNEL_ORIENTS, ORIENT_CHANNELS } from "./axisView.js";
15
15
  import ContainerView from "./containerView.js";
@@ -17,6 +17,7 @@ import LayerView from "./layerView.js";
17
17
  import createTitle from "./title.js";
18
18
  import UnitView from "./unitView.js";
19
19
  import interactionToZoom from "./zoom.js";
20
+ import clamp from "../utils/clamp.js";
20
21
 
21
22
  /**
22
23
  * Modeled after: https://vega.github.io/vega/docs/layout/
@@ -31,13 +32,15 @@ import interactionToZoom from "./zoom.js";
31
32
  * - Facet (column / row) titles
32
33
  * - Header / footer
33
34
  * - Zoom / pan
35
+ * - Scrollable viewports (with scrollbars)
34
36
  * - And later on, brushing, legend(?)
35
37
  */
36
38
  export default class GridView extends ContainerView {
37
39
  /**
38
40
  * @typedef {"row" | "column"} Direction
41
+ * @typedef {"horizontal" | "vertical"} ScrollDirection
39
42
  *
40
- * @typedef {import("./view").default} View
43
+ * @typedef {import("./view.js").default} View
41
44
  */
42
45
 
43
46
  /** */
@@ -55,7 +58,7 @@ export default class GridView extends ContainerView {
55
58
  * toggleable view visibilities. For example, if the bottom view is suddenly hidden,
56
59
  * the axis should be shown in the view that takes its place as the new bottom view.
57
60
  *
58
- * @type { Partial<Record<import("../spec/channel").PrimaryPositionalChannel, AxisView>> } }
61
+ * @type { Partial<Record<import("../spec/channel.js").PrimaryPositionalChannel, AxisView>> } }
59
62
  */
60
63
  #sharedAxes = {};
61
64
 
@@ -63,15 +66,24 @@ export default class GridView extends ContainerView {
63
66
 
64
67
  /**
65
68
  *
66
- * @param {import("../spec/view").AnyConcatSpec} spec
67
- * @param {import("../types/viewContext").default} context
69
+ * @param {import("../spec/view.js").AnyConcatSpec} spec
70
+ * @param {import("../types/viewContext.js").default} context
68
71
  * @param {ContainerView} layoutParent
69
72
  * @param {View} dataParent
70
73
  * @param {string} name
71
74
  * @param {number} columns
75
+ * @param {import("./view.js").ViewOptions} [options]
72
76
  */
73
- constructor(spec, context, layoutParent, dataParent, name, columns) {
74
- super(spec, context, layoutParent, dataParent, name);
77
+ constructor(
78
+ spec,
79
+ context,
80
+ layoutParent,
81
+ dataParent,
82
+ name,
83
+ columns,
84
+ options
85
+ ) {
86
+ super(spec, context, layoutParent, dataParent, name, options);
75
87
  this.spec = spec;
76
88
 
77
89
  this.#spacing = spec.spacing ?? 10;
@@ -80,15 +92,6 @@ export default class GridView extends ContainerView {
80
92
  this.#children = [];
81
93
 
82
94
  this.wrappingFacet = false;
83
-
84
- this._createChildren();
85
- }
86
-
87
- /**
88
- * @protected
89
- */
90
- _createChildren() {
91
- // Override
92
95
  }
93
96
 
94
97
  /**
@@ -153,13 +156,13 @@ export default class GridView extends ContainerView {
153
156
  return this.#children.length;
154
157
  }
155
158
 
156
- onScalesResolved() {
157
- super.onScalesResolved();
158
-
159
- this.#createAxes();
160
- }
159
+ /**
160
+ * @protected
161
+ */
162
+ async createAxes() {
163
+ /** @type {Promise<void>[]} */
164
+ const promises = [];
161
165
 
162
- #createAxes() {
163
166
  // Axis ticks, labels, etc. They should be created only if this view has caught
164
167
  // the scale resolution for the channel.
165
168
  for (const channel of primaryPositionalChannels) {
@@ -180,22 +183,17 @@ export default class GridView extends ContainerView {
180
183
  this,
181
184
  this
182
185
  );
186
+ promises.push(v.initializeChildren());
183
187
  this.#sharedAxes[channel] = v;
184
-
185
- // Axes are created after scales are resolved, so we need to resolve possible new scales here
186
- v.visit((view) => {
187
- if (view instanceof UnitView) {
188
- view.resolve("scale");
189
- }
190
- });
191
188
  }
192
189
  }
193
190
  }
194
191
 
195
192
  // Create view decorations, grid lines, and independent axes for each child
196
- for (const gridChild of this.#children) {
197
- gridChild.createAxes();
198
- }
193
+ return Promise.all([
194
+ ...promises,
195
+ ...this.#children.map((gridChild) => gridChild.createAxes()),
196
+ ]);
199
197
  }
200
198
 
201
199
  /**
@@ -244,9 +242,9 @@ export default class GridView extends ContainerView {
244
242
  view: getLargestSize(
245
243
  col.map(
246
244
  (rowIndex) =>
247
- this.#visibleChildren[rowIndex].view.getSize()[
248
- dim
249
- ]
245
+ this.#visibleChildren[
246
+ rowIndex
247
+ ].view.getViewportSize()[dim]
250
248
  )
251
249
  ),
252
250
  })
@@ -275,7 +273,7 @@ export default class GridView extends ContainerView {
275
273
  #makeFlexItems(direction) {
276
274
  const sizes = this.#getSizes(direction);
277
275
 
278
- /** @type {import("../utils/layout/flexLayout").SizeDef[]} */
276
+ /** @type {import("./layout/flexLayout.js").SizeDef[]} */
279
277
  const items = [];
280
278
 
281
279
  // Title
@@ -312,15 +310,14 @@ export default class GridView extends ContainerView {
312
310
 
313
311
  /**
314
312
  * @param {Direction} direction
315
- * @return {import("../utils/layout/flexLayout").SizeDef}
313
+ * @return {import("./layout/flexLayout.js").SizeDef}
316
314
  */
317
315
  #getFlexSize(direction) {
318
316
  let grow = 0;
319
317
  let px = 0;
320
318
 
321
319
  const explicitSize =
322
- (direction == "row" && this.spec.height) ??
323
- (direction == "column" && this.spec.width);
320
+ direction == "row" ? this.spec.height : this.spec.width;
324
321
  if (explicitSize || explicitSize === 0) {
325
322
  return parseSizeDef(explicitSize);
326
323
  }
@@ -396,7 +393,7 @@ export default class GridView extends ContainerView {
396
393
 
397
394
  #getSharedAxisOverhang() {
398
395
  /**
399
- * @param {import("../spec/axis").AxisOrient} orient
396
+ * @param {import("../spec/axis.js").AxisOrient} orient
400
397
  */
401
398
  const getSharedAxisSize = (orient) => {
402
399
  const channel = ORIENT_CHANNELS[orient];
@@ -433,9 +430,9 @@ export default class GridView extends ContainerView {
433
430
  }
434
431
 
435
432
  /**
436
- * @param {import("./renderingContext/viewRenderingContext").default} context
437
- * @param {import("../utils/layout/rectangle").default} coords
438
- * @param {import("../types/rendering").RenderingOptions} [options]
433
+ * @param {import("./renderingContext/viewRenderingContext.js").default} context
434
+ * @param {import("./layout/rectangle.js").default} coords
435
+ * @param {import("../types/rendering.js").RenderingOptions} [options]
439
436
  */
440
437
  // eslint-disable-next-line complexity
441
438
  render(context, coords, options = {}) {
@@ -471,6 +468,10 @@ export default class GridView extends ContainerView {
471
468
  this.#columns ?? Infinity
472
469
  );
473
470
 
471
+ /** @param {number} x */
472
+ const round = (x) =>
473
+ Math.round(x * devicePixelRatio) / devicePixelRatio;
474
+
474
475
  for (const [i, gridChild] of this.#visibleChildren.entries()) {
475
476
  const {
476
477
  view,
@@ -486,31 +487,65 @@ export default class GridView extends ContainerView {
486
487
  columnFlexCoords[this.#getViewSlot("column", col)];
487
488
  const rowLocSize = rowFlexCoords[this.#getViewSlot("row", row)];
488
489
 
489
- const size = view.getSize();
490
+ const viewportSize = view.getViewportSize();
491
+ const viewSize = view.getSize();
492
+
490
493
  const overhang = view.getOverhang();
491
494
 
492
495
  const x = colLocSize.location - overhang.left;
493
496
  const y = rowLocSize.location - overhang.top;
494
497
 
495
- const width =
496
- (size.width.grow ? colLocSize.size : size.width.px) +
497
- overhang.width;
498
- const height =
499
- (size.height.grow ? rowLocSize.size : size.height.px) +
500
- overhang.height;
498
+ // TODO: Optimize for cases where viewportSize and viewSize have equal identity
499
+
500
+ /**
501
+ * @param {FlexDimensions} size
502
+ * @param {"width" | "height"} dimension
503
+ */
504
+ const getLen = (size, dimension) =>
505
+ (size[dimension].grow
506
+ ? (dimension == "width" ? colLocSize : rowLocSize).size
507
+ : size[dimension].px) + overhang[dimension];
501
508
 
502
- const childCoords = new Rectangle(
509
+ const viewportWidth = getLen(viewportSize, "width");
510
+ const viewportHeight = getLen(viewportSize, "height");
511
+ const viewWidth = getLen(viewSize, "width");
512
+ const viewHeight = getLen(viewSize, "height");
513
+
514
+ const hScrollbar = gridChild.scrollbars.horizontal;
515
+ const vScrollbar = gridChild.scrollbars.vertical;
516
+
517
+ const getHScrollOffset = hScrollbar
518
+ ? () => round(hScrollbar.viewportOffset)
519
+ : () => 0;
520
+ const getVScrollOffset = vScrollbar
521
+ ? () => round(vScrollbar.viewportOffset)
522
+ : () => 0;
523
+
524
+ // TODO: Part of the following rendering logic could be moved to GridChild
525
+
526
+ const viewportCoords = new Rectangle(
503
527
  () => coords.x + x,
504
528
  () => coords.y + y,
505
- () => width,
506
- () => height
529
+ () => viewportWidth,
530
+ () => viewportHeight
507
531
  );
508
532
 
509
- gridChild.coords = childCoords;
533
+ const scrollable = view.isScrollable();
534
+
535
+ const viewCoords = scrollable
536
+ ? new Rectangle(
537
+ () => coords.x + x - getHScrollOffset(),
538
+ () => coords.y + y - getVScrollOffset(),
539
+ () => viewWidth,
540
+ () => viewHeight
541
+ )
542
+ : viewportCoords;
543
+
544
+ gridChild.coords = viewportCoords;
510
545
 
511
546
  const clippedChildCoords = options.clipRect
512
- ? childCoords.intersect(options.clipRect)
513
- : childCoords;
547
+ ? viewportCoords.intersect(options.clipRect)
548
+ : viewportCoords;
514
549
 
515
550
  background?.render(context, clippedChildCoords, {
516
551
  ...options,
@@ -518,13 +553,17 @@ export default class GridView extends ContainerView {
518
553
  });
519
554
 
520
555
  for (const gridLineView of Object.values(gridLines)) {
521
- gridLineView.render(context, childCoords, options);
556
+ gridLineView.render(context, viewportCoords, options);
522
557
  }
523
558
 
559
+ const clipped = isClippedChildren(view) || scrollable;
560
+
524
561
  // If clipped, the axes should be drawn on top of the marks (because clipping may not be pixel-perfect)
525
- const clipped = isClippedChildren(view);
526
562
  if (clipped) {
527
- view.render(context, childCoords, options);
563
+ view.render(context, viewCoords, {
564
+ ...options,
565
+ clipRect: clippedChildCoords,
566
+ });
528
567
  }
529
568
 
530
569
  backgroundStroke?.render(context, clippedChildCoords, {
@@ -534,14 +573,66 @@ export default class GridView extends ContainerView {
534
573
 
535
574
  // Independent axes
536
575
  for (const [orient, axisView] of Object.entries(axes)) {
537
- axisView.render(
538
- context,
539
- translateAxisCoords(childCoords, orient, axisView),
540
- options
576
+ const direction =
577
+ orient == "left" || orient == "right"
578
+ ? "vertical"
579
+ : "horizontal";
580
+
581
+ const scrollable = gridChild.scrollbars[direction];
582
+
583
+ // Axes should stick to the viewport edge but move with the view
584
+ // when scrolling.
585
+ const coords = scrollable
586
+ ? viewportCoords.modify(
587
+ direction == "vertical"
588
+ ? {
589
+ y: () => viewCoords.y,
590
+ height: viewHeight,
591
+ }
592
+ : {
593
+ x: () => viewCoords.x,
594
+ width: viewWidth,
595
+ }
596
+ )
597
+ : viewportCoords;
598
+
599
+ const translatedCoords = translateAxisCoords(
600
+ coords,
601
+ orient,
602
+ axisView
541
603
  );
604
+
605
+ let clipRect = options.clipRect;
606
+
607
+ // Scrollable axes must be clipped along the scroll direction.
608
+ if (scrollable) {
609
+ clipRect = translatedCoords.intersect(clipRect).intersect(
610
+ scrollable
611
+ ? viewportCoords.modify(
612
+ // Ugly hack. Need to implement intersectX and intersectY.
613
+ direction == "vertical"
614
+ ? {
615
+ x: -100000,
616
+ width: 200000,
617
+ }
618
+ : {
619
+ y: -100000,
620
+ height: 200000,
621
+ }
622
+ )
623
+ : undefined
624
+ );
625
+ }
626
+
627
+ axisView.render(context, translatedCoords, {
628
+ ...options,
629
+ clipRect,
630
+ });
542
631
  }
543
632
 
544
633
  // Axes shared between children
634
+ // TODO: What if some have scrollable viewports?
635
+ // Should throw an error because cannot have shared axes in such cases.
545
636
  for (const axisView of Object.values(this.#sharedAxes)) {
546
637
  const props = axisView.axisProps;
547
638
  const orient = props.orient;
@@ -554,7 +645,7 @@ export default class GridView extends ContainerView {
554
645
  axisView.render(
555
646
  context,
556
647
  translateAxisCoords(
557
- childCoords.shrink(gridChild.view.getOverhang()),
648
+ viewportCoords.shrink(gridChild.view.getOverhang()),
558
649
  orient,
559
650
  axisView
560
651
  ),
@@ -564,17 +655,22 @@ export default class GridView extends ContainerView {
564
655
  }
565
656
 
566
657
  if (!clipped) {
567
- view.render(context, childCoords, options);
658
+ view.render(context, viewCoords, options);
659
+ }
660
+
661
+ for (const scrollbar of Object.values(gridChild.scrollbars)) {
662
+ scrollbar.updateScrollbar(viewportCoords, viewCoords);
663
+ scrollbar.render(context, coords, options);
568
664
  }
569
665
 
570
- title?.render(context, childCoords, options);
666
+ title?.render(context, viewportCoords, options);
571
667
  }
572
668
 
573
669
  context.popView(this);
574
670
  }
575
671
 
576
672
  /**
577
- * @param {import("../utils/interactionEvent").default} event
673
+ * @param {import("../utils/interactionEvent.js").default} event
578
674
  */
579
675
  propagateInteractionEvent(event) {
580
676
  this.handleInteractionEvent(undefined, event, true);
@@ -586,6 +682,16 @@ export default class GridView extends ContainerView {
586
682
  const pointedChild = this.#visibleChildren.find((gridChild) =>
587
683
  gridChild.coords.containsPoint(event.point.x, event.point.y)
588
684
  );
685
+
686
+ for (const scrollbar of Object.values(pointedChild?.scrollbars ?? {})) {
687
+ if (scrollbar.coords.containsPoint(event.point.x, event.point.y)) {
688
+ scrollbar.propagateInteractionEvent(event);
689
+ if (event.stopped) {
690
+ return;
691
+ }
692
+ }
693
+ }
694
+
589
695
  const pointedView = pointedChild?.view;
590
696
  if (pointedView) {
591
697
  pointedView.propagateInteractionEvent(event);
@@ -617,9 +723,9 @@ export default class GridView extends ContainerView {
617
723
 
618
724
  /**
619
725
  *
620
- * @param {import("../utils/layout/rectangle").default} coords Coordinates
726
+ * @param {import("./layout/rectangle.js").default} coords Coordinates
621
727
  * @param {View} view
622
- * @param {import("./zoom").ZoomEvent} zoomEvent
728
+ * @param {import("./zoom.js").ZoomEvent} zoomEvent
623
729
  */
624
730
  #handleZoom(coords, view, zoomEvent) {
625
731
  for (const [channel, resolutionSet] of Object.entries(
@@ -653,9 +759,9 @@ export default class GridView extends ContainerView {
653
759
  }
654
760
 
655
761
  /**
656
- * @param {import("../spec/channel").Channel} channel
657
- * @param {import("../spec/view").ResolutionTarget} resolutionType
658
- * @returns {import("../spec/view").ResolutionBehavior}
762
+ * @param {import("../spec/channel.js").Channel} channel
763
+ * @param {import("../spec/view.js").ResolutionTarget} resolutionType
764
+ * @returns {import("../spec/view.js").ResolutionBehavior}
659
765
  */
660
766
  getDefaultResolution(channel, resolutionType) {
661
767
  return "independent";
@@ -663,8 +769,8 @@ export default class GridView extends ContainerView {
663
769
  }
664
770
 
665
771
  /**
666
- * @param {import("../spec/view").ViewBackground} viewBackground
667
- * @returns {import("../spec/view").UnitSpec}
772
+ * @param {import("../spec/view.js").ViewBackground} viewBackground
773
+ * @returns {import("../spec/view.js").UnitSpec}
668
774
  */
669
775
  export function createBackground(viewBackground) {
670
776
  if (
@@ -691,8 +797,8 @@ export function createBackground(viewBackground) {
691
797
  }
692
798
 
693
799
  /**
694
- * @param {import("../spec/view").ViewBackground} viewBackground
695
- * @returns {import("../spec/view").UnitSpec}
800
+ * @param {import("../spec/view.js").ViewBackground} viewBackground
801
+ * @returns {import("../spec/view.js").UnitSpec}
696
802
  */
697
803
  export function createBackgroundStroke(viewBackground) {
698
804
  if (
@@ -745,7 +851,7 @@ export function createBackgroundStroke(viewBackground) {
745
851
  * @returns
746
852
  */
747
853
  function getZoomableResolutions(view) {
748
- /** @type {Record<import("../spec/channel").PrimaryPositionalChannel, Set<import("./scaleResolution").default>>} */
854
+ /** @type {Record<import("../spec/channel.js").PrimaryPositionalChannel, Set<import("./scaleResolution.js").default>>} */
749
855
  const resolutions = {
750
856
  x: new Set(),
751
857
  y: new Set(),
@@ -781,8 +887,8 @@ export function isClippedChildren(view) {
781
887
 
782
888
  /**
783
889
  *
784
- * @param {import("../utils/layout/rectangle").default} coords
785
- * @param {import("../spec/axis").AxisOrient} orient
890
+ * @param {import("./layout/rectangle.js").default} coords
891
+ * @param {import("../spec/axis.js").AxisOrient} orient
786
892
  * @param {AxisView} axisView
787
893
  */
788
894
  export function translateAxisCoords(coords, orient, axisView) {
@@ -821,12 +927,15 @@ export class GridChild {
821
927
  /** @type {UnitView} */
822
928
  this.backgroundStroke = undefined;
823
929
 
824
- /** @type {Partial<Record<import("../spec/axis").AxisOrient, AxisView>>} axes */
930
+ /** @type {Partial<Record<import("../spec/axis.js").AxisOrient, AxisView>>} axes */
825
931
  this.axes = {};
826
932
 
827
- /** @type {Partial<Record<import("../spec/axis").AxisOrient, AxisGridView>>} gridLines */
933
+ /** @type {Partial<Record<import("../spec/axis.js").AxisOrient, AxisGridView>>} gridLines */
828
934
  this.gridLines = {};
829
935
 
936
+ /** @type {Partial<Record<ScrollDirection, Scrollbar>>} */
937
+ this.scrollbars = {};
938
+
830
939
  /** @type {UnitView} */
831
940
  this.title = undefined;
832
941
 
@@ -844,10 +953,11 @@ export class GridChild {
844
953
  layoutParent.context,
845
954
  layoutParent,
846
955
  view,
847
- "background" + serial
956
+ "background" + serial,
957
+ {
958
+ blockEncodingInheritance: true,
959
+ }
848
960
  );
849
- // TODO: Make configurable through spec:
850
- this.background.blockEncodingInheritance = true;
851
961
  }
852
962
 
853
963
  const backgroundStrokeSpec = createBackgroundStroke(viewBackground);
@@ -857,10 +967,11 @@ export class GridChild {
857
967
  layoutParent.context,
858
968
  layoutParent,
859
969
  view,
860
- "backgroundStroke" + serial
970
+ "backgroundStroke" + serial,
971
+ {
972
+ blockEncodingInheritance: true,
973
+ }
861
974
  );
862
- // TODO: Make configurable through spec:
863
- this.backgroundStroke.blockEncodingInheritance = true;
864
975
  }
865
976
 
866
977
  const title = createTitle(view.spec.title);
@@ -870,13 +981,23 @@ export class GridChild {
870
981
  layoutParent.context,
871
982
  layoutParent,
872
983
  view,
873
- "title" + serial
984
+ "title" + serial,
985
+ {
986
+ blockEncodingInheritance: true,
987
+ }
874
988
  );
875
- // TODO: Make configurable through spec:
876
- unitView.blockEncodingInheritance = true;
877
989
  this.title = unitView;
878
990
  }
879
991
  }
992
+
993
+ // TODO: More specific getter for this
994
+ if (view.spec.viewportWidth != null) {
995
+ this.scrollbars.horizontal = new Scrollbar(this, "horizontal");
996
+ }
997
+
998
+ if (view.spec.viewportHeight != null) {
999
+ this.scrollbars.vertical = new Scrollbar(this, "vertical");
1000
+ }
880
1001
  }
881
1002
 
882
1003
  *getChildren() {
@@ -892,17 +1013,18 @@ export class GridChild {
892
1013
  yield* Object.values(this.axes);
893
1014
  yield* Object.values(this.gridLines);
894
1015
  yield this.view;
1016
+ yield* Object.values(this.scrollbars);
895
1017
  }
896
1018
 
897
1019
  /**
898
1020
  * Create view decorations, grid lines, axes, etc.
899
1021
  */
900
- createAxes() {
1022
+ async createAxes() {
901
1023
  const { view, axes, gridLines } = this;
902
1024
 
903
1025
  /**
904
- * @param {import("./axisResolution").default} r
905
- * @param {import("../spec/channel").PrimaryPositionalChannel} channel
1026
+ * @param {import("./axisResolution.js").default} r
1027
+ * @param {import("../spec/channel.js").PrimaryPositionalChannel} channel
906
1028
  */
907
1029
  const getAxisPropsWithDefaults = (r, channel) => {
908
1030
  const propsWithoutDefaults = r.getAxisProps();
@@ -942,11 +1064,11 @@ export class GridChild {
942
1064
  };
943
1065
 
944
1066
  /**
945
- * @param {import("./axisResolution").default} r
946
- * @param {import("../spec/channel").PrimaryPositionalChannel} channel
1067
+ * @param {import("./axisResolution.js").default} r
1068
+ * @param {import("../spec/channel.js").PrimaryPositionalChannel} channel
947
1069
  * @param {View} axisParent
948
1070
  */
949
- const createAxis = (r, channel, axisParent) => {
1071
+ const createAxis = async (r, channel, axisParent) => {
950
1072
  const props = getAxisPropsWithDefaults(r, channel);
951
1073
 
952
1074
  if (props) {
@@ -956,37 +1078,41 @@ export class GridChild {
956
1078
  );
957
1079
  }
958
1080
 
959
- axes[props.orient] = new AxisView(
1081
+ const axisView = new AxisView(
960
1082
  props,
961
1083
  r.scaleResolution.type,
962
1084
  this.layoutParent.context,
963
1085
  this.layoutParent,
964
1086
  axisParent
965
1087
  );
1088
+ axes[props.orient] = axisView;
1089
+ await axisView.initializeChildren();
966
1090
  }
967
1091
  };
968
1092
 
969
1093
  /**
970
- * @param {import("./axisResolution").default} r
971
- * @param {import("../spec/channel").PrimaryPositionalChannel} channel
1094
+ * @param {import("./axisResolution.js").default} r
1095
+ * @param {import("../spec/channel.js").PrimaryPositionalChannel} channel
972
1096
  * @param {View} axisParent
973
1097
  */
974
- const createAxisGrid = (r, channel, axisParent) => {
1098
+ const createAxisGrid = async (r, channel, axisParent) => {
975
1099
  const props = getAxisPropsWithDefaults(r, channel);
976
1100
 
977
1101
  if (props && (props.grid || props.chromGrid)) {
978
- gridLines[props.orient] = new AxisGridView(
1102
+ const axisGridView = new AxisGridView(
979
1103
  props,
980
1104
  r.scaleResolution.type,
981
1105
  this.layoutParent.context,
982
1106
  this.layoutParent,
983
1107
  axisParent
984
1108
  );
1109
+ gridLines[props.orient] = axisGridView;
1110
+ await axisGridView.initializeChildren();
985
1111
  }
986
1112
  };
987
1113
 
988
1114
  // Handle children that have caught axis resolutions. Create axes for them.
989
- for (const channel of /** @type {import("../spec/channel").PrimaryPositionalChannel[]} */ ([
1115
+ for (const channel of /** @type {import("../spec/channel.js").PrimaryPositionalChannel[]} */ ([
990
1116
  "x",
991
1117
  "y",
992
1118
  ])) {
@@ -996,13 +1122,13 @@ export class GridChild {
996
1122
  continue;
997
1123
  }
998
1124
 
999
- createAxis(r, channel, view);
1125
+ await createAxis(r, channel, view);
1000
1126
  }
1001
1127
  }
1002
1128
 
1003
1129
  // Handle gridlines of children. Note: children's axis resolution may be caught by
1004
1130
  // this view or some of this view's ancestors.
1005
- for (const channel of /** @type {import("../spec/channel").PrimaryPositionalChannel[]} */ ([
1131
+ for (const channel of /** @type {import("../spec/channel.js").PrimaryPositionalChannel[]} */ ([
1006
1132
  "x",
1007
1133
  "y",
1008
1134
  ])) {
@@ -1014,32 +1140,32 @@ export class GridChild {
1014
1140
 
1015
1141
  // TODO: Optimization: the same grid view could be reused for all children
1016
1142
  // because they share the axis and scale resolutions anyway.
1017
- createAxisGrid(r, channel, view);
1143
+ await createAxisGrid(r, channel, view);
1018
1144
  }
1019
1145
  }
1020
1146
 
1021
1147
  // Handle LayerView's possible independent axes
1022
1148
  if (view instanceof LayerView) {
1023
1149
  // First create axes that have an orient preference
1024
- for (const layerChild of view.children) {
1150
+ for (const layerChild of view) {
1025
1151
  for (const [channel, r] of Object.entries(
1026
1152
  layerChild.resolutions.axis
1027
1153
  )) {
1028
1154
  const props = r.getAxisProps();
1029
1155
  if (props && props.orient) {
1030
- createAxis(r, channel, layerChild);
1156
+ await createAxis(r, channel, layerChild);
1031
1157
  }
1032
1158
  }
1033
1159
  }
1034
1160
 
1035
1161
  // Then create axes in a priority order
1036
- for (const layerChild of view.children) {
1162
+ for (const layerChild of view) {
1037
1163
  for (const [channel, r] of Object.entries(
1038
1164
  layerChild.resolutions.axis
1039
1165
  )) {
1040
1166
  const props = r.getAxisProps();
1041
1167
  if (props && !props.orient) {
1042
- createAxis(r, channel, layerChild);
1168
+ await createAxis(r, channel, layerChild);
1043
1169
  }
1044
1170
  }
1045
1171
  }
@@ -1059,7 +1185,7 @@ export class GridChild {
1059
1185
 
1060
1186
  getOverhang() {
1061
1187
  const calculate = (
1062
- /** @type {import("../spec/axis").AxisOrient} */ orient
1188
+ /** @type {import("../spec/axis.js").AxisOrient} */ orient
1063
1189
  ) => {
1064
1190
  const axisView = this.axes[orient];
1065
1191
  return axisView
@@ -1084,3 +1210,164 @@ export class GridChild {
1084
1210
  return this.getOverhang().add(this.view.getPadding());
1085
1211
  }
1086
1212
  }
1213
+
1214
+ class Scrollbar extends UnitView {
1215
+ /**
1216
+ * @param {GridChild} gridChild
1217
+ * @param {ScrollDirection} scrollDirection
1218
+ */
1219
+ constructor(gridChild, scrollDirection) {
1220
+ // TODO: Configurable
1221
+ const config = {
1222
+ scrollbarSize: 8,
1223
+ scrollbarPadding: 2,
1224
+ // TODO: inside/outside view
1225
+ };
1226
+
1227
+ super(
1228
+ {
1229
+ data: { values: [{}] },
1230
+ mark: {
1231
+ type: "rect",
1232
+ fill: "#b0b0b0",
1233
+ fillOpacity: 0.6,
1234
+ stroke: "white",
1235
+ strokeWidth: 1,
1236
+ strokeOpacity: 1,
1237
+ cornerRadius: 5,
1238
+ clip: false,
1239
+ },
1240
+ configurableVisibility: false,
1241
+ },
1242
+ gridChild.layoutParent.context,
1243
+ gridChild.layoutParent,
1244
+ gridChild.view,
1245
+ "scrollbar-" + scrollDirection, // TODO: Serial
1246
+ {
1247
+ blockEncodingInheritance: true,
1248
+ }
1249
+ );
1250
+
1251
+ this.config = config;
1252
+ this.scrollDirection = scrollDirection;
1253
+
1254
+ // This is the actual state of the scrollbar. It's better to keep track of
1255
+ // the viewport offset rather than the scrollbar offset because the former
1256
+ // is more stable when the viewport size changes.
1257
+ this.viewportOffset = 0;
1258
+
1259
+ this.maxScrollOffset = 0;
1260
+ this.scrollbarCoords = Rectangle.ZERO;
1261
+
1262
+ this.addInteractionEventListener("mousedown", (coords, event) => {
1263
+ event.stopPropagation();
1264
+
1265
+ if (this.maxScrollOffset <= 0) {
1266
+ return;
1267
+ }
1268
+
1269
+ const getMouseOffset = (/** @type {MouseEvent} */ mouseEvent) =>
1270
+ scrollDirection == "vertical"
1271
+ ? mouseEvent.clientY
1272
+ : mouseEvent.clientX;
1273
+
1274
+ const mouseEvent = /** @type {MouseEvent} */ (event.uiEvent);
1275
+ mouseEvent.preventDefault();
1276
+
1277
+ const initialScrollOffset = this.getScrollOffset();
1278
+ const initialOffset = getMouseOffset(mouseEvent);
1279
+
1280
+ const onMousemove = /** @param {MouseEvent} moveEvent */ (
1281
+ moveEvent
1282
+ ) => {
1283
+ const scrollOffset = clamp(
1284
+ getMouseOffset(moveEvent) -
1285
+ initialOffset +
1286
+ initialScrollOffset,
1287
+ 0,
1288
+ this.maxScrollOffset
1289
+ );
1290
+
1291
+ this.viewportOffset =
1292
+ (scrollOffset / this.maxScrollOffset) *
1293
+ this.maxViewportOffset;
1294
+ this.context.animator.requestRender();
1295
+ };
1296
+
1297
+ const onMouseup = () => {
1298
+ document.removeEventListener("mousemove", onMousemove);
1299
+ document.removeEventListener("mouseup", onMouseup);
1300
+ };
1301
+
1302
+ document.addEventListener("mouseup", onMouseup, false);
1303
+ document.addEventListener("mousemove", onMousemove, false);
1304
+ });
1305
+ }
1306
+
1307
+ getScrollOffset() {
1308
+ return (
1309
+ (this.viewportOffset / this.maxViewportOffset) *
1310
+ this.maxScrollOffset
1311
+ );
1312
+ }
1313
+
1314
+ /**
1315
+ * @param {import("./renderingContext/viewRenderingContext.js").default} context
1316
+ * @param {import("./layout/rectangle.js").default} coords
1317
+ * @param {import("../types/rendering.js").RenderingOptions} [options]
1318
+ */
1319
+ render(context, coords, options) {
1320
+ super.render(context, this.scrollbarCoords, options);
1321
+ }
1322
+
1323
+ /**
1324
+ *
1325
+ * @param {Rectangle} viewportCoords
1326
+ * @param {Rectangle} coords
1327
+ */
1328
+ updateScrollbar(viewportCoords, coords) {
1329
+ const sPad = this.config.scrollbarPadding;
1330
+ const sSize = this.config.scrollbarSize;
1331
+
1332
+ const dimension =
1333
+ this.scrollDirection == "horizontal" ? "width" : "height";
1334
+
1335
+ const visibleFraction = Math.min(
1336
+ 1,
1337
+ viewportCoords[dimension] / coords[dimension]
1338
+ );
1339
+ const maxScrollLength = viewportCoords[dimension] - 2 * sPad;
1340
+ const scrollLength = visibleFraction * maxScrollLength;
1341
+
1342
+ this.maxScrollOffset = maxScrollLength - scrollLength;
1343
+ this.maxViewportOffset = coords[dimension] - viewportCoords[dimension];
1344
+ this.viewportOffset = clamp(
1345
+ this.viewportOffset,
1346
+ 0,
1347
+ this.maxViewportOffset
1348
+ );
1349
+
1350
+ this.scrollbarCoords =
1351
+ this.scrollDirection == "vertical"
1352
+ ? new Rectangle(
1353
+ () =>
1354
+ viewportCoords.x +
1355
+ viewportCoords.width -
1356
+ sSize -
1357
+ sPad,
1358
+ () => viewportCoords.y + sPad + this.getScrollOffset(),
1359
+ () => sSize,
1360
+ () => scrollLength
1361
+ )
1362
+ : new Rectangle(
1363
+ () => viewportCoords.x + sPad + this.getScrollOffset(),
1364
+ () =>
1365
+ viewportCoords.y +
1366
+ viewportCoords.height -
1367
+ sSize -
1368
+ sPad,
1369
+ () => scrollLength,
1370
+ () => sSize
1371
+ );
1372
+ }
1373
+ }