@genome-spy/core 0.73.0 → 0.75.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 (392) hide show
  1. package/dist/bundle/AbortablePromiseCache-3gHJdF3E.js +96 -0
  2. package/dist/bundle/browser-BTgw5ieH.js +126 -0
  3. package/dist/bundle/chunk-DmhlhrBa.js +11 -0
  4. package/dist/bundle/esm-BDFRLEuD.js +1248 -0
  5. package/dist/bundle/esm-BygJiwh0.js +573 -0
  6. package/dist/bundle/esm-CGX-qz1d.js +155 -0
  7. package/dist/bundle/esm-CgfVIRJ-.js +121 -0
  8. package/dist/bundle/esm-CuMSzCHy.js +298 -0
  9. package/dist/bundle/esm-DMXpJXM4.js +369 -0
  10. package/dist/bundle/esm-DQiq2Zhd.js +1426 -0
  11. package/dist/bundle/esm-DtE8VqAv.js +1015 -0
  12. package/dist/bundle/esm-sIoQYZ21.js +461 -0
  13. package/dist/bundle/index.es.js +21266 -25938
  14. package/dist/bundle/index.js +367 -383
  15. package/dist/bundle/parquetRead-DG_-F5j5.js +1609 -0
  16. package/dist/schema.json +13421 -7210
  17. package/dist/src/config/axisConfig.d.ts +16 -0
  18. package/dist/src/config/axisConfig.d.ts.map +1 -0
  19. package/dist/src/config/axisConfig.js +84 -0
  20. package/dist/src/config/defaultConfig.d.ts +3 -0
  21. package/dist/src/config/defaultConfig.d.ts.map +1 -0
  22. package/dist/src/config/defaultConfig.js +38 -0
  23. package/dist/src/config/defaults/axisDefaults.d.ts +5 -0
  24. package/dist/src/config/defaults/axisDefaults.d.ts.map +1 -0
  25. package/dist/src/config/defaults/axisDefaults.js +72 -0
  26. package/dist/src/config/defaults/markDefaults.d.ts +15 -0
  27. package/dist/src/config/defaults/markDefaults.d.ts.map +1 -0
  28. package/dist/src/config/defaults/markDefaults.js +121 -0
  29. package/dist/src/config/defaults/scaleDefaults.d.ts +5 -0
  30. package/dist/src/config/defaults/scaleDefaults.d.ts.map +1 -0
  31. package/dist/src/config/defaults/scaleDefaults.js +18 -0
  32. package/dist/src/config/defaults/titleDefaults.d.ts +5 -0
  33. package/dist/src/config/defaults/titleDefaults.d.ts.map +1 -0
  34. package/dist/src/config/defaults/titleDefaults.js +47 -0
  35. package/dist/src/config/defaults/viewDefaults.d.ts +3 -0
  36. package/dist/src/config/defaults/viewDefaults.d.ts.map +1 -0
  37. package/dist/src/config/defaults/viewDefaults.js +2 -0
  38. package/dist/src/config/markConfig.d.ts +8 -0
  39. package/dist/src/config/markConfig.d.ts.map +1 -0
  40. package/dist/src/config/markConfig.js +27 -0
  41. package/dist/src/config/mergeConfig.d.ts +8 -0
  42. package/dist/src/config/mergeConfig.d.ts.map +1 -0
  43. package/dist/src/config/mergeConfig.js +81 -0
  44. package/dist/src/config/resolveConfig.d.ts +22 -0
  45. package/dist/src/config/resolveConfig.d.ts.map +1 -0
  46. package/dist/src/config/resolveConfig.js +32 -0
  47. package/dist/src/config/scaleConfig.d.ts +40 -0
  48. package/dist/src/config/scaleConfig.d.ts.map +1 -0
  49. package/dist/src/config/scaleConfig.js +220 -0
  50. package/dist/src/config/styleUtils.d.ts +6 -0
  51. package/dist/src/config/styleUtils.d.ts.map +1 -0
  52. package/dist/src/config/styleUtils.js +10 -0
  53. package/dist/src/config/themes.d.ts +15 -0
  54. package/dist/src/config/themes.d.ts.map +1 -0
  55. package/dist/src/config/themes.js +293 -0
  56. package/dist/src/config/titleConfig.d.ts +12 -0
  57. package/dist/src/config/titleConfig.d.ts.map +1 -0
  58. package/dist/src/config/titleConfig.js +42 -0
  59. package/dist/src/config/viewConfig.d.ts +7 -0
  60. package/dist/src/config/viewConfig.d.ts.map +1 -0
  61. package/dist/src/config/viewConfig.js +29 -0
  62. package/dist/src/data/flowNode.d.ts +22 -1
  63. package/dist/src/data/flowNode.d.ts.map +1 -1
  64. package/dist/src/data/flowNode.js +37 -1
  65. package/dist/src/data/formats/bed.d.ts.map +1 -1
  66. package/dist/src/data/formats/bed.js +6 -1
  67. package/dist/src/data/formats/bedpe.d.ts.map +1 -1
  68. package/dist/src/data/formats/bedpe.js +4 -0
  69. package/dist/src/data/formats/fasta.d.ts.map +1 -1
  70. package/dist/src/data/formats/fasta.js +4 -0
  71. package/dist/src/data/formats/parquet.d.ts.map +1 -1
  72. package/dist/src/data/formats/parquet.js +4 -0
  73. package/dist/src/data/sources/dataSourceFactory.d.ts +2 -13
  74. package/dist/src/data/sources/dataSourceFactory.d.ts.map +1 -1
  75. package/dist/src/data/sources/dataSourceFactory.js +5 -141
  76. package/dist/src/data/sources/dataUtils.d.ts +25 -0
  77. package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
  78. package/dist/src/data/sources/dataUtils.js +23 -0
  79. package/dist/src/data/sources/inlineSource.js +2 -2
  80. package/dist/src/data/sources/lazy/axisGenomeSource.d.ts.map +1 -1
  81. package/dist/src/data/sources/lazy/axisGenomeSource.js +11 -0
  82. package/dist/src/data/sources/lazy/axisTickSource.d.ts +1 -1
  83. package/dist/src/data/sources/lazy/axisTickSource.d.ts.map +1 -1
  84. package/dist/src/data/sources/lazy/axisTickSource.js +19 -8
  85. package/dist/src/data/sources/lazy/bamSource.d.ts.map +1 -1
  86. package/dist/src/data/sources/lazy/bamSource.js +11 -0
  87. package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
  88. package/dist/src/data/sources/lazy/bigBedSource.js +12 -1
  89. package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
  90. package/dist/src/data/sources/lazy/bigWigSource.js +11 -0
  91. package/dist/src/data/sources/lazy/gff3Source.d.ts.map +1 -1
  92. package/dist/src/data/sources/lazy/gff3Source.js +12 -1
  93. package/dist/src/data/sources/lazy/indexedFastaSource.d.ts.map +1 -1
  94. package/dist/src/data/sources/lazy/indexedFastaSource.js +11 -0
  95. package/dist/src/data/sources/lazy/lazyDataSourceRegistry.d.ts +27 -0
  96. package/dist/src/data/sources/lazy/lazyDataSourceRegistry.d.ts.map +1 -0
  97. package/dist/src/data/sources/lazy/lazyDataSourceRegistry.js +65 -0
  98. package/dist/src/data/sources/lazy/registerBuiltInLazySources.d.ts +2 -0
  99. package/dist/src/data/sources/lazy/registerBuiltInLazySources.d.ts.map +1 -0
  100. package/dist/src/data/sources/lazy/registerBuiltInLazySources.js +8 -0
  101. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  102. package/dist/src/data/sources/lazy/singleAxisLazySource.js +11 -2
  103. package/dist/src/data/sources/lazy/vcfSource.d.ts.map +1 -1
  104. package/dist/src/data/sources/lazy/vcfSource.js +11 -0
  105. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  106. package/dist/src/data/sources/urlSource.js +13 -5
  107. package/dist/src/data/transforms/aggregate.d.ts +1 -0
  108. package/dist/src/data/transforms/aggregate.d.ts.map +1 -1
  109. package/dist/src/data/transforms/aggregate.js +30 -8
  110. package/dist/src/data/transforms/aggregateOps.d.ts.map +1 -1
  111. package/dist/src/data/transforms/aggregateOps.js +12 -1
  112. package/dist/src/data/transforms/coverage.js +2 -2
  113. package/dist/src/data/transforms/filter.js +1 -1
  114. package/dist/src/data/transforms/filterScoredLabels.d.ts +6 -0
  115. package/dist/src/data/transforms/filterScoredLabels.d.ts.map +1 -1
  116. package/dist/src/data/transforms/filterScoredLabels.js +9 -0
  117. package/dist/src/data/transforms/measureText.d.ts +1 -0
  118. package/dist/src/data/transforms/measureText.d.ts.map +1 -1
  119. package/dist/src/data/transforms/measureText.js +14 -5
  120. package/dist/src/data/transforms/pileup.d.ts.map +1 -1
  121. package/dist/src/data/transforms/pileup.js +1 -2
  122. package/dist/src/data/transforms/regexFold.d.ts.map +1 -1
  123. package/dist/src/data/transforms/regexFold.js +0 -1
  124. package/dist/src/embedFactory.d.ts +13 -0
  125. package/dist/src/embedFactory.d.ts.map +1 -0
  126. package/dist/src/embedFactory.js +127 -0
  127. package/dist/src/encoder/accessor.d.ts +3 -12
  128. package/dist/src/encoder/accessor.d.ts.map +1 -1
  129. package/dist/src/encoder/accessor.js +10 -65
  130. package/dist/src/encoder/encoder.d.ts +51 -8
  131. package/dist/src/encoder/encoder.d.ts.map +1 -1
  132. package/dist/src/encoder/encoder.js +179 -55
  133. package/dist/src/fonts/bmFontManager.js +1 -1
  134. package/dist/src/full.d.ts +2 -0
  135. package/dist/src/full.d.ts.map +1 -0
  136. package/dist/src/full.js +2 -0
  137. package/dist/src/genome/genome.d.ts +8 -0
  138. package/dist/src/genome/genome.d.ts.map +1 -1
  139. package/dist/src/genome/genome.js +16 -2
  140. package/dist/src/genome/genomeStore.js +1 -1
  141. package/dist/src/genome/rootGenomeConfig.d.ts.map +1 -1
  142. package/dist/src/genome/rootGenomeConfig.js +6 -2
  143. package/dist/src/genome/scaleLocus.d.ts.map +1 -1
  144. package/dist/src/genome/scaleLocus.js +31 -7
  145. package/dist/src/genomeSpy/cursorManager.d.ts +69 -0
  146. package/dist/src/genomeSpy/cursorManager.d.ts.map +1 -0
  147. package/dist/src/genomeSpy/cursorManager.js +131 -0
  148. package/dist/src/genomeSpy/headlessBootstrap.d.ts +113 -0
  149. package/dist/src/genomeSpy/headlessBootstrap.d.ts.map +1 -0
  150. package/dist/src/genomeSpy/headlessBootstrap.js +246 -0
  151. package/dist/src/genomeSpy/interactionController.d.ts +5 -0
  152. package/dist/src/genomeSpy/interactionController.d.ts.map +1 -1
  153. package/dist/src/genomeSpy/interactionController.js +292 -59
  154. package/dist/src/genomeSpy/interactionDispatcher.d.ts +50 -0
  155. package/dist/src/genomeSpy/interactionDispatcher.d.ts.map +1 -0
  156. package/dist/src/genomeSpy/interactionDispatcher.js +203 -0
  157. package/dist/src/genomeSpy/viewContextFactory.d.ts +4 -2
  158. package/dist/src/genomeSpy/viewContextFactory.d.ts.map +1 -1
  159. package/dist/src/genomeSpy/viewContextFactory.js +12 -4
  160. package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -1
  161. package/dist/src/genomeSpy/viewDataInit.js +7 -3
  162. package/dist/src/genomeSpy.d.ts +1 -124
  163. package/dist/src/genomeSpy.d.ts.map +1 -1
  164. package/dist/src/genomeSpy.js +7 -688
  165. package/dist/src/genomeSpyBase.d.ts +133 -0
  166. package/dist/src/genomeSpyBase.d.ts.map +1 -0
  167. package/dist/src/genomeSpyBase.js +719 -0
  168. package/dist/src/gl/arrayBuilder.d.ts.map +1 -1
  169. package/dist/src/gl/arrayBuilder.js +0 -3
  170. package/dist/src/gl/colorUtils.d.ts.map +1 -1
  171. package/dist/src/gl/colorUtils.js +3 -0
  172. package/dist/src/gl/dataToVertices.d.ts +12 -14
  173. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  174. package/dist/src/gl/dataToVertices.js +121 -95
  175. package/dist/src/gl/glslScaleGenerator.d.ts +5 -2
  176. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
  177. package/dist/src/gl/glslScaleGenerator.js +15 -15
  178. package/dist/src/gl/vertexRangeIndex.d.ts +23 -0
  179. package/dist/src/gl/vertexRangeIndex.d.ts.map +1 -0
  180. package/dist/src/gl/vertexRangeIndex.js +150 -0
  181. package/dist/src/index.d.ts +3 -9
  182. package/dist/src/index.d.ts.map +1 -1
  183. package/dist/src/index.js +5 -114
  184. package/dist/src/marks/__snapshots__/shaderSnapshot.test.js.snap +4462 -0
  185. package/dist/src/marks/link.d.ts.map +1 -1
  186. package/dist/src/marks/link.js +0 -23
  187. package/dist/src/marks/mark.d.ts +8 -1
  188. package/dist/src/marks/mark.d.ts.map +1 -1
  189. package/dist/src/marks/mark.js +61 -20
  190. package/dist/src/marks/markUtils.d.ts +18 -1
  191. package/dist/src/marks/markUtils.d.ts.map +1 -1
  192. package/dist/src/marks/markUtils.js +52 -4
  193. package/dist/src/marks/point.d.ts.map +1 -1
  194. package/dist/src/marks/point.js +6 -26
  195. package/dist/src/marks/rect.d.ts.map +1 -1
  196. package/dist/src/marks/rect.js +13 -21
  197. package/dist/src/marks/rule.d.ts +7 -2
  198. package/dist/src/marks/rule.d.ts.map +1 -1
  199. package/dist/src/marks/rule.js +125 -16
  200. package/dist/src/marks/text.d.ts.map +1 -1
  201. package/dist/src/marks/text.js +5 -47
  202. package/dist/src/minimal.d.ts +8 -0
  203. package/dist/src/minimal.d.ts.map +1 -0
  204. package/dist/src/minimal.js +21 -0
  205. package/dist/src/paramRuntime/expressionCompiler.d.ts +2 -1
  206. package/dist/src/paramRuntime/expressionCompiler.d.ts.map +1 -1
  207. package/dist/src/paramRuntime/expressionCompiler.js +3 -2
  208. package/dist/src/paramRuntime/expressionRef.d.ts +4 -1
  209. package/dist/src/paramRuntime/expressionRef.d.ts.map +1 -1
  210. package/dist/src/paramRuntime/expressionRef.js +10 -3
  211. package/dist/src/paramRuntime/graphRuntime.d.ts.map +1 -1
  212. package/dist/src/paramRuntime/graphRuntime.js +15 -6
  213. package/dist/src/paramRuntime/paramRuntime.d.ts +8 -2
  214. package/dist/src/paramRuntime/paramRuntime.d.ts.map +1 -1
  215. package/dist/src/paramRuntime/paramRuntime.js +10 -5
  216. package/dist/src/paramRuntime/types.d.ts +1 -0
  217. package/dist/src/paramRuntime/types.d.ts.map +1 -1
  218. package/dist/src/paramRuntime/types.js +1 -0
  219. package/dist/src/paramRuntime/viewParamRuntime.d.ts +24 -4
  220. package/dist/src/paramRuntime/viewParamRuntime.d.ts.map +1 -1
  221. package/dist/src/paramRuntime/viewParamRuntime.js +52 -6
  222. package/dist/src/scale/scale.d.ts.map +1 -1
  223. package/dist/src/scale/scale.js +14 -7
  224. package/dist/src/scales/axisResolution.d.ts.map +1 -1
  225. package/dist/src/scales/axisResolution.js +9 -5
  226. package/dist/src/scales/domainPlanner.d.ts +82 -16
  227. package/dist/src/scales/domainPlanner.d.ts.map +1 -1
  228. package/dist/src/scales/domainPlanner.js +364 -131
  229. package/dist/src/scales/indexLikeDomainUtils.d.ts +29 -0
  230. package/dist/src/scales/indexLikeDomainUtils.d.ts.map +1 -0
  231. package/dist/src/scales/indexLikeDomainUtils.js +67 -0
  232. package/dist/src/scales/resolutionMemberOrder.d.ts +15 -0
  233. package/dist/src/scales/resolutionMemberOrder.d.ts.map +1 -0
  234. package/dist/src/scales/resolutionMemberOrder.js +22 -0
  235. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
  236. package/dist/src/scales/scaleInstanceManager.js +7 -2
  237. package/dist/src/scales/scaleInteractionController.d.ts.map +1 -1
  238. package/dist/src/scales/scaleInteractionController.js +43 -4
  239. package/dist/src/scales/scalePropsResolver.d.ts +5 -3
  240. package/dist/src/scales/scalePropsResolver.d.ts.map +1 -1
  241. package/dist/src/scales/scalePropsResolver.js +108 -8
  242. package/dist/src/scales/scaleResolution.d.ts +35 -1
  243. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  244. package/dist/src/scales/scaleResolution.js +381 -66
  245. package/dist/src/scales/scaleResolutionTestUtils.d.ts.map +1 -1
  246. package/dist/src/scales/scaleResolutionTestUtils.js +6 -2
  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 +30 -0
  250. package/dist/src/scales/selectionDomainUtils.d.ts.map +1 -1
  251. package/dist/src/scales/selectionDomainUtils.js +116 -1
  252. package/dist/src/screenshotExport.d.ts +23 -0
  253. package/dist/src/screenshotExport.d.ts.map +1 -0
  254. package/dist/src/screenshotExport.js +44 -0
  255. package/dist/src/screenshotHarness.d.ts.map +1 -1
  256. package/dist/src/screenshotHarness.js +26 -25
  257. package/dist/src/spec/axis.d.ts +43 -32
  258. package/dist/src/spec/channel.d.ts +19 -13
  259. package/dist/src/spec/config.d.ts +264 -0
  260. package/dist/src/spec/data.d.ts +19 -0
  261. package/dist/src/spec/decoration.d.ts +51 -0
  262. package/dist/src/spec/exampleFiles.d.ts +12 -0
  263. package/dist/src/spec/exampleFiles.d.ts.map +1 -0
  264. package/dist/src/spec/exampleFiles.js +52 -0
  265. package/dist/src/spec/font.d.ts +1 -1
  266. package/dist/src/spec/mark.d.ts +97 -13
  267. package/dist/src/spec/parameter.d.ts +30 -10
  268. package/dist/src/spec/root.d.ts +14 -0
  269. package/dist/src/spec/scale.d.ts +31 -14
  270. package/dist/src/spec/title.d.ts +13 -2
  271. package/dist/src/spec/tooltip.d.ts +1 -1
  272. package/dist/src/spec/transform.d.ts +39 -4
  273. package/dist/src/spec/view.d.ts +67 -19
  274. package/dist/src/styles/genome-spy.css +55 -55
  275. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  276. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  277. package/dist/src/styles/genome-spy.css.js +23 -22
  278. package/dist/src/testSetup.d.ts +2 -0
  279. package/dist/src/testSetup.d.ts.map +1 -0
  280. package/dist/src/testSetup.js +5 -0
  281. package/dist/src/tooltip/dataTooltipHandler.js +8 -2
  282. package/dist/src/tooltip/tooltipContext.d.ts.map +1 -1
  283. package/dist/src/tooltip/tooltipContext.js +3 -2
  284. package/dist/src/types/embedApi.d.ts +7 -0
  285. package/dist/src/types/encoder.d.ts +17 -15
  286. package/dist/src/types/scaleResolutionApi.d.ts +20 -0
  287. package/dist/src/types/viewContext.d.ts +23 -1
  288. package/dist/src/utils/expression.d.ts +18 -10
  289. package/dist/src/utils/expression.d.ts.map +1 -1
  290. package/dist/src/utils/expression.js +354 -19
  291. package/dist/src/utils/field.d.ts.map +1 -1
  292. package/dist/src/utils/field.js +0 -1
  293. package/dist/src/utils/inertia.d.ts.map +1 -1
  294. package/dist/src/utils/inertia.js +0 -1
  295. package/dist/src/utils/inputBinding.d.ts +1 -1
  296. package/dist/src/utils/interaction.d.ts +109 -0
  297. package/dist/src/utils/interaction.d.ts.map +1 -0
  298. package/dist/src/utils/interaction.js +200 -0
  299. package/dist/src/utils/interactionEvent.d.ts +21 -42
  300. package/dist/src/utils/interactionEvent.d.ts.map +1 -1
  301. package/dist/src/utils/interactionEvent.js +43 -66
  302. package/dist/src/utils/kWayMerge.js +1 -1
  303. package/dist/src/utils/mergeObjects.d.ts.map +1 -1
  304. package/dist/src/utils/mergeObjects.js +0 -2
  305. package/dist/src/utils/radixSort.d.ts.map +1 -1
  306. package/dist/src/utils/radixSort.js +0 -2
  307. package/dist/src/utils/throttle.d.ts.map +1 -1
  308. package/dist/src/utils/throttle.js +0 -2
  309. package/dist/src/utils/ui/tooltip.d.ts +1 -0
  310. package/dist/src/utils/ui/tooltip.d.ts.map +1 -1
  311. package/dist/src/utils/ui/tooltip.js +1 -0
  312. package/dist/src/utils/url.js +1 -1
  313. package/dist/src/view/axisGridView.d.ts +1 -1
  314. package/dist/src/view/axisGridView.d.ts.map +1 -1
  315. package/dist/src/view/axisGridView.js +2 -47
  316. package/dist/src/view/axisView.d.ts +2 -3
  317. package/dist/src/view/axisView.d.ts.map +1 -1
  318. package/dist/src/view/axisView.js +251 -106
  319. package/dist/src/view/concatView.d.ts +2 -1
  320. package/dist/src/view/concatView.d.ts.map +1 -1
  321. package/dist/src/view/concatView.js +4 -2
  322. package/dist/src/view/containerMutationHelper.d.ts +3 -0
  323. package/dist/src/view/containerMutationHelper.d.ts.map +1 -1
  324. package/dist/src/view/containerMutationHelper.js +4 -1
  325. package/dist/src/view/facetView.d.ts +1 -1
  326. package/dist/src/view/facetView.js +3 -3
  327. package/dist/src/view/flowBuilder.d.ts +1 -1
  328. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  329. package/dist/src/view/flowBuilder.js +13 -9
  330. package/dist/src/view/gridView/gridChild.d.ts +6 -0
  331. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  332. package/dist/src/view/gridView/gridChild.js +72 -43
  333. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  334. package/dist/src/view/gridView/gridView.js +255 -101
  335. package/dist/src/view/gridView/keyboardZoomController.d.ts +2 -2
  336. package/dist/src/view/gridView/keyboardZoomController.d.ts.map +1 -1
  337. package/dist/src/view/gridView/keyboardZoomController.js +1 -1
  338. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  339. package/dist/src/view/gridView/scrollbar.js +4 -2
  340. package/dist/src/view/gridView/selectionRect.d.ts +4 -0
  341. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  342. package/dist/src/view/gridView/selectionRect.js +20 -1
  343. package/dist/src/view/gridView/separatorView.d.ts +1 -0
  344. package/dist/src/view/gridView/separatorView.d.ts.map +1 -1
  345. package/dist/src/view/gridView/separatorView.js +9 -0
  346. package/dist/src/view/interactionRouting.d.ts +20 -0
  347. package/dist/src/view/interactionRouting.d.ts.map +1 -0
  348. package/dist/src/view/interactionRouting.js +53 -0
  349. package/dist/src/view/layerView.d.ts.map +1 -1
  350. package/dist/src/view/layerView.js +12 -9
  351. package/dist/src/view/layout/grid.js +1 -1
  352. package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts.map +1 -1
  353. package/dist/src/view/renderingContext/bufferedViewRenderingContext.js +0 -2
  354. package/dist/src/view/resolutionPlanner.d.ts +9 -0
  355. package/dist/src/view/resolutionPlanner.d.ts.map +1 -0
  356. package/dist/src/view/resolutionPlanner.js +302 -0
  357. package/dist/src/view/testUtils.d.ts +17 -3
  358. package/dist/src/view/testUtils.d.ts.map +1 -1
  359. package/dist/src/view/testUtils.js +62 -69
  360. package/dist/src/view/title.d.ts +8 -1
  361. package/dist/src/view/title.d.ts.map +1 -1
  362. package/dist/src/view/title.js +66 -76
  363. package/dist/src/view/unitView.d.ts +1 -1
  364. package/dist/src/view/unitView.d.ts.map +1 -1
  365. package/dist/src/view/unitView.js +72 -169
  366. package/dist/src/view/view.d.ts +76 -30
  367. package/dist/src/view/view.d.ts.map +1 -1
  368. package/dist/src/view/view.js +138 -48
  369. package/dist/src/view/viewFactory.d.ts +11 -3
  370. package/dist/src/view/viewFactory.d.ts.map +1 -1
  371. package/dist/src/view/viewFactory.js +37 -11
  372. package/dist/src/view/viewUtils.d.ts.map +1 -1
  373. package/dist/src/view/viewUtils.js +41 -5
  374. package/dist/src/view/zoom.d.ts +2 -2
  375. package/dist/src/view/zoom.d.ts.map +1 -1
  376. package/dist/src/view/zoom.js +21 -23
  377. package/package.json +18 -10
  378. package/dist/bundle/AbortablePromiseCache-Dj0vzLnp.js +0 -149
  379. package/dist/bundle/browser-0iNU5Wit.js +0 -138
  380. package/dist/bundle/index-BYsZN7b0.js +0 -1597
  381. package/dist/bundle/index-C3kClAEN.js +0 -1771
  382. package/dist/bundle/index-C7wOh6y1.js +0 -657
  383. package/dist/bundle/index-CRaQAuki.js +0 -326
  384. package/dist/bundle/index-D9v1PCj9.js +0 -507
  385. package/dist/bundle/index-GDOuv_D5.js +0 -266
  386. package/dist/bundle/index-Gt44EOIH.js +0 -628
  387. package/dist/bundle/inflate-GtwLkvSP.js +0 -1048
  388. package/dist/bundle/parquetRead-BnAGCa4_.js +0 -1663
  389. package/dist/bundle/unzip-Bac01w6X.js +0 -1492
  390. package/dist/src/config/scaleDefaults.d.ts +0 -8
  391. package/dist/src/config/scaleDefaults.d.ts.map +0 -1
  392. package/dist/src/config/scaleDefaults.js +0 -45
@@ -1,72 +1,124 @@
1
1
  import { span } from "vega-util";
2
2
  import { isContinuous } from "vega-scale";
3
3
 
4
- import { LOCUS } from "./scaleResolutionConstants.js";
5
- import { requireIntervalSelection } from "./selectionDomainUtils.js";
4
+ import { INDEX, LOCUS } from "./scaleResolutionConstants.js";
5
+ import {
6
+ toInternalIndexLikeDataDomain,
7
+ toInternalIndexLikeInterval,
8
+ } from "./indexLikeDomainUtils.js";
9
+ import {
10
+ hasIntervalSelectionBindingInScope,
11
+ resolveIntervalSelectionBinding,
12
+ } from "./selectionDomainUtils.js";
6
13
  import createDomain from "../utils/domainArray.js";
14
+ import { isExprRef } from "../paramRuntime/paramUtils.js";
7
15
  import { getAccessorDomainKey, isScaleAccessor } from "../encoder/accessor.js";
8
- import { getPrimaryChannel } from "../encoder/encoder.js";
16
+ import { getEncoderAccessors, getPrimaryChannel } from "../encoder/encoder.js";
17
+ import {
18
+ hasExplicitLocusUpperBound,
19
+ isChromosomalLocusInterval,
20
+ } from "../genome/genome.js";
21
+
22
+ /*
23
+ * Domain planning decides what domain a shared scale should use before the
24
+ * scale instance is configured.
25
+ *
26
+ * "Planning" means collecting the participating members, separating literal
27
+ * configured domains from selection-driven domains, validating that the shared
28
+ * scale is not asked to mix incompatible sources, and producing the final union
29
+ * that will be applied to the scale.
30
+ */
9
31
 
10
32
  /**
11
33
  * @typedef {import("../utils/domainArray.js").DomainArray} DomainArray
12
34
  * @typedef {import("../spec/scale.js").ComplexDomain} ComplexDomain
13
35
  * @typedef {import("../spec/scale.js").ScalarDomain} ScalarDomain
14
36
  * @typedef {import("../spec/scale.js").SelectionDomainRef} SelectionDomainRef
37
+ * @typedef {import("../spec/parameter.js").ExprRef} ExprRef
15
38
  * @typedef {import("./scaleResolution.js").ScaleResolutionMember} ScaleResolutionMember
39
+ * @typedef {() => Set<ScaleResolutionMember>} ScaleMembersGetter
40
+ * @typedef {(interval: ScalarDomain | ComplexDomain) => number[]} FromComplexInterval
41
+ * @typedef {(assembly: import("../spec/scale.js").Scale["assembly"] | undefined) => number[]} GetLocusExtent
42
+ * @typedef {{
43
+ * domains: DomainArray[],
44
+ * selectionRef: SelectionDomainLinkInfo | undefined,
45
+ * selectionRuntime: any,
46
+ * selectionDescription: string | undefined,
47
+ * hasLiteralDomain: boolean,
48
+ * }} ConfiguredDomainResolutionState
49
+ * @typedef {{
50
+ * kind: "literal",
51
+ * domain: DomainArray,
52
+ * } | {
53
+ * kind: "selection",
54
+ * domain: DomainArray | undefined,
55
+ * description: string,
56
+ * param: string,
57
+ * encoding: "x" | "y",
58
+ * hasInitial: boolean,
59
+ * runtime: any,
60
+ * }} ConfiguredDomainMemberResolution
16
61
  * @typedef {{
17
62
  * param: string,
18
63
  * encoding: "x" | "y",
19
- * sync: "auto" | "oneWay" | "twoWay",
64
+ * hasInitial: boolean,
65
+ * runtime: any,
20
66
  * }} SelectionDomainLinkInfo
21
67
  */
22
68
 
23
69
  export default class DomainPlanner {
24
- /** @type {() => Set<ScaleResolutionMember>} */
25
- #getMembers;
70
+ /** @type {ScaleMembersGetter} */
71
+ #getActiveMembers;
72
+
73
+ /** @type {ScaleMembersGetter} */
74
+ #getAllMembers;
26
75
 
27
- /** @type {() => Set<ScaleResolutionMember>} */
76
+ /** @type {ScaleMembersGetter} */
28
77
  #getDataMembers;
29
78
 
30
79
  /** @type {() => import("../spec/channel.js").Type} */
31
80
  #getType;
32
81
 
33
- /** @type {(assembly: import("../spec/scale.js").Scale["assembly"] | undefined) => number[]} */
82
+ /** @type {GetLocusExtent} */
34
83
  #getLocusExtent;
35
84
 
36
- /** @type {(interval: ScalarDomain | ComplexDomain) => number[]} */
85
+ /** @type {FromComplexInterval} */
37
86
  #fromComplexInterval;
38
87
 
39
88
  /** @type {any[]} */
40
89
  #initialDomain;
41
90
 
42
- /** @type {DomainArray | undefined} */
43
- #configuredDomain;
44
-
45
91
  /** @type {SelectionDomainLinkInfo | undefined} */
46
92
  #selectionDomainLinkInfo = undefined;
47
93
 
48
94
  #configuredDomainDirty = true;
49
95
 
96
+ /** @type {Map<boolean, DomainArray | undefined>} */
97
+ #configuredDomainsByInitialMode = new Map();
98
+
50
99
  /** @type {WeakMap<ScaleResolutionMember, import("../types/encoder.js").ScaleAccessor[]>} */
51
100
  #accessorsByMember = new WeakMap();
52
101
 
53
102
  /**
54
103
  * @param {object} options
55
- * @param {() => Set<ScaleResolutionMember>} options.getMembers
56
- * @param {() => Set<ScaleResolutionMember>} [options.getDataMembers]
104
+ * @param {ScaleMembersGetter} options.getActiveMembers Active shared-scale members used for configured domain planning.
105
+ * @param {ScaleMembersGetter} [options.getAllMembers] All members, including inactive ones, used for conflict validation.
106
+ * @param {ScaleMembersGetter} [options.getDataMembers] Members used for data-domain extraction; defaults to `getActiveMembers`.
57
107
  * @param {() => import("../spec/channel.js").Type} options.getType
58
- * @param {(assembly: import("../spec/scale.js").Scale["assembly"] | undefined) => number[]} options.getLocusExtent
59
- * @param {(interval: ScalarDomain | ComplexDomain) => number[]} options.fromComplexInterval
108
+ * @param {GetLocusExtent} options.getLocusExtent
109
+ * @param {FromComplexInterval} options.fromComplexInterval
60
110
  */
61
111
  constructor({
62
- getMembers,
112
+ getActiveMembers,
113
+ getAllMembers,
63
114
  getDataMembers,
64
115
  getType,
65
116
  getLocusExtent,
66
117
  fromComplexInterval,
67
118
  }) {
68
- this.#getMembers = getMembers;
69
- this.#getDataMembers = getDataMembers ?? getMembers;
119
+ this.#getActiveMembers = getActiveMembers;
120
+ this.#getAllMembers = getAllMembers ?? getActiveMembers;
121
+ this.#getDataMembers = getDataMembers ?? getActiveMembers;
70
122
  this.#getType = getType;
71
123
  this.#getLocusExtent = getLocusExtent;
72
124
  this.#fromComplexInterval = fromComplexInterval;
@@ -79,25 +131,46 @@ export default class DomainPlanner {
79
131
  return this.#initialDomain;
80
132
  }
81
133
 
82
- hasConfiguredDomain() {
83
- return !!this.getConfiguredDomain();
134
+ /**
135
+ * @param {{ includeSelectionInitial?: boolean }} [options]
136
+ */
137
+ hasConfiguredDomain(options = {}) {
138
+ return !!this.getConfiguredDomain(options);
84
139
  }
85
140
 
86
141
  hasSelectionConfiguredDomain() {
87
- this.getConfiguredDomain();
142
+ this.getSelectionConfiguredDomainBindingInfo();
88
143
  return !!this.#selectionDomainLinkInfo;
89
144
  }
90
145
 
91
146
  /**
92
147
  * @returns {SelectionDomainLinkInfo | undefined}
93
148
  */
94
- getSelectionConfiguredDomainInfo() {
149
+ getSelectionConfiguredDomainBindingInfo() {
150
+ if (this.#selectionDomainLinkInfo || !this.#configuredDomainDirty) {
151
+ return this.#selectionDomainLinkInfo;
152
+ }
153
+
95
154
  this.getConfiguredDomain();
96
155
  return this.#selectionDomainLinkInfo;
97
156
  }
98
157
 
158
+ getSelectionConfiguredDomainInfo() {
159
+ const bindingInfo = this.getSelectionConfiguredDomainBindingInfo();
160
+ if (!bindingInfo) {
161
+ return;
162
+ }
163
+
164
+ return {
165
+ param: bindingInfo.param,
166
+ encoding: bindingInfo.encoding,
167
+ };
168
+ }
169
+
99
170
  invalidateConfiguredDomain() {
100
171
  this.#configuredDomainDirty = true;
172
+ this.#selectionDomainLinkInfo = undefined;
173
+ this.#configuredDomainsByInitialMode.clear();
101
174
  }
102
175
 
103
176
  /**
@@ -108,10 +181,13 @@ export default class DomainPlanner {
108
181
  * @returns {any[]}
109
182
  */
110
183
  getDefaultDomain(extractDataDomain = false, locusAssembly) {
184
+ const type = this.#getType();
111
185
  return resolveDefaultDomain(
112
- this.#getType(),
186
+ type,
113
187
  this.#getLocusExtent,
114
- extractDataDomain ? this.getDataDomain() : undefined,
188
+ extractDataDomain && type !== LOCUS
189
+ ? this.getDataDomain()
190
+ : undefined,
115
191
  locusAssembly
116
192
  );
117
193
  }
@@ -121,12 +197,17 @@ export default class DomainPlanner {
121
197
  *
122
198
  * @param {boolean} [extractDataDomain]
123
199
  * @param {import("../spec/scale.js").Scale["assembly"]} [locusAssembly]
200
+ * @param {{ includeSelectionInitial?: boolean }} [options]
124
201
  * @returns {any[]}
125
202
  */
126
- getConfiguredOrDefaultDomain(extractDataDomain = false, locusAssembly) {
203
+ getConfiguredOrDefaultDomain(
204
+ extractDataDomain = false,
205
+ locusAssembly,
206
+ options = {}
207
+ ) {
127
208
  // TODO: intersect the domain with zoom extent (if it's defined)
128
209
  return (
129
- this.getConfiguredDomain() ??
210
+ this.getConfiguredDomain(options) ??
130
211
  this.getDefaultDomain(extractDataDomain, locusAssembly)
131
212
  );
132
213
  }
@@ -134,19 +215,35 @@ export default class DomainPlanner {
134
215
  /**
135
216
  * Unions the configured domains of all participating views.
136
217
  *
218
+ * @param {{ includeSelectionInitial?: boolean }} [options]
137
219
  * @return {DomainArray}
138
220
  */
139
- getConfiguredDomain() {
140
- if (!this.#configuredDomainDirty) {
141
- return this.#configuredDomain;
221
+ getConfiguredDomain(options = {}) {
222
+ const includeSelectionInitial = options.includeSelectionInitial ?? true;
223
+
224
+ if (
225
+ !this.#configuredDomainDirty &&
226
+ this.#configuredDomainsByInitialMode.has(includeSelectionInitial)
227
+ ) {
228
+ return this.#configuredDomainsByInitialMode.get(
229
+ includeSelectionInitial
230
+ );
142
231
  }
143
232
 
144
233
  const configuredDomain = resolveConfiguredDomain(
145
- this.#getMembers(),
146
- this.#fromComplexInterval
234
+ this.#getActiveMembers(),
235
+ this.#fromComplexInterval,
236
+ includeSelectionInitial
237
+ );
238
+ validateSharedSelectionDomain(
239
+ this.#getAllMembers(),
240
+ configuredDomain.selectionRef
147
241
  );
148
- this.#configuredDomain = configuredDomain.domain;
149
242
  this.#selectionDomainLinkInfo = configuredDomain.selectionRef;
243
+ this.#configuredDomainsByInitialMode.set(
244
+ includeSelectionInitial,
245
+ configuredDomain.domain
246
+ );
150
247
  this.#configuredDomainDirty = false;
151
248
  return configuredDomain.domain;
152
249
  }
@@ -167,18 +264,19 @@ export default class DomainPlanner {
167
264
  /**
168
265
  * @param {import("../types/encoder.js").VegaScale} scale
169
266
  * @param {boolean} domainWasInitialized
267
+ * @param {any[]} [snapshotDomain]
170
268
  * @returns {boolean} true if listeners should be notified immediately
171
269
  */
172
- captureInitialDomain(scale, domainWasInitialized) {
270
+ captureInitialDomain(scale, domainWasInitialized, snapshotDomain) {
173
271
  if (!this.#initialDomain && isContinuous(scale.type)) {
174
- const domain = scale.domain();
272
+ const domain = snapshotDomain ?? scale.domain();
175
273
  if (span(domain) > 0) {
176
274
  this.#initialDomain = domain;
177
275
  }
178
276
  }
179
277
 
180
278
  if (!domainWasInitialized) {
181
- this.#initialDomain = scale.domain();
279
+ this.#initialDomain = snapshotDomain ?? scale.domain();
182
280
  return true;
183
281
  }
184
282
 
@@ -205,7 +303,7 @@ export default class DomainPlanner {
205
303
  return [];
206
304
  }
207
305
 
208
- const accessors = encoder.accessors ?? [];
306
+ const accessors = getEncoderAccessors(encoder);
209
307
  if (accessors.length === 0) {
210
308
  return [];
211
309
  }
@@ -222,107 +320,168 @@ export default class DomainPlanner {
222
320
  /**
223
321
  * @param {Set<ScaleResolutionMember>} members
224
322
  * @param {(interval: ScalarDomain | ComplexDomain) => number[]} fromComplexInterval
323
+ * @param {boolean} includeSelectionInitial
225
324
  * @returns {{
226
325
  * domain: DomainArray | undefined,
227
326
  * selectionRef: SelectionDomainLinkInfo | undefined,
228
327
  * }}
229
328
  */
230
- function resolveConfiguredDomain(members, fromComplexInterval) {
329
+ function resolveConfiguredDomain(
330
+ members,
331
+ fromComplexInterval,
332
+ includeSelectionInitial
333
+ ) {
231
334
  const domainMembers = Array.from(members)
232
335
  .filter((member) => member.contributesToDomain)
233
336
  .filter((member) => member.channelDef.scale?.domain);
234
337
 
235
- /** @type {DomainArray[]} */
236
- const domains = [];
237
-
238
- /** @type {string | undefined} */
239
- let selectionRefKey = undefined;
240
- /** @type {string | undefined} */
241
- let selectionRefDescription = undefined;
242
- /** @type {"auto" | "oneWay" | "twoWay" | undefined} */
243
- let selectionRefSync = undefined;
244
- /** @type {SelectionDomainLinkInfo | undefined} */
245
- let selectionRef = undefined;
246
- let hasLiteralDomain = false;
338
+ /** @type {ConfiguredDomainResolutionState} */
339
+ const state = {
340
+ domains: [],
341
+ selectionRef: undefined,
342
+ selectionRuntime: undefined,
343
+ selectionDescription: undefined,
344
+ hasLiteralDomain: false,
345
+ };
247
346
 
248
347
  for (const member of domainMembers) {
249
- const domainDef = member.channelDef.scale.domain;
250
- if (isSelectionDomainRef(domainDef)) {
251
- if (hasLiteralDomain) {
252
- throw new Error(
253
- "Cannot mix selection-driven and literal configured domains on a shared scale."
254
- );
255
- }
348
+ const resolved = resolveConfiguredDomainMember(
349
+ member,
350
+ fromComplexInterval,
351
+ includeSelectionInitial
352
+ );
353
+
354
+ if (resolved.kind === "selection") {
355
+ mergeSelectionConfiguredDomain(state, resolved);
356
+ continue;
357
+ }
256
358
 
257
- const resolved = resolveSelectionDomain(
359
+ mergeLiteralConfiguredDomain(state, resolved);
360
+ }
361
+
362
+ return finishConfiguredDomainResolution(state);
363
+ }
364
+
365
+ /**
366
+ * @param {ScaleResolutionMember} member
367
+ * @param {(interval: ScalarDomain | ComplexDomain) => number[]} fromComplexInterval
368
+ * @param {boolean} includeSelectionInitial
369
+ * @returns {ConfiguredDomainMemberResolution}
370
+ */
371
+ function resolveConfiguredDomainMember(
372
+ member,
373
+ fromComplexInterval,
374
+ includeSelectionInitial
375
+ ) {
376
+ const domainDef = member.channelDef.scale.domain;
377
+ if (isSelectionDomainRef(domainDef)) {
378
+ return {
379
+ kind: "selection",
380
+ ...resolveSelectionDomain(
258
381
  member,
259
382
  domainDef,
383
+ fromComplexInterval,
384
+ includeSelectionInitial
385
+ ),
386
+ };
387
+ }
388
+
389
+ if (isExprRef(domainDef)) {
390
+ return {
391
+ kind: "literal",
392
+ domain: resolveConfiguredIntervalDomain(
393
+ member.channelDef.type,
394
+ member.view.paramRuntime.createExpression(domainDef.expr)(),
260
395
  fromComplexInterval
261
- );
396
+ ),
397
+ };
398
+ }
262
399
 
263
- if (selectionRefKey && selectionRefKey !== resolved.key) {
264
- throw new Error(
265
- "Conflicting selection domain references on a shared scale: " +
266
- selectionRefDescription +
267
- " vs " +
268
- resolved.description +
269
- "."
270
- );
271
- }
400
+ return {
401
+ kind: "literal",
402
+ domain: resolveConfiguredIntervalDomain(
403
+ member.channelDef.type,
404
+ domainDef,
405
+ fromComplexInterval
406
+ ),
407
+ };
408
+ }
272
409
 
273
- if (!selectionRefSync) {
274
- selectionRefSync = resolved.sync;
275
- } else if (selectionRefSync === "auto") {
276
- selectionRefSync = resolved.sync;
277
- } else if (resolved.sync !== "auto") {
278
- if (selectionRefSync !== resolved.sync) {
279
- throw new Error(
280
- "Conflicting selection domain sync modes on a shared scale: " +
281
- selectionRefSync +
282
- " vs " +
283
- resolved.sync +
284
- "."
285
- );
286
- }
287
- }
410
+ /**
411
+ * @param {ConfiguredDomainResolutionState} state
412
+ * @param {Extract<ConfiguredDomainMemberResolution, { kind: "selection" }>} resolved
413
+ */
414
+ function mergeSelectionConfiguredDomain(state, resolved) {
415
+ if (state.hasLiteralDomain) {
416
+ throw new Error(
417
+ "Cannot mix selection-driven and literal configured domains on a shared scale."
418
+ );
419
+ }
288
420
 
289
- selectionRefKey = resolved.key;
290
- selectionRefDescription = resolved.description;
291
- selectionRef = {
292
- param: resolved.param,
293
- encoding: resolved.encoding,
294
- sync: selectionRefSync,
295
- };
421
+ if (
422
+ state.selectionRef &&
423
+ (state.selectionRef.runtime !== resolved.runtime ||
424
+ state.selectionRef.param !== resolved.param ||
425
+ state.selectionRef.encoding !== resolved.encoding)
426
+ ) {
427
+ throw new Error(
428
+ "Conflicting selection domain references on a shared scale: " +
429
+ state.selectionDescription +
430
+ " vs " +
431
+ resolved.description +
432
+ "."
433
+ );
434
+ }
296
435
 
297
- if (resolved.domain) {
298
- domains.push(resolved.domain);
299
- }
300
- continue;
301
- }
436
+ state.selectionRuntime = resolved.runtime;
437
+ state.selectionDescription = resolved.description;
438
+ state.selectionRef = {
439
+ param: resolved.param,
440
+ encoding: resolved.encoding,
441
+ hasInitial:
442
+ (state.selectionRef?.hasInitial ?? false) || resolved.hasInitial,
443
+ runtime: resolved.runtime,
444
+ };
302
445
 
303
- if (selectionRefKey) {
304
- throw new Error(
305
- "Cannot mix literal configured domains with selection-driven domains on a shared scale."
306
- );
307
- }
446
+ if (resolved.domain) {
447
+ state.domains.push(resolved.domain);
448
+ }
449
+ }
308
450
 
309
- hasLiteralDomain = true;
310
- domains.push(
311
- createDomain(member.channelDef.type, fromComplexInterval(domainDef))
451
+ /**
452
+ * @param {ConfiguredDomainResolutionState} state
453
+ * @param {Extract<ConfiguredDomainMemberResolution, { kind: "literal" }>} resolved
454
+ */
455
+ function mergeLiteralConfiguredDomain(state, resolved) {
456
+ if (state.selectionRuntime) {
457
+ throw new Error(
458
+ "Cannot mix literal configured domains with selection-driven domains on a shared scale."
312
459
  );
313
460
  }
314
461
 
315
- if (domains.length > 0) {
462
+ state.hasLiteralDomain = true;
463
+ state.domains.push(resolved.domain);
464
+ }
465
+
466
+ /**
467
+ * @param {ConfiguredDomainResolutionState} state
468
+ * @returns {{
469
+ * domain: DomainArray | undefined,
470
+ * selectionRef: SelectionDomainLinkInfo | undefined,
471
+ * }}
472
+ */
473
+ function finishConfiguredDomainResolution(state) {
474
+ if (state.domains.length > 0) {
316
475
  return {
317
- domain: domains.reduce((acc, curr) => acc.extendAll(curr)),
318
- selectionRef,
476
+ domain: state.domains.reduce((acc, curr) => acc.extendAll(curr)),
477
+ selectionRef: state.selectionRef,
319
478
  };
320
479
  }
321
480
 
322
- if (selectionRefKey) {
481
+ if (state.selectionRuntime) {
323
482
  // Selection refs are still the source of truth even when the
324
483
  // selection interval currently resolves to no domain.
325
- return { domain: undefined, selectionRef };
484
+ return { domain: undefined, selectionRef: state.selectionRef };
326
485
  }
327
486
 
328
487
  return { domain: undefined, selectionRef: undefined };
@@ -332,24 +491,23 @@ function resolveConfiguredDomain(members, fromComplexInterval) {
332
491
  * @param {ScaleResolutionMember} member
333
492
  * @param {SelectionDomainRef} domainRef
334
493
  * @param {(interval: ScalarDomain | ComplexDomain) => number[]} fromComplexInterval
494
+ * @param {boolean} includeSelectionInitial
335
495
  * @returns {{
336
496
  * domain: DomainArray | undefined,
337
- * key: string,
338
497
  * description: string,
339
498
  * param: string,
340
499
  * encoding: "x" | "y",
341
- * sync: "auto" | "oneWay" | "twoWay",
500
+ * hasInitial: boolean,
501
+ * runtime: any,
342
502
  * }}
343
503
  */
344
- function resolveSelectionDomain(member, domainRef, fromComplexInterval) {
504
+ function resolveSelectionDomain(
505
+ member,
506
+ domainRef,
507
+ fromComplexInterval,
508
+ includeSelectionInitial
509
+ ) {
345
510
  const paramName = domainRef.param;
346
- const syncMode = domainRef.sync ?? "auto";
347
-
348
- if (syncMode !== "auto" && syncMode !== "oneWay" && syncMode !== "twoWay") {
349
- throw new Error(
350
- `Invalid selection domain sync mode "${syncMode}" for parameter "${paramName}".`
351
- );
352
- }
353
511
 
354
512
  const resolvedChannel = resolveSelectionDomainChannel(
355
513
  member.channel,
@@ -357,40 +515,112 @@ function resolveSelectionDomain(member, domainRef, fromComplexInterval) {
357
515
  paramName
358
516
  );
359
517
 
360
- const paramRuntime = member.view.paramRuntime;
361
- const selection = requireIntervalSelection(
362
- paramRuntime?.findValue(paramName),
363
- paramName
518
+ const binding = resolveIntervalSelectionBinding(
519
+ member.view,
520
+ paramName,
521
+ resolvedChannel
364
522
  );
365
-
366
- const interval = selection.intervals[resolvedChannel];
367
- const key = [paramName, resolvedChannel].join("|");
523
+ const hasInitial = domainRef.initial !== undefined;
524
+ const interval = binding.selection.intervals[resolvedChannel];
368
525
  const description = paramName + "." + resolvedChannel;
369
-
370
526
  if (!interval || interval.length !== 2) {
527
+ const initialDomain = includeSelectionInitial
528
+ ? domainRef.initial
529
+ ? resolveConfiguredIntervalDomain(
530
+ member.channelDef.type,
531
+ domainRef.initial,
532
+ fromComplexInterval
533
+ )
534
+ : undefined
535
+ : undefined;
371
536
  return {
372
- domain: undefined,
373
- key,
537
+ domain: initialDomain,
374
538
  description,
375
539
  param: paramName,
376
540
  encoding: resolvedChannel,
377
- sync: syncMode,
541
+ hasInitial,
542
+ runtime: binding.runtime,
378
543
  };
379
544
  }
380
545
 
381
546
  return {
547
+ // Selection intervals already use internal scale-domain coordinates.
382
548
  domain: createDomain(
383
549
  member.channelDef.type,
384
550
  fromComplexInterval(interval)
385
551
  ),
386
- key,
387
552
  description,
388
553
  param: paramName,
389
554
  encoding: resolvedChannel,
390
- sync: syncMode,
555
+ hasInitial,
556
+ runtime: binding.runtime,
391
557
  };
392
558
  }
393
559
 
560
+ /**
561
+ * @param {import("../spec/channel.js").Type} type
562
+ * @param {ScalarDomain | ComplexDomain} interval
563
+ * @param {(interval: ScalarDomain | ComplexDomain) => number[]} fromComplexInterval
564
+ * @returns {DomainArray}
565
+ */
566
+ function resolveConfiguredIntervalDomain(type, interval, fromComplexInterval) {
567
+ const numericDomain = fromComplexInterval(interval);
568
+ const internalDomain =
569
+ type === LOCUS &&
570
+ isChromosomalLocusInterval(interval) &&
571
+ !hasExplicitLocusUpperBound(interval)
572
+ ? numericDomain
573
+ : toInternalIndexLikeInterval(type, numericDomain);
574
+
575
+ return createDomain(type, internalDomain);
576
+ }
577
+
578
+ /**
579
+ * Fails fast when a selection-driven scale domain ends up sharing the same
580
+ * scale resolution as the interval selection that drives it. This typically
581
+ * happens when an overview/detail spec forgets to make the linked positional
582
+ * scale independent.
583
+ *
584
+ * @param {Set<ScaleResolutionMember>} members
585
+ * @param {SelectionDomainLinkInfo | undefined} selectionRef
586
+ */
587
+ function validateSharedSelectionDomain(members, selectionRef) {
588
+ if (
589
+ !selectionRef ||
590
+ members.size < 2 ||
591
+ !Array.from(members).some((member) =>
592
+ hasIntervalSelectionBindingInScope(
593
+ member.view,
594
+ selectionRef.runtime,
595
+ selectionRef.param,
596
+ selectionRef.encoding
597
+ )
598
+ )
599
+ ) {
600
+ return;
601
+ }
602
+
603
+ const viewPaths = Array.from(
604
+ new Set(
605
+ Array.from(members)
606
+ .filter((member) => member.contributesToDomain)
607
+ .map(
608
+ (member) =>
609
+ member.view.getPathString?.() ??
610
+ member.view.name ??
611
+ "(unknown)"
612
+ )
613
+ )
614
+ );
615
+
616
+ throw new Error(
617
+ `Selection domain reference "${selectionRef.param}.${selectionRef.encoding}" cannot use a shared ${selectionRef.encoding} scale when the same interval selection is defined in that shared view group (${viewPaths.join(", ")}). ` +
618
+ `This creates a feedback loop between brushing and the scale domain. ` +
619
+ `Make the linked ${selectionRef.encoding} scale independent, for example with ` +
620
+ `"resolve": { "scale": { "${selectionRef.encoding}": "independent" } } on the common ancestor.`
621
+ );
622
+ }
623
+
394
624
  /**
395
625
  * @param {import("../spec/channel.js").ChannelWithScale} channel
396
626
  * @param {SelectionDomainRef} domainRef
@@ -502,5 +732,8 @@ function resolveDefaultDomain(type, getLocusExtent, dataDomain, locusAssembly) {
502
732
  if (type == LOCUS) {
503
733
  return getLocusExtent(locusAssembly);
504
734
  }
735
+ if (type == INDEX) {
736
+ return toInternalIndexLikeDataDomain(type, dataDomain) ?? [];
737
+ }
505
738
  return dataDomain ?? [];
506
739
  }