@genome-spy/core 0.64.0 → 0.66.1

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 (285) hide show
  1. package/dist/bundle/{index-CCJIjehY.js → AbortablePromiseCache-CcuMrnn7.js} +22 -91
  2. package/dist/bundle/browser-BRemItdO.js +138 -0
  3. package/dist/bundle/index-BatuyGAI.js +271 -0
  4. package/dist/bundle/index-ByuE8dvu.js +332 -0
  5. package/dist/bundle/index-Cq3QFUxX.js +1781 -0
  6. package/dist/bundle/{index-C08YCM2T.js → index-D-w7Mmt9.js} +246 -126
  7. package/dist/bundle/index-D28m8tSW.js +1607 -0
  8. package/dist/bundle/index-D74H8TTz.js +508 -0
  9. package/dist/bundle/index-DbJ0oeYM.js +631 -0
  10. package/dist/bundle/index.es.js +15034 -13842
  11. package/dist/bundle/index.js +223 -237
  12. package/dist/bundle/inflate-GtwLkvSP.js +1048 -0
  13. package/dist/bundle/unzip-NywezaRR.js +1492 -0
  14. package/dist/schema.json +22 -4
  15. package/dist/src/config/scaleDefaults.d.ts +8 -0
  16. package/dist/src/config/scaleDefaults.d.ts.map +1 -0
  17. package/dist/src/config/scaleDefaults.js +45 -0
  18. package/dist/src/data/collector.d.ts +7 -2
  19. package/dist/src/data/collector.d.ts.map +1 -1
  20. package/dist/src/data/collector.js +13 -2
  21. package/dist/src/data/dataFlow.d.ts +20 -42
  22. package/dist/src/data/dataFlow.d.ts.map +1 -1
  23. package/dist/src/data/dataFlow.js +57 -80
  24. package/dist/src/data/flowHandle.d.ts +15 -0
  25. package/dist/src/data/flowHandle.d.ts.map +1 -0
  26. package/dist/src/data/flowHandle.js +13 -0
  27. package/dist/src/data/flowInit.d.ts +85 -0
  28. package/dist/src/data/flowInit.d.ts.map +1 -0
  29. package/dist/src/data/flowInit.js +238 -0
  30. package/dist/src/data/flowInit.test.d.ts +2 -0
  31. package/dist/src/data/flowInit.test.d.ts.map +1 -0
  32. package/dist/src/data/flowOptimizer.d.ts +6 -4
  33. package/dist/src/data/flowOptimizer.d.ts.map +1 -1
  34. package/dist/src/data/flowOptimizer.js +29 -14
  35. package/dist/src/data/sources/lazy/axisTickSource.js +1 -1
  36. package/dist/src/data/sources/lazy/bamSource.js +1 -1
  37. package/dist/src/data/sources/lazy/bigBedSource.js +1 -1
  38. package/dist/src/data/sources/lazy/bigWigSource.js +1 -1
  39. package/dist/src/data/sources/lazy/gff3Source.d.ts +2 -6
  40. package/dist/src/data/sources/lazy/gff3Source.d.ts.map +1 -1
  41. package/dist/src/data/sources/lazy/gff3Source.js +4 -8
  42. package/dist/src/data/sources/lazy/indexedFastaSource.d.ts.map +1 -1
  43. package/dist/src/data/sources/lazy/indexedFastaSource.js +17 -17
  44. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +1 -1
  45. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  46. package/dist/src/data/sources/lazy/singleAxisLazySource.js +10 -3
  47. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  48. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +5 -1
  49. package/dist/src/data/sources/lazy/tabixSource.js +1 -1
  50. package/dist/src/data/transforms/filterScoredLabels.d.ts +1 -1
  51. package/dist/src/data/transforms/filterScoredLabels.d.ts.map +1 -1
  52. package/dist/src/data/transforms/filterScoredLabels.js +1 -1
  53. package/dist/src/data/transforms/linearizeGenomicCoordinate.d.ts.map +1 -1
  54. package/dist/src/data/transforms/linearizeGenomicCoordinate.js +2 -1
  55. package/dist/src/encoder/encoder.d.ts +1 -1
  56. package/dist/src/encoder/encoder.d.ts.map +1 -1
  57. package/dist/src/encoder/encoder.js +1 -1
  58. package/dist/src/genome/scaleLocus.d.ts +39 -0
  59. package/dist/src/genome/scaleLocus.d.ts.map +1 -1
  60. package/dist/src/genome/scaleLocus.js +76 -0
  61. package/dist/src/genomeSpy/canvasExport.d.ts +19 -0
  62. package/dist/src/genomeSpy/canvasExport.d.ts.map +1 -0
  63. package/dist/src/genomeSpy/canvasExport.js +66 -0
  64. package/dist/src/genomeSpy/containerUi.d.ts +17 -0
  65. package/dist/src/genomeSpy/containerUi.d.ts.map +1 -0
  66. package/dist/src/genomeSpy/containerUi.js +78 -0
  67. package/dist/src/genomeSpy/eventListenerRegistry.d.ts +19 -0
  68. package/dist/src/genomeSpy/eventListenerRegistry.d.ts.map +1 -0
  69. package/dist/src/genomeSpy/eventListenerRegistry.js +38 -0
  70. package/dist/src/genomeSpy/inputBindingManager.d.ts +14 -0
  71. package/dist/src/genomeSpy/inputBindingManager.d.ts.map +1 -0
  72. package/dist/src/genomeSpy/inputBindingManager.js +63 -0
  73. package/dist/src/genomeSpy/interactionController.d.ts +40 -0
  74. package/dist/src/genomeSpy/interactionController.d.ts.map +1 -0
  75. package/dist/src/genomeSpy/interactionController.js +371 -0
  76. package/dist/src/genomeSpy/keyboardListenerManager.d.ts +10 -0
  77. package/dist/src/genomeSpy/keyboardListenerManager.d.ts.map +1 -0
  78. package/dist/src/genomeSpy/keyboardListenerManager.js +31 -0
  79. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts +15 -0
  80. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts.map +1 -0
  81. package/dist/src/genomeSpy/loadingIndicatorManager.js +92 -0
  82. package/dist/src/genomeSpy/renderCoordinator.d.ts +22 -0
  83. package/dist/src/genomeSpy/renderCoordinator.d.ts.map +1 -0
  84. package/dist/src/genomeSpy/renderCoordinator.js +118 -0
  85. package/dist/src/genomeSpy/viewContextFactory.d.ts +18 -0
  86. package/dist/src/genomeSpy/viewContextFactory.d.ts.map +1 -0
  87. package/dist/src/genomeSpy/viewContextFactory.js +79 -0
  88. package/dist/src/genomeSpy/viewDataInit.d.ts +12 -0
  89. package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -0
  90. package/dist/src/genomeSpy/viewDataInit.js +41 -0
  91. package/dist/src/genomeSpy/viewHierarchyConfig.d.ts +14 -0
  92. package/dist/src/genomeSpy/viewHierarchyConfig.d.ts.map +1 -0
  93. package/dist/src/genomeSpy/viewHierarchyConfig.js +24 -0
  94. package/dist/src/genomeSpy/viewHighlight.d.ts +5 -0
  95. package/dist/src/genomeSpy/viewHighlight.d.ts.map +1 -0
  96. package/dist/src/genomeSpy/viewHighlight.js +30 -0
  97. package/dist/src/genomeSpy.d.ts +17 -72
  98. package/dist/src/genomeSpy.d.ts.map +1 -1
  99. package/dist/src/genomeSpy.js +180 -789
  100. package/dist/src/gl/glslScaleGenerator.d.ts +1 -1
  101. package/dist/src/gl/webGLHelper.d.ts +2 -2
  102. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  103. package/dist/src/gl/webGLHelper.js +4 -4
  104. package/dist/src/index.d.ts.map +1 -1
  105. package/dist/src/index.js +2 -12
  106. package/dist/src/marks/mark.d.ts +1 -0
  107. package/dist/src/marks/mark.d.ts.map +1 -1
  108. package/dist/src/marks/mark.js +26 -3
  109. package/dist/src/{view → scales}/axisResolution.d.ts +12 -14
  110. package/dist/src/scales/axisResolution.d.ts.map +1 -0
  111. package/dist/src/{view → scales}/axisResolution.js +38 -12
  112. package/dist/src/scales/axisResolution.test.d.ts.map +1 -0
  113. package/dist/src/scales/scaleDomainAggregator.d.ts +57 -0
  114. package/dist/src/scales/scaleDomainAggregator.d.ts.map +1 -0
  115. package/dist/src/scales/scaleDomainAggregator.js +162 -0
  116. package/dist/src/scales/scaleDomainAggregator.test.d.ts +2 -0
  117. package/dist/src/scales/scaleDomainAggregator.test.d.ts.map +1 -0
  118. package/dist/src/scales/scaleInstanceManager.d.ts +40 -0
  119. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -0
  120. package/dist/src/scales/scaleInstanceManager.js +313 -0
  121. package/dist/src/scales/scaleInstanceManager.test.d.ts +2 -0
  122. package/dist/src/scales/scaleInstanceManager.test.d.ts.map +1 -0
  123. package/dist/src/scales/scaleInteractionController.d.ts +73 -0
  124. package/dist/src/scales/scaleInteractionController.d.ts.map +1 -0
  125. package/dist/src/scales/scaleInteractionController.js +336 -0
  126. package/dist/src/scales/scaleInteractionController.test.d.ts +2 -0
  127. package/dist/src/scales/scaleInteractionController.test.d.ts.map +1 -0
  128. package/dist/src/scales/scalePropsResolver.d.ts +23 -0
  129. package/dist/src/scales/scalePropsResolver.d.ts.map +1 -0
  130. package/dist/src/scales/scalePropsResolver.js +74 -0
  131. package/dist/src/{view → scales}/scaleResolution.d.ts +53 -31
  132. package/dist/src/scales/scaleResolution.d.ts.map +1 -0
  133. package/dist/src/scales/scaleResolution.js +658 -0
  134. package/dist/src/scales/scaleResolution.test.d.ts.map +1 -0
  135. package/dist/src/scales/scaleResolutionConstants.d.ts +6 -0
  136. package/dist/src/scales/scaleResolutionConstants.d.ts.map +1 -0
  137. package/dist/src/scales/scaleResolutionConstants.js +5 -0
  138. package/dist/src/scales/scaleRules.d.ts +16 -0
  139. package/dist/src/scales/scaleRules.d.ts.map +1 -0
  140. package/dist/src/scales/scaleRules.js +103 -0
  141. package/dist/src/scales/scaleRules.test.d.ts +2 -0
  142. package/dist/src/scales/scaleRules.test.d.ts.map +1 -0
  143. package/dist/src/spec/channel.d.ts +13 -18
  144. package/dist/src/spec/sampleView.d.ts +3 -2
  145. package/dist/src/spec/scale.d.ts +6 -0
  146. package/dist/src/types/embedApi.d.ts +5 -0
  147. package/dist/src/types/scaleResolutionApi.d.ts +1 -1
  148. package/dist/src/types/viewContext.d.ts +1 -1
  149. package/dist/src/view/concatView.d.ts +18 -0
  150. package/dist/src/view/concatView.d.ts.map +1 -1
  151. package/dist/src/view/concatView.js +73 -0
  152. package/dist/src/view/concatView.test.d.ts +2 -0
  153. package/dist/src/view/concatView.test.d.ts.map +1 -0
  154. package/dist/src/view/containerMutationHelper.d.ts +74 -0
  155. package/dist/src/view/containerMutationHelper.d.ts.map +1 -0
  156. package/dist/src/view/containerMutationHelper.js +114 -0
  157. package/dist/src/view/containerView.d.ts +0 -7
  158. package/dist/src/view/containerView.d.ts.map +1 -1
  159. package/dist/src/view/containerView.js +0 -10
  160. package/dist/src/view/facetView.d.ts.map +1 -1
  161. package/dist/src/view/facetView.js +0 -14
  162. package/dist/src/view/flowBuilder.d.ts +2 -2
  163. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  164. package/dist/src/view/flowBuilder.js +21 -4
  165. package/dist/src/view/gridView/gridChild.d.ts +11 -0
  166. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  167. package/dist/src/view/gridView/gridChild.js +32 -6
  168. package/dist/src/view/gridView/gridView.d.ts +39 -1
  169. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  170. package/dist/src/view/gridView/gridView.js +113 -42
  171. package/dist/src/view/gridView/gridView.test.d.ts +2 -0
  172. package/dist/src/view/gridView/gridView.test.d.ts.map +1 -0
  173. package/dist/src/view/gridView/scrollbar.d.ts +39 -8
  174. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  175. package/dist/src/view/gridView/scrollbar.js +184 -69
  176. package/dist/src/view/gridView/selectionRect.d.ts +8 -4
  177. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  178. package/dist/src/view/gridView/selectionRect.js +28 -3
  179. package/dist/src/view/gridView/selectionRect.test.d.ts +2 -0
  180. package/dist/src/view/gridView/selectionRect.test.d.ts.map +1 -0
  181. package/dist/src/view/layerView.d.ts +14 -0
  182. package/dist/src/view/layerView.d.ts.map +1 -1
  183. package/dist/src/view/layerView.js +66 -0
  184. package/dist/src/view/layerView.test.d.ts +2 -0
  185. package/dist/src/view/layerView.test.d.ts.map +1 -0
  186. package/dist/src/view/paramMediator.d.ts +2 -1
  187. package/dist/src/view/paramMediator.d.ts.map +1 -1
  188. package/dist/src/view/paramMediator.js +13 -1
  189. package/dist/src/view/testUtils.d.ts.map +1 -1
  190. package/dist/src/view/testUtils.js +18 -5
  191. package/dist/src/view/unitView.d.ts.map +1 -1
  192. package/dist/src/view/unitView.js +52 -12
  193. package/dist/src/view/view.d.ts +23 -7
  194. package/dist/src/view/view.d.ts.map +1 -1
  195. package/dist/src/view/view.js +61 -5
  196. package/dist/src/view/viewDispose.test.d.ts +2 -0
  197. package/dist/src/view/viewDispose.test.d.ts.map +1 -0
  198. package/dist/src/view/viewUtils.d.ts +4 -4
  199. package/dist/src/view/viewUtils.d.ts.map +1 -1
  200. package/dist/src/view/viewUtils.js +19 -15
  201. package/dist/src/view/viewUtils.test.d.ts +2 -0
  202. package/dist/src/view/viewUtils.test.d.ts.map +1 -0
  203. package/package.json +10 -10
  204. package/dist/bundle/__vite-browser-external-C--ziKoh.js +0 -8
  205. package/dist/bundle/_commonjsHelpers-DjF3Plf2.js +0 -26
  206. package/dist/bundle/index-5ajWdKly.js +0 -1319
  207. package/dist/bundle/index-B03-Om4z.js +0 -274
  208. package/dist/bundle/index-BftNdA0O.js +0 -27
  209. package/dist/bundle/index-Bg7C4Xat.js +0 -2750
  210. package/dist/bundle/index-C3QR8Lv6.js +0 -2131
  211. package/dist/bundle/index-DTcHjAHp.js +0 -505
  212. package/dist/bundle/index-DnIkxb0L.js +0 -1025
  213. package/dist/bundle/index-Ww3TAo6_.js +0 -71
  214. package/dist/bundle/index-g8iXgW0W.js +0 -651
  215. package/dist/bundle/long-B-FASCSo.js +0 -2387
  216. package/dist/bundle/remoteFile-BuaqFGWk.js +0 -94
  217. package/dist/src/data/collector.test.js +0 -138
  218. package/dist/src/data/dataFlow.test.js +0 -5
  219. package/dist/src/data/flow.test.js +0 -81
  220. package/dist/src/data/flowNode.test.js +0 -50
  221. package/dist/src/data/flowOptimizer.test.js +0 -204
  222. package/dist/src/data/formats/fasta.test.js +0 -27
  223. package/dist/src/data/sources/inlineSource.test.js +0 -63
  224. package/dist/src/data/sources/sequenceSource.test.js +0 -81
  225. package/dist/src/data/transforms/aggregate.test.js +0 -134
  226. package/dist/src/data/transforms/clone.test.js +0 -11
  227. package/dist/src/data/transforms/coverage.test.js +0 -238
  228. package/dist/src/data/transforms/filter.test.js +0 -20
  229. package/dist/src/data/transforms/flatten.test.js +0 -96
  230. package/dist/src/data/transforms/flattenDelimited.test.js +0 -90
  231. package/dist/src/data/transforms/flattenSequence.test.js +0 -34
  232. package/dist/src/data/transforms/formula.test.js +0 -25
  233. package/dist/src/data/transforms/identifier.test.js +0 -92
  234. package/dist/src/data/transforms/pileup.test.js +0 -70
  235. package/dist/src/data/transforms/project.test.js +0 -32
  236. package/dist/src/data/transforms/regexExtract.test.js +0 -70
  237. package/dist/src/data/transforms/regexFold.test.js +0 -201
  238. package/dist/src/data/transforms/sample.test.js +0 -38
  239. package/dist/src/data/transforms/stack.test.js +0 -91
  240. package/dist/src/encoder/accessor.test.js +0 -162
  241. package/dist/src/encoder/encoder.test.js +0 -105
  242. package/dist/src/genome/genome.test.js +0 -268
  243. package/dist/src/genome/genomes.test.js +0 -8
  244. package/dist/src/genome/scaleIndex.test.js +0 -78
  245. package/dist/src/genome/scaleLocus.test.js +0 -4
  246. package/dist/src/scale/scale.test.js +0 -326
  247. package/dist/src/scale/ticks.test.js +0 -46
  248. package/dist/src/selection/selection.test.js +0 -14
  249. package/dist/src/utils/addBaseUrl.test.js +0 -30
  250. package/dist/src/utils/binnedIndex.test.js +0 -201
  251. package/dist/src/utils/cloner.test.js +0 -35
  252. package/dist/src/utils/coalesce.test.js +0 -16
  253. package/dist/src/utils/concatIterables.test.js +0 -8
  254. package/dist/src/utils/domainArray.test.js +0 -130
  255. package/dist/src/utils/indexer.test.js +0 -49
  256. package/dist/src/utils/interactionEvent.test.js +0 -35
  257. package/dist/src/utils/iterateNestedMaps.test.js +0 -33
  258. package/dist/src/utils/kWayMerge.test.js +0 -30
  259. package/dist/src/utils/mergeObjects.test.js +0 -42
  260. package/dist/src/utils/numberExtractor.test.js +0 -6
  261. package/dist/src/utils/propertyCacher.test.js +0 -89
  262. package/dist/src/utils/propertyCoalescer.test.js +0 -25
  263. package/dist/src/utils/radixSort.test.js +0 -51
  264. package/dist/src/utils/reservationMap.test.js +0 -20
  265. package/dist/src/utils/ringBuffer.test.js +0 -39
  266. package/dist/src/utils/topK.test.js +0 -54
  267. package/dist/src/utils/trees.test.js +0 -135
  268. package/dist/src/utils/url.test.js +0 -28
  269. package/dist/src/utils/variableTools.test.js +0 -13
  270. package/dist/src/view/axisResolution.d.ts.map +0 -1
  271. package/dist/src/view/axisResolution.test.d.ts.map +0 -1
  272. package/dist/src/view/axisResolution.test.js +0 -206
  273. package/dist/src/view/flowBuilder.test.js +0 -125
  274. package/dist/src/view/layout/flexLayout.test.js +0 -323
  275. package/dist/src/view/layout/grid.test.js +0 -71
  276. package/dist/src/view/layout/rectangle.test.js +0 -192
  277. package/dist/src/view/paramMediator.test.js +0 -260
  278. package/dist/src/view/scaleResolution.d.ts.map +0 -1
  279. package/dist/src/view/scaleResolution.js +0 -1049
  280. package/dist/src/view/scaleResolution.test.d.ts.map +0 -1
  281. package/dist/src/view/scaleResolution.test.js +0 -645
  282. package/dist/src/view/view.test.js +0 -245
  283. package/dist/src/view/viewFactory.test.js +0 -25
  284. /package/dist/src/{view → scales}/axisResolution.test.d.ts +0 -0
  285. /package/dist/src/{view → scales}/scaleResolution.test.d.ts +0 -0
@@ -0,0 +1,336 @@
1
+ import {
2
+ clampRange,
3
+ isArray,
4
+ isBoolean,
5
+ isObject,
6
+ panLinear,
7
+ panLog,
8
+ panPow,
9
+ span,
10
+ zoomLinear,
11
+ zoomLog,
12
+ zoomPow,
13
+ } from "vega-util";
14
+ import { isContinuous } from "vega-scale";
15
+ import { easeCubicInOut } from "d3-ease";
16
+
17
+ import eerp from "../utils/eerp.js";
18
+ import { shallowArrayEquals } from "../utils/arrayUtils.js";
19
+
20
+ /**
21
+ * @typedef {import("../spec/scale.js").NumericDomain} NumericDomain
22
+ * @typedef {import("../spec/scale.js").ScalarDomain} ScalarDomain
23
+ * @typedef {import("../spec/scale.js").ComplexDomain} ComplexDomain
24
+ * @typedef {import("../spec/scale.js").ZoomParams} ZoomParams
25
+ * @typedef {import("../types/encoder.js").VegaScale} VegaScale
26
+ * @typedef {VegaScale & { props: import("../spec/scale.js").Scale }} ScaleWithProps
27
+ */
28
+
29
+ export default class ScaleInteractionController {
30
+ /** @type {() => ScaleWithProps} */
31
+ #getScale;
32
+
33
+ /** @type {() => import("../utils/animator.js").default} */
34
+ #getAnimator;
35
+
36
+ /** @type {() => number[]} */
37
+ #getInitialDomainSnapshot;
38
+
39
+ /** @type {() => number[]} */
40
+ #getResetDomain;
41
+
42
+ /** @type {(domain: ScalarDomain | ComplexDomain) => number[]} */
43
+ #fromComplexInterval;
44
+
45
+ /** @type {() => number[]} */
46
+ #getGenomeExtent;
47
+
48
+ /**
49
+ * @param {object} options
50
+ * @param {() => ScaleWithProps} options.getScale
51
+ * @param {() => import("../utils/animator.js").default} options.getAnimator
52
+ * @param {() => number[]} options.getInitialDomainSnapshot
53
+ * @param {() => number[]} options.getResetDomain
54
+ * @param {(domain: ScalarDomain | ComplexDomain) => number[]} options.fromComplexInterval
55
+ * @param {() => number[]} options.getGenomeExtent
56
+ */
57
+ constructor({
58
+ getScale,
59
+ getAnimator,
60
+ getInitialDomainSnapshot,
61
+ getResetDomain,
62
+ fromComplexInterval,
63
+ getGenomeExtent,
64
+ }) {
65
+ this.#getScale = getScale;
66
+ this.#getAnimator = getAnimator;
67
+ this.#getInitialDomainSnapshot = getInitialDomainSnapshot;
68
+ this.#getResetDomain = getResetDomain;
69
+ this.#fromComplexInterval = fromComplexInterval;
70
+ this.#getGenomeExtent = getGenomeExtent;
71
+ }
72
+
73
+ getZoomExtent() {
74
+ const scale = this.#getScale();
75
+ const zoom = scale.props.zoom;
76
+ return resolveZoomExtent(
77
+ scale,
78
+ zoom,
79
+ this.#fromComplexInterval,
80
+ this.#getGenomeExtent,
81
+ this.#getInitialDomainSnapshot
82
+ );
83
+ }
84
+
85
+ isZoomable() {
86
+ return this.isZoomingSupported() && !!this.#getScale().props.zoom;
87
+ }
88
+
89
+ isZoomingSupported() {
90
+ return isContinuous(this.#getScale().type);
91
+ }
92
+
93
+ /**
94
+ * Return true if the scale is zoomable and the current domain differs from the initial domain.
95
+ *
96
+ * @returns true if zoomed
97
+ */
98
+ isZoomed() {
99
+ return (
100
+ this.isZoomingSupported() &&
101
+ shallowArrayEquals(
102
+ this.#getResetDomain(),
103
+ this.#getScale().domain()
104
+ )
105
+ );
106
+ }
107
+
108
+ /**
109
+ * Pans (translates) and zooms using a specified scale factor.
110
+ *
111
+ * @param {number} scaleFactor
112
+ * @param {number} scaleAnchor
113
+ * @param {number} pan
114
+ * @returns {boolean} true if the scale was zoomed
115
+ */
116
+ zoom(scaleFactor, scaleAnchor, pan) {
117
+ if (!this.isZoomingSupported()) {
118
+ return false;
119
+ }
120
+
121
+ const scale = this.#getScale();
122
+ const oldDomain = scale.domain();
123
+ let newDomain = applyZoomTransform(
124
+ scale,
125
+ oldDomain,
126
+ scaleFactor,
127
+ scaleAnchor,
128
+ pan
129
+ );
130
+
131
+ // TODO: Use the zoomTo method. Move clamping etc there.
132
+ const zoomExtent = this.getZoomExtent();
133
+ newDomain = clampRange(newDomain, zoomExtent[0], zoomExtent[1]);
134
+
135
+ if ([0, 1].some((i) => newDomain[i] != oldDomain[i])) {
136
+ scale.domain(newDomain);
137
+ return true;
138
+ }
139
+
140
+ return false;
141
+ }
142
+
143
+ /**
144
+ * Immediately zooms to the given interval.
145
+ *
146
+ * @param {NumericDomain | ComplexDomain} domain
147
+ * @param {boolean | number} [duration] an approximate duration for transition.
148
+ * Zero duration zooms immediately. Boolean `true` indicates a default duration.
149
+ */
150
+ async zoomTo(domain, duration = false) {
151
+ if (isBoolean(duration)) {
152
+ duration = duration ? 700 : 0;
153
+ }
154
+
155
+ if (!this.isZoomingSupported()) {
156
+ throw new Error("Not a zoomable scale!");
157
+ }
158
+
159
+ const to = this.#fromComplexInterval(domain);
160
+
161
+ // TODO: Intersect the domain with zoom extent
162
+
163
+ const animator = this.#getAnimator();
164
+
165
+ const scale = this.#getScale();
166
+ const from = /** @type {number[]} */ (scale.domain());
167
+
168
+ if (duration > 0 && from.length == 2) {
169
+ // Spans
170
+ const fw = from[1] - from[0];
171
+ const tw = to[1] - to[0];
172
+
173
+ // Centers
174
+ const fc = from[0] + fw / 2;
175
+ const tc = to[0] + tw / 2;
176
+
177
+ // Constant endpoints. Skip calculation to maintain precision.
178
+ const ac = from[0] == to[0];
179
+ const bc = from[1] == to[1];
180
+
181
+ // TODO: Abort possible previous transition
182
+ await animator.transition({
183
+ duration,
184
+ easingFunction: easeCubicInOut,
185
+ onUpdate: (t) => {
186
+ const w = eerp(fw, tw, t);
187
+ const wt = fw == tw ? t : (fw - w) / (fw - tw);
188
+ const c = wt * tc + (1 - wt) * fc;
189
+ const newDomain = [
190
+ ac ? from[0] : c - w / 2,
191
+ bc ? from[1] : c + w / 2,
192
+ ];
193
+ scale.domain(newDomain);
194
+ },
195
+ });
196
+
197
+ scale.domain(to);
198
+ } else {
199
+ scale.domain(to);
200
+ animator?.requestRender();
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Resets the current domain to the initial one
206
+ *
207
+ * @returns true if the domain was changed
208
+ */
209
+ resetZoom() {
210
+ if (!this.isZoomingSupported()) {
211
+ throw new Error("Not a zoomable scale!");
212
+ }
213
+
214
+ const scale = this.#getScale();
215
+ const oldDomain = scale.domain();
216
+ const newDomain = this.#getResetDomain();
217
+
218
+ if ([0, 1].some((i) => newDomain[i] != oldDomain[i])) {
219
+ scale.domain(newDomain);
220
+ return true;
221
+ }
222
+ return false;
223
+ }
224
+
225
+ /**
226
+ * Returns the zoom level with respect to the reference domain span (the original domain).
227
+ */
228
+ getZoomLevel() {
229
+ // Zoom level makes sense only for user-zoomable scales where zoom extent is defined
230
+ if (this.isZoomable()) {
231
+ return span(this.getZoomExtent()) / span(this.#getScale().domain());
232
+ }
233
+
234
+ return 1.0;
235
+ }
236
+ }
237
+
238
+ /**
239
+ * @param {ScaleWithProps} scale
240
+ * @param {ZoomParams | boolean | undefined} zoom
241
+ * @param {(interval: ScalarDomain | ComplexDomain) => number[]} fromComplexInterval
242
+ * @param {() => number[]} getGenomeExtent
243
+ * @param {() => number[]} getInitialDomainSnapshot
244
+ * @returns {number[]}
245
+ */
246
+ function resolveZoomExtent(
247
+ scale,
248
+ zoom,
249
+ fromComplexInterval,
250
+ getGenomeExtent,
251
+ getInitialDomainSnapshot
252
+ ) {
253
+ if (isZoomParams(zoom)) {
254
+ if (isArray(zoom.extent)) {
255
+ return fromComplexInterval(zoom.extent);
256
+ }
257
+ }
258
+
259
+ if (zoom && scale.props.type == "locus") {
260
+ return getGenomeExtent();
261
+ }
262
+
263
+ // TODO: Perhaps this should be "domain" for index scale and nothing for quantitative.
264
+ // Would behave similarly to Vega-Lite, which doesn't have constraints.
265
+ return getInitialDomainSnapshot();
266
+ }
267
+
268
+ /**
269
+ * @param {ScaleWithProps} scale
270
+ * @param {number[]} domain
271
+ * @param {number} scaleFactor
272
+ * @param {number} scaleAnchor
273
+ * @param {number} pan
274
+ * @returns {number[]}
275
+ */
276
+ function applyZoomTransform(scale, domain, scaleFactor, scaleAnchor, pan) {
277
+ let newDomain = [...domain];
278
+
279
+ /** @type {number} */
280
+ // @ts-ignore
281
+ let anchor = scale.invert(scaleAnchor);
282
+
283
+ if (scale.props.reverse) {
284
+ pan = -pan;
285
+ }
286
+
287
+ if ("align" in scale) {
288
+ anchor += scale.align();
289
+ }
290
+
291
+ // TODO: symlog
292
+ switch (scale.type) {
293
+ case "linear":
294
+ case "index":
295
+ case "locus":
296
+ newDomain = panLinear(newDomain, pan || 0);
297
+ newDomain = zoomLinear(newDomain, anchor, scaleFactor);
298
+ break;
299
+ case "log":
300
+ newDomain = panLog(newDomain, pan || 0);
301
+ newDomain = zoomLog(newDomain, anchor, scaleFactor);
302
+ break;
303
+ case "pow":
304
+ case "sqrt": {
305
+ const powScale =
306
+ /** @type {import("d3-scale").ScalePower<number, number>} */ (
307
+ scale
308
+ );
309
+ newDomain = panPow(newDomain, pan || 0, powScale.exponent());
310
+ newDomain = zoomPow(
311
+ newDomain,
312
+ anchor,
313
+ scaleFactor,
314
+ powScale.exponent()
315
+ );
316
+ break;
317
+ }
318
+ default:
319
+ throw new Error("Zooming is not implemented for: " + scale.type);
320
+ }
321
+
322
+ return newDomain;
323
+ }
324
+
325
+ /**
326
+ * @param {boolean | ZoomParams} zoom
327
+ * @returns {zoom is ZoomParams}
328
+ */
329
+ function isZoomParams(zoom) {
330
+ return isObject(zoom);
331
+ }
332
+
333
+ /**
334
+ * @param {any[]} a
335
+ * @param {any[]} b
336
+ */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scaleInteractionController.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaleInteractionController.test.d.ts","sourceRoot":"","sources":["../../../src/scales/scaleInteractionController.test.js"],"names":[],"mappings":""}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @typedef {import("../spec/channel.js").Channel} Channel
3
+ * @typedef {import("../spec/scale.js").Scale} Scale
4
+ * @typedef {import("./scaleResolution.js").ScaleResolutionMember} ScaleResolutionMember
5
+ */
6
+ /**
7
+ * @param {object} options
8
+ * @param {Channel} options.channel
9
+ * @param {import("../spec/channel.js").Type} options.dataType
10
+ * @param {Set<ScaleResolutionMember>} options.members
11
+ * @param {boolean} options.isExplicitDomain
12
+ * @returns {Scale}
13
+ */
14
+ export function resolveScalePropsBase({ channel, dataType, members, isExplicitDomain, }: {
15
+ channel: Channel;
16
+ dataType: import("../spec/channel.js").Type;
17
+ members: Set<ScaleResolutionMember>;
18
+ isExplicitDomain: boolean;
19
+ }): Scale;
20
+ export type Channel = import("../spec/channel.js").Channel;
21
+ export type Scale = import("../spec/scale.js").Scale;
22
+ export type ScaleResolutionMember = import("./scaleResolution.js").ScaleResolutionMember;
23
+ //# sourceMappingURL=scalePropsResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scalePropsResolver.d.ts","sourceRoot":"","sources":["../../../src/scales/scalePropsResolver.js"],"names":[],"mappings":"AAOA;;;;GAIG;AAEH;;;;;;;GAOG;AACH,yFANG;IAAyB,OAAO,EAAxB,OAAO;IACoC,QAAQ,EAAnD,OAAO,oBAAoB,EAAE,IAAI;IACG,OAAO,EAA3C,GAAG,CAAC,qBAAqB,CAAC;IACT,gBAAgB,EAAjC,OAAO;CACf,GAAU,KAAK,CAiDjB;sBA5DY,OAAO,oBAAoB,EAAE,OAAO;oBACpC,OAAO,kBAAkB,EAAE,KAAK;oCAChC,OAAO,sBAAsB,EAAE,qBAAqB"}
@@ -0,0 +1,74 @@
1
+ import { isDiscrete } from "vega-scale";
2
+
3
+ import mergeObjects from "../utils/mergeObjects.js";
4
+ import { getDefaultScaleProperties } from "../config/scaleDefaults.js";
5
+ import { applyLockedProperties, getDefaultScaleType } from "./scaleRules.js";
6
+ import { INDEX, LOCUS } from "./scaleResolutionConstants.js";
7
+
8
+ /**
9
+ * @typedef {import("../spec/channel.js").Channel} Channel
10
+ * @typedef {import("../spec/scale.js").Scale} Scale
11
+ * @typedef {import("./scaleResolution.js").ScaleResolutionMember} ScaleResolutionMember
12
+ */
13
+
14
+ /**
15
+ * @param {object} options
16
+ * @param {Channel} options.channel
17
+ * @param {import("../spec/channel.js").Type} options.dataType
18
+ * @param {Set<ScaleResolutionMember>} options.members
19
+ * @param {boolean} options.isExplicitDomain
20
+ * @returns {Scale}
21
+ */
22
+ export function resolveScalePropsBase({
23
+ channel,
24
+ dataType,
25
+ members,
26
+ isExplicitDomain,
27
+ }) {
28
+ const propArray = Array.from(members)
29
+ .map((member) => member.channelDef.scale)
30
+ .filter((props) => props !== undefined);
31
+
32
+ // TODO: Disabled scale: https://vega.github.io/vega-lite/docs/scale.html#disable
33
+ const mergedProps = mergeObjects(propArray, "scale", ["domain"]);
34
+ if (mergedProps === null || mergedProps.type == "null") {
35
+ return /** @type {Scale} */ ({ type: "null" });
36
+ }
37
+
38
+ const props = {
39
+ ...getDefaultScaleProperties(channel, dataType, isExplicitDomain),
40
+ ...mergedProps,
41
+ };
42
+
43
+ if (!props.type) {
44
+ props.type = getDefaultScaleType(channel, dataType);
45
+ }
46
+
47
+ // Reverse discrete y axis
48
+ if (
49
+ channel == "y" &&
50
+ isDiscrete(props.type) &&
51
+ props.reverse == undefined
52
+ ) {
53
+ props.reverse = true;
54
+ }
55
+
56
+ if (props.range && props.scheme) {
57
+ delete props.scheme;
58
+ // TODO: Props should be set more intelligently
59
+ }
60
+
61
+ // By default, index and locus scales are zoomable, others are not
62
+ if (!("zoom" in props) && [INDEX, LOCUS].includes(props.type)) {
63
+ props.zoom = true;
64
+ }
65
+
66
+ applyLockedProperties(props, channel);
67
+
68
+ return props;
69
+ }
70
+
71
+ /**
72
+ * @param {Scale} props
73
+ * @param {Channel} channel
74
+ */
@@ -1,5 +1,7 @@
1
1
  /**
2
- * Reconfigures scales, starting from the given view.
2
+ * Reconfigures scale domains, starting from the given view.
3
+ *
4
+ * Use this for data-driven updates where only domains need refreshing.
3
5
  *
4
6
  * TODO: This should be made unnecessary. Collectors should trigger the reconfiguration
5
7
  * for those views that get their data from the collector.
@@ -7,28 +9,24 @@
7
9
  * TODO: This may reconfigure channels that are not affected by the change.
8
10
  * Causes performance issues with domains that are extracted from data.
9
11
  *
10
- * @param {import("./view.js").default | import("./view.js").default[]} fromViews
12
+ * @param {import("../view/view.js").default | import("../view/view.js").default[]} fromViews
11
13
  */
12
- export function reconfigureScales(fromViews: import("./view.js").default | import("./view.js").default[]): void;
13
- export const QUANTITATIVE: "quantitative";
14
- export const ORDINAL: "ordinal";
15
- export const NOMINAL: "nominal";
16
- export const LOCUS: "locus";
17
- export const INDEX: "index";
14
+ export function reconfigureScaleDomains(fromViews: import("../view/view.js").default | import("../view/view.js").default[]): void;
18
15
  /**
19
16
  * @template {ChannelWithScale}[T=ChannelWithScale]
20
17
  *
21
18
  * @typedef {object} ScaleResolutionMember
22
- * @prop {import("./unitView.js").default} view TODO: Get rid of the view reference
19
+ * @prop {import("../view/unitView.js").default} view TODO: Get rid of the view reference
23
20
  * @prop {T} channel
24
21
  * @prop {import("../spec/channel.js").ChannelDefWithScale} channelDef
25
22
  * @prop {(channel: ChannelWithScale, type: import("../spec/channel.js").Type) => DomainArray} dataDomainSource
26
23
  */
27
24
  /**
28
- * Resolution takes care of merging domains and scales from multiple views.
29
- * This class also provides some utility methods for zooming the scales etc..
30
- *
31
- * TODO: This has grown a bit too fat. Consider splitting.
25
+ * Resolves a shared scale for a channel by merging scale properties and domains
26
+ * across participating views, then coordinating range updates and zoom/pan
27
+ * interactions. It is the central wiring point for scale-related state and
28
+ * notifications, while delegating domain aggregation, scale instance setup, and
29
+ * interaction logic to focused helpers.
32
30
  *
33
31
  * @implements {ScaleResolutionApi}
34
32
  */
@@ -38,8 +36,6 @@ export default class ScaleResolution implements ScaleResolutionApi {
38
36
  */
39
37
  constructor(channel: import("../spec/channel.js").Channel);
40
38
  channel: import("../spec/channel.js").Channel;
41
- /** @type {ScaleResolutionMember[]} The involved views */
42
- members: ScaleResolutionMember[];
43
39
  /** @type {import("../spec/channel.js").Type} Data type (quantitative, nominal, etc...) */
44
40
  type: import("../spec/channel.js").Type;
45
41
  /** @type {string} An optional unique identifier for the scale */
@@ -60,29 +56,54 @@ export default class ScaleResolution implements ScaleResolutionApi {
60
56
  */
61
57
  removeEventListener(type: import("../types/scaleResolutionApi.js").ScaleResolutionEventType, listener: import("../types/scaleResolutionApi.js").ScaleResolutionListener): void;
62
58
  /**
63
- * Add a view to this resolution.
64
- * N.B. This is expected to be called in depth-first order
65
- *
66
- * @param {ScaleResolutionMember} newMember
59
+ * @param {ScaleResolutionMember} member
60
+ * @returns {() => boolean}
67
61
  */
68
- addMember(newMember: ScaleResolutionMember): void;
62
+ registerMember(member: ScaleResolutionMember): () => boolean;
69
63
  /**
70
- * Extracts and unions the data domains of all participating views.
64
+ * Reconfigures the scale: updates domain and other settings.
71
65
  *
72
- * @return { DomainArray }
66
+ * Use this when the set of participating members changes (views added or removed),
67
+ * or when scale properties are otherwise re-resolved from the view hierarchy.
73
68
  */
74
- getDataDomain(): import("../utils/domainArray.js").DomainArray;
69
+ reconfigure(): void;
75
70
  /**
76
- * Reconfigures the scale: updates domain and other settings
71
+ * Reconfigures only the effective domain (configured + data-derived).
72
+ *
73
+ * Use this when data changes but the scale membership and properties are stable.
77
74
  */
78
- reconfigure(): void;
75
+ reconfigureDomain(): void;
79
76
  /**
80
77
  * @returns {ScaleWithProps}
81
78
  */
82
79
  get scale(): import("../types/encoder.js").VegaScale & {
83
80
  props: import("../spec/scale.js").Scale;
84
81
  };
82
+ /**
83
+ * Returns the scale instance, creating it if needed.
84
+ *
85
+ * Use this from call sites that may run before explicit initialization.
86
+ *
87
+ * @returns {ScaleWithProps}
88
+ */
89
+ getScale(): import("../types/encoder.js").VegaScale & {
90
+ props: import("../spec/scale.js").Scale;
91
+ };
92
+ /**
93
+ * Initializes the scale instance once resolution has stabilized.
94
+ *
95
+ * @returns {ScaleWithProps}
96
+ */
97
+ initializeScale(): import("../types/encoder.js").VegaScale & {
98
+ props: import("../spec/scale.js").Scale;
99
+ };
85
100
  getDomain(): any[];
101
+ /**
102
+ * Extracts and unions the data domains of all participating views.
103
+ *
104
+ * @return { DomainArray }
105
+ */
106
+ getDataDomain(): import("../utils/domainArray.js").DomainArray;
86
107
  /**
87
108
  * @returns {NumericDomain | ComplexDomain}
88
109
  */
@@ -136,11 +157,6 @@ export default class ScaleResolution implements ScaleResolutionApi {
136
157
  * be configured as pixels, but that is yet to be materialized.
137
158
  */
138
159
  getAxisLength(): number;
139
- /**
140
- *
141
- * @returns {import("../genome/genome.js").default}
142
- */
143
- getGenome(): import("../genome/genome.js").default;
144
160
  /**
145
161
  * Inverts a value in range to a value on domain. Returns an object in
146
162
  * case of locus scale.
@@ -168,9 +184,15 @@ export type ScaleResolutionMember<T extends import("../spec/channel.js").Channel
168
184
  /**
169
185
  * TODO: Get rid of the view reference
170
186
  */
171
- view: import("./unitView.js").default;
187
+ view: import("../view/unitView.js").default;
172
188
  channel: T;
173
189
  channelDef: import("../spec/channel.js").ChannelDefWithScale;
174
190
  dataDomainSource: (channel: import("../spec/channel.js").ChannelWithScale, type: import("../spec/channel.js").Type) => import("../utils/domainArray.js").DomainArray;
175
191
  };
192
+ import { INDEX } from "./scaleResolutionConstants.js";
193
+ import { LOCUS } from "./scaleResolutionConstants.js";
194
+ import { NOMINAL } from "./scaleResolutionConstants.js";
195
+ import { ORDINAL } from "./scaleResolutionConstants.js";
196
+ import { QUANTITATIVE } from "./scaleResolutionConstants.js";
197
+ export { INDEX, LOCUS, NOMINAL, ORDINAL, QUANTITATIVE };
176
198
  //# sourceMappingURL=scaleResolution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaleResolution.d.ts","sourceRoot":"","sources":["../../../src/scales/scaleResolution.js"],"names":[],"mappings":"AA0mBA;;;;;;;;;;;;GAYG;AACH,mDAFW,OAAO,iBAAiB,EAAE,OAAO,GAAG,OAAO,iBAAiB,EAAE,OAAO,EAAE,QA4BjF;AA5mBD;;;;;;;;GAQG;AACH;;;;;;;;GAQG;AACH;IAsCI;;OAEG;IACH,2DAgCC;IA/BG,8CAAsB;IACtB,0FAA0F;IAC1F,MADW,OAAO,oBAAoB,EAAE,IAAI,CAC5B;IAEhB,iEAAiE;IACjE,MADW,MAAM,CACI;IA2CzB,2BASC;IAqBD;;;;;;;OAOG;IACH,4KAEC;IAED;;;OAGG;IACH,+KAEC;IAyED;;;OAGG;IACH,uBAHW,qBAAqB,GACnB,MAAM,OAAO,CAQzB;IA8ED;;;;;OAKG;IACH,oBAGC;IAED;;;;OAIG;IACH,0BAKC;IAkDD;;OAEG;IACH;eAtWkC,OAAO,kBAAkB,EAAE,KAAK;MA6WjE;IAED;;;;;;OAMG;IACH;eAtXkC,OAAO,kBAAkB,EAAE,KAAK;MAwXjE;IAED;;;;OAIG;IACH;eA/XkC,OAAO,kBAAkB,EAAE,KAAK;MAwYjE;IAED,mBAEC;IAED;;;;OAIG;IACH,+DAEC;IAED;;OAEG;IACH,oBAFa,mFAA6B,CAMzC;IAED;;;;OAIG;IACH,oBAEC;IAED;;OAEG;IACH,sBAGC;IAED;;;;;;;OAOG;IACH,kBALW,MAAM,eACN,MAAM,OACN,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;OAMG;IACH,eAJW,mFAA6B,aAC7B,OAAO,GAAG,MAAM,iBAK1B;IAED;;;;OAIG;IACH,qBAEC;IAED;;;;;OAKG;IACH,uBAEC;IAED;;;;;;;OAOG;IACH,wBAoBC;IAED;;;;;OAKG;IACH,uBAFW,MAAM,yDAUhB;IAED;;OAEG;IACH,iBAFW,MAAM,yDAIhB;IAED;;;OAGG;IACH,qBAHW,MAAM,+CAAmB,GACvB,MAAM,CAIlB;IAED;;;OAGG;IACH,8BAHW,kFAA4B,GAC1B,MAAM,EAAE,CAOpB;;CACJ;kCAlkB+B,CAAC,SAApB,6CAAkB;;;;UAGrB,OAAO,qBAAqB,EAAE,OAAO;aACrC,CAAC;gBACD,OAAO,oBAAoB,EAAE,mBAAmB;sBAChD,CAAC,OAAO,+CAAkB,EAAE,IAAI,EAAE,OAAO,oBAAoB,EAAE,IAAI,kDAAgB;;sBArBtF,+BAA+B;sBAA/B,+BAA+B;wBAA/B,+BAA+B;wBAA/B,+BAA+B;6BAA/B,+BAA+B"}