@genome-spy/core 0.67.0 → 0.69.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 (290) hide show
  1. package/dist/bundle/index.es.js +15884 -13130
  2. package/dist/bundle/index.js +130 -149
  3. package/dist/schema.json +6498 -6191
  4. package/dist/src/data/collector.d.ts +20 -0
  5. package/dist/src/data/collector.d.ts.map +1 -1
  6. package/dist/src/data/collector.js +148 -0
  7. package/dist/src/data/dataFlow.d.ts +6 -0
  8. package/dist/src/data/dataFlow.d.ts.map +1 -1
  9. package/dist/src/data/dataFlow.js +20 -0
  10. package/dist/src/data/flowInit.d.ts.map +1 -1
  11. package/dist/src/data/flowInit.js +2 -3
  12. package/dist/src/data/flowNode.d.ts +33 -10
  13. package/dist/src/data/flowNode.d.ts.map +1 -1
  14. package/dist/src/data/flowNode.js +84 -13
  15. package/dist/src/data/flowTestUtils.d.ts +2 -2
  16. package/dist/src/data/flowTestUtils.d.ts.map +1 -1
  17. package/dist/src/data/flowTestUtils.js +5 -4
  18. package/dist/src/data/keyIndex.d.ts +18 -0
  19. package/dist/src/data/keyIndex.d.ts.map +1 -0
  20. package/dist/src/data/keyIndex.js +241 -0
  21. package/dist/src/data/keyIndex.test.d.ts +2 -0
  22. package/dist/src/data/keyIndex.test.d.ts.map +1 -0
  23. package/dist/src/data/sources/dataSource.d.ts.map +1 -1
  24. package/dist/src/data/sources/dataSource.js +7 -3
  25. package/dist/src/data/sources/dataSourceFactory.d.ts +14 -12
  26. package/dist/src/data/sources/dataSourceFactory.d.ts.map +1 -1
  27. package/dist/src/data/sources/dataSourceFactory.js +52 -16
  28. package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
  29. package/dist/src/data/sources/lazy/bigBedSource.js +11 -10
  30. package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
  31. package/dist/src/data/sources/lazy/bigWigSource.js +11 -10
  32. package/dist/src/data/sources/lazy/mockLazySource.d.ts +29 -0
  33. package/dist/src/data/sources/lazy/mockLazySource.d.ts.map +1 -0
  34. package/dist/src/data/sources/lazy/mockLazySource.js +44 -0
  35. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +22 -1
  36. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  37. package/dist/src/data/sources/lazy/singleAxisLazySource.js +34 -2
  38. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  39. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +16 -1
  40. package/dist/src/data/sources/lazy/tabixSource.d.ts +0 -1
  41. package/dist/src/data/sources/lazy/tabixSource.d.ts.map +1 -1
  42. package/dist/src/data/sources/lazy/tabixSource.js +56 -16
  43. package/dist/src/data/sources/sequenceSource.d.ts.map +1 -1
  44. package/dist/src/data/sources/sequenceSource.js +5 -3
  45. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  46. package/dist/src/data/sources/urlSource.js +7 -3
  47. package/dist/src/data/transforms/filter.d.ts +4 -4
  48. package/dist/src/data/transforms/filter.d.ts.map +1 -1
  49. package/dist/src/data/transforms/filter.js +13 -7
  50. package/dist/src/data/transforms/filterScoredLabels.d.ts.map +1 -1
  51. package/dist/src/data/transforms/filterScoredLabels.js +11 -6
  52. package/dist/src/data/transforms/filterScoredLabels.test.d.ts +2 -0
  53. package/dist/src/data/transforms/filterScoredLabels.test.d.ts.map +1 -0
  54. package/dist/src/data/transforms/formula.d.ts +4 -4
  55. package/dist/src/data/transforms/formula.d.ts.map +1 -1
  56. package/dist/src/data/transforms/formula.js +12 -6
  57. package/dist/src/data/transforms/measureText.d.ts +2 -2
  58. package/dist/src/data/transforms/measureText.d.ts.map +1 -1
  59. package/dist/src/data/transforms/measureText.js +16 -12
  60. package/dist/src/data/transforms/stack.d.ts.map +1 -1
  61. package/dist/src/data/transforms/stack.js +1 -0
  62. package/dist/src/data/transforms/transform.d.ts +2 -2
  63. package/dist/src/data/transforms/transform.d.ts.map +1 -1
  64. package/dist/src/data/transforms/transform.js +3 -3
  65. package/dist/src/encoder/accessor.d.ts +51 -4
  66. package/dist/src/encoder/accessor.d.ts.map +1 -1
  67. package/dist/src/encoder/accessor.js +174 -10
  68. package/dist/src/encoder/encoder.d.ts +11 -2
  69. package/dist/src/encoder/encoder.d.ts.map +1 -1
  70. package/dist/src/encoder/encoder.js +29 -9
  71. package/dist/src/encoder/metadataChannels.d.ts +15 -0
  72. package/dist/src/encoder/metadataChannels.d.ts.map +1 -0
  73. package/dist/src/encoder/metadataChannels.js +65 -0
  74. package/dist/src/encoder/metadataChannels.test.d.ts +2 -0
  75. package/dist/src/encoder/metadataChannels.test.d.ts.map +1 -0
  76. package/dist/src/genome/genome.d.ts +8 -0
  77. package/dist/src/genome/genome.d.ts.map +1 -1
  78. package/dist/src/genome/genome.js +16 -1
  79. package/dist/src/genome/scaleLocus.d.ts.map +1 -1
  80. package/dist/src/genome/scaleLocus.js +14 -1
  81. package/dist/src/genomeSpy/containerUi.d.ts +0 -1
  82. package/dist/src/genomeSpy/containerUi.d.ts.map +1 -1
  83. package/dist/src/genomeSpy/containerUi.js +0 -14
  84. package/dist/src/genomeSpy/inputBindingManager.js +1 -1
  85. package/dist/src/genomeSpy/interactionController.d.ts.map +1 -1
  86. package/dist/src/genomeSpy/interactionController.js +7 -1
  87. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts +3 -7
  88. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts.map +1 -1
  89. package/dist/src/genomeSpy/loadingIndicatorManager.js +68 -20
  90. package/dist/src/genomeSpy/loadingStatusRegistry.d.ts +52 -0
  91. package/dist/src/genomeSpy/loadingStatusRegistry.d.ts.map +1 -0
  92. package/dist/src/genomeSpy/loadingStatusRegistry.js +86 -0
  93. package/dist/src/genomeSpy/viewContextFactory.d.ts.map +1 -1
  94. package/dist/src/genomeSpy/viewContextFactory.js +0 -1
  95. package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -1
  96. package/dist/src/genomeSpy/viewDataInit.js +56 -11
  97. package/dist/src/genomeSpy.d.ts +0 -2
  98. package/dist/src/genomeSpy.d.ts.map +1 -1
  99. package/dist/src/genomeSpy.js +47 -27
  100. package/dist/src/gl/glslScaleGenerator.js +1 -1
  101. package/dist/src/marks/mark.d.ts.map +1 -1
  102. package/dist/src/marks/mark.js +40 -41
  103. package/dist/src/marks/markUtils.js +1 -1
  104. package/dist/src/marks/point.d.ts.map +1 -1
  105. package/dist/src/marks/point.js +4 -6
  106. package/dist/src/paramRuntime/expressionCompiler.d.ts +7 -0
  107. package/dist/src/paramRuntime/expressionCompiler.d.ts.map +1 -0
  108. package/dist/src/paramRuntime/expressionCompiler.js +10 -0
  109. package/dist/src/paramRuntime/expressionRef.d.ts +20 -0
  110. package/dist/src/paramRuntime/expressionRef.d.ts.map +1 -0
  111. package/dist/src/paramRuntime/expressionRef.js +95 -0
  112. package/dist/src/paramRuntime/expressionRef.test.d.ts +2 -0
  113. package/dist/src/paramRuntime/expressionRef.test.d.ts.map +1 -0
  114. package/dist/src/paramRuntime/graphRuntime.d.ts +176 -0
  115. package/dist/src/paramRuntime/graphRuntime.d.ts.map +1 -0
  116. package/dist/src/paramRuntime/graphRuntime.js +628 -0
  117. package/dist/src/paramRuntime/graphRuntime.test.d.ts +2 -0
  118. package/dist/src/paramRuntime/graphRuntime.test.d.ts.map +1 -0
  119. package/dist/src/paramRuntime/index.d.ts +9 -0
  120. package/dist/src/paramRuntime/index.d.ts.map +1 -0
  121. package/dist/src/paramRuntime/index.js +8 -0
  122. package/dist/src/paramRuntime/lifecycleRegistry.d.ts +27 -0
  123. package/dist/src/paramRuntime/lifecycleRegistry.d.ts.map +1 -0
  124. package/dist/src/paramRuntime/lifecycleRegistry.js +54 -0
  125. package/dist/src/paramRuntime/paramRuntime.d.ts +165 -0
  126. package/dist/src/paramRuntime/paramRuntime.d.ts.map +1 -0
  127. package/dist/src/paramRuntime/paramRuntime.js +222 -0
  128. package/dist/src/paramRuntime/paramRuntime.test.d.ts +2 -0
  129. package/dist/src/paramRuntime/paramRuntime.test.d.ts.map +1 -0
  130. package/dist/src/paramRuntime/paramStore.d.ts +68 -0
  131. package/dist/src/paramRuntime/paramStore.d.ts.map +1 -0
  132. package/dist/src/paramRuntime/paramStore.js +148 -0
  133. package/dist/src/paramRuntime/paramStore.test.d.ts +2 -0
  134. package/dist/src/paramRuntime/paramStore.test.d.ts.map +1 -0
  135. package/dist/src/paramRuntime/paramUtils.d.ts +86 -0
  136. package/dist/src/paramRuntime/paramUtils.d.ts.map +1 -0
  137. package/dist/src/paramRuntime/paramUtils.js +272 -0
  138. package/dist/src/paramRuntime/selectionStore.d.ts +6 -0
  139. package/dist/src/paramRuntime/selectionStore.d.ts.map +1 -0
  140. package/dist/src/paramRuntime/selectionStore.js +13 -0
  141. package/dist/src/paramRuntime/types.d.ts +16 -0
  142. package/dist/src/paramRuntime/types.d.ts.map +1 -0
  143. package/dist/src/paramRuntime/types.js +25 -0
  144. package/dist/src/paramRuntime/viewParamRuntime.d.ts +164 -0
  145. package/dist/src/paramRuntime/viewParamRuntime.d.ts.map +1 -0
  146. package/dist/src/paramRuntime/viewParamRuntime.js +443 -0
  147. package/dist/src/scale/scale.d.ts +6 -1
  148. package/dist/src/scale/scale.d.ts.map +1 -1
  149. package/dist/src/scale/scale.js +83 -23
  150. package/dist/src/scales/axisResolution.d.ts.map +1 -1
  151. package/dist/src/scales/axisResolution.js +10 -0
  152. package/dist/src/scales/{scaleDomainAggregator.d.ts → domainPlanner.d.ts} +6 -3
  153. package/dist/src/scales/domainPlanner.d.ts.map +1 -0
  154. package/dist/src/scales/{scaleDomainAggregator.js → domainPlanner.js} +128 -10
  155. package/dist/src/scales/domainPlanner.test.d.ts +2 -0
  156. package/dist/src/scales/domainPlanner.test.d.ts.map +1 -0
  157. package/dist/src/scales/scaleInstanceManager.d.ts +6 -3
  158. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
  159. package/dist/src/scales/scaleInstanceManager.js +17 -11
  160. package/dist/src/scales/scaleInteractionController.d.ts +6 -0
  161. package/dist/src/scales/scaleInteractionController.d.ts.map +1 -1
  162. package/dist/src/scales/scaleInteractionController.js +41 -3
  163. package/dist/src/scales/scaleResolution.d.ts +20 -17
  164. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  165. package/dist/src/scales/scaleResolution.js +188 -71
  166. package/dist/src/scales/scaleResolution.test.d.ts.map +1 -1
  167. package/dist/src/selection/selection.d.ts +21 -0
  168. package/dist/src/selection/selection.d.ts.map +1 -1
  169. package/dist/src/selection/selection.js +83 -1
  170. package/dist/src/spec/channel.d.ts +52 -15
  171. package/dist/src/spec/coreSchemaRoot.d.ts +53 -0
  172. package/dist/src/spec/data.d.ts +4 -0
  173. package/dist/src/spec/parameter.d.ts +16 -11
  174. package/dist/src/spec/root.d.ts +1 -1
  175. package/dist/src/spec/testing.d.ts +12 -0
  176. package/dist/src/spec/testing.d.ts.map +1 -0
  177. package/dist/src/spec/testing.js +20 -0
  178. package/dist/src/spec/view.d.ts +157 -41
  179. package/dist/src/styles/genome-spy.css +3 -31
  180. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  181. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  182. package/dist/src/styles/genome-spy.css.js +0 -29
  183. package/dist/src/tooltip/dataTooltipHandler.d.ts +1 -1
  184. package/dist/src/tooltip/dataTooltipHandler.js +23 -32
  185. package/dist/src/tooltip/dataTooltipHandler.test.d.ts +2 -0
  186. package/dist/src/tooltip/dataTooltipHandler.test.d.ts.map +1 -0
  187. package/dist/src/tooltip/flattenDatumRows.d.ts +13 -0
  188. package/dist/src/tooltip/flattenDatumRows.d.ts.map +1 -0
  189. package/dist/src/tooltip/flattenDatumRows.js +47 -0
  190. package/dist/src/tooltip/flattenDatumRows.test.d.ts +2 -0
  191. package/dist/src/tooltip/flattenDatumRows.test.d.ts.map +1 -0
  192. package/dist/src/tooltip/refseqGeneTooltipHandler.d.ts +1 -1
  193. package/dist/src/tooltip/refseqGeneTooltipHandler.js +7 -1
  194. package/dist/src/tooltip/tooltipContext.d.ts +13 -0
  195. package/dist/src/tooltip/tooltipContext.d.ts.map +1 -0
  196. package/dist/src/tooltip/tooltipContext.js +543 -0
  197. package/dist/src/tooltip/tooltipContext.test.d.ts +2 -0
  198. package/dist/src/tooltip/tooltipContext.test.d.ts.map +1 -0
  199. package/dist/src/tooltip/tooltipHandler.d.ts +40 -1
  200. package/dist/src/tooltip/tooltipHandler.d.ts.map +1 -1
  201. package/dist/src/tooltip/tooltipHandler.ts +62 -1
  202. package/dist/src/types/encoder.d.ts +38 -3
  203. package/dist/src/types/rendering.d.ts +4 -3
  204. package/dist/src/types/viewContext.d.ts +0 -14
  205. package/dist/src/utils/inputBinding.d.ts +10 -2
  206. package/dist/src/utils/inputBinding.d.ts.map +1 -1
  207. package/dist/src/utils/inputBinding.js +12 -3
  208. package/dist/src/utils/throttle.d.ts +4 -1
  209. package/dist/src/utils/throttle.d.ts.map +1 -1
  210. package/dist/src/utils/throttle.js +54 -23
  211. package/dist/src/utils/throttle.test.d.ts +2 -0
  212. package/dist/src/utils/throttle.test.d.ts.map +1 -0
  213. package/dist/src/utils/transition.d.ts +21 -0
  214. package/dist/src/utils/transition.d.ts.map +1 -1
  215. package/dist/src/utils/transition.js +28 -0
  216. package/dist/src/utils/ui/tooltip.d.ts.map +1 -1
  217. package/dist/src/utils/ui/tooltip.js +7 -1
  218. package/dist/src/utils/ui/tooltip.test.d.ts +2 -0
  219. package/dist/src/utils/ui/tooltip.test.d.ts.map +1 -0
  220. package/dist/src/view/axisGridView.d.ts.map +1 -1
  221. package/dist/src/view/axisGridView.js +22 -5
  222. package/dist/src/view/axisView.d.ts.map +1 -1
  223. package/dist/src/view/axisView.js +20 -5
  224. package/dist/src/view/concatView.js +3 -3
  225. package/dist/src/view/containerMutationHelper.js +1 -1
  226. package/dist/src/view/containerView.d.ts +9 -5
  227. package/dist/src/view/containerView.d.ts.map +1 -1
  228. package/dist/src/view/containerView.js +34 -9
  229. package/dist/src/view/dataReadiness.d.ts +46 -0
  230. package/dist/src/view/dataReadiness.d.ts.map +1 -0
  231. package/dist/src/view/dataReadiness.js +267 -0
  232. package/dist/src/view/dataReadiness.test.d.ts +2 -0
  233. package/dist/src/view/dataReadiness.test.d.ts.map +1 -0
  234. package/dist/src/view/facetView.d.ts.map +1 -1
  235. package/dist/src/view/facetView.js +7 -5
  236. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  237. package/dist/src/view/flowBuilder.js +17 -4
  238. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  239. package/dist/src/view/gridView/gridChild.js +16 -3
  240. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  241. package/dist/src/view/gridView/gridView.js +119 -2
  242. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  243. package/dist/src/view/gridView/scrollbar.js +3 -0
  244. package/dist/src/view/gridView/selectionRect.d.ts +6 -10
  245. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  246. package/dist/src/view/gridView/selectionRect.js +22 -24
  247. package/dist/src/view/gridView/separatorView.d.ts +51 -0
  248. package/dist/src/view/gridView/separatorView.d.ts.map +1 -0
  249. package/dist/src/view/gridView/separatorView.js +275 -0
  250. package/dist/src/view/layerView.d.ts.map +1 -1
  251. package/dist/src/view/layerView.js +7 -5
  252. package/dist/src/view/layout/flexLayout.d.ts +0 -30
  253. package/dist/src/view/layout/flexLayout.d.ts.map +1 -1
  254. package/dist/src/view/layout/flexLayout.js +0 -86
  255. package/dist/src/view/multiscale.d.ts +35 -0
  256. package/dist/src/view/multiscale.d.ts.map +1 -0
  257. package/dist/src/view/multiscale.js +233 -0
  258. package/dist/src/view/multiscale.test.d.ts +2 -0
  259. package/dist/src/view/multiscale.test.d.ts.map +1 -0
  260. package/dist/src/view/testUtils.d.ts.map +1 -1
  261. package/dist/src/view/testUtils.js +6 -1
  262. package/dist/src/view/unitView.d.ts +8 -13
  263. package/dist/src/view/unitView.d.ts.map +1 -1
  264. package/dist/src/view/unitView.js +120 -45
  265. package/dist/src/view/view.d.ts +27 -18
  266. package/dist/src/view/view.d.ts.map +1 -1
  267. package/dist/src/view/view.js +298 -37
  268. package/dist/src/view/viewFactory.d.ts +0 -12
  269. package/dist/src/view/viewFactory.d.ts.map +1 -1
  270. package/dist/src/view/viewFactory.js +55 -25
  271. package/dist/src/view/viewParamRuntime.test.d.ts +2 -0
  272. package/dist/src/view/viewParamRuntime.test.d.ts.map +1 -0
  273. package/dist/src/view/viewSelectors.d.ts +148 -0
  274. package/dist/src/view/viewSelectors.d.ts.map +1 -0
  275. package/dist/src/view/viewSelectors.js +776 -0
  276. package/dist/src/view/viewSelectors.test.d.ts +2 -0
  277. package/dist/src/view/viewSelectors.test.d.ts.map +1 -0
  278. package/dist/src/view/viewUtils.d.ts +0 -8
  279. package/dist/src/view/viewUtils.d.ts.map +1 -1
  280. package/dist/src/view/viewUtils.js +1 -21
  281. package/package.json +4 -4
  282. package/dist/src/scales/scaleDomainAggregator.d.ts.map +0 -1
  283. package/dist/src/scales/scaleDomainAggregator.test.d.ts +0 -2
  284. package/dist/src/scales/scaleDomainAggregator.test.d.ts.map +0 -1
  285. package/dist/src/spec/sampleView.d.ts +0 -197
  286. package/dist/src/view/paramMediator.d.ts +0 -149
  287. package/dist/src/view/paramMediator.d.ts.map +0 -1
  288. package/dist/src/view/paramMediator.js +0 -478
  289. package/dist/src/view/paramMediator.test.d.ts +0 -2
  290. package/dist/src/view/paramMediator.test.d.ts.map +0 -1
@@ -0,0 +1,233 @@
1
+ import { isArray, isObject } from "vega-util";
2
+ import { isExprRef } from "../paramRuntime/paramUtils.js";
3
+
4
+ const DEFAULT_FADE = 0.5;
5
+
6
+ /**
7
+ * @typedef {"unitsPerPixel"} MultiscaleMetric
8
+ * @typedef {"x" | "y" | "auto"} MultiscaleChannel
9
+ * @typedef {number | import("../spec/parameter.js").ExprRef} StopValue
10
+ *
11
+ * @typedef {{
12
+ * metric: MultiscaleMetric;
13
+ * values: StopValue[];
14
+ * channel: MultiscaleChannel;
15
+ * fade: number;
16
+ * }} ParsedStops
17
+ */
18
+
19
+ /**
20
+ * @param {object} spec
21
+ * @returns {spec is import("../spec/view.js").MultiscaleSpec}
22
+ */
23
+ export function isMultiscaleSpec(spec) {
24
+ return "multiscale" in spec && isArray(spec.multiscale);
25
+ }
26
+
27
+ /**
28
+ * Converts a multiscale spec into a regular layer spec by wrapping each stage
29
+ * into a generated opacity layer.
30
+ *
31
+ * @param {import("../spec/view.js").MultiscaleSpec} spec
32
+ * @returns {import("../spec/view.js").LayerSpec}
33
+ */
34
+ export function normalizeMultiscaleSpec(spec) {
35
+ if (!spec.multiscale.length) {
36
+ throw new Error('"multiscale" must contain at least one child view.');
37
+ }
38
+
39
+ const parsedStops = parseStops(spec.stops, spec.multiscale.length);
40
+
41
+ /** @type {import("../spec/view.js").LayerSpec["layer"]} */
42
+ const layer = spec.multiscale.map((child, i) => {
43
+ if (spec.multiscale.length === 1) {
44
+ return child;
45
+ }
46
+
47
+ return {
48
+ opacity: createStageOpacity(i, spec.multiscale.length, parsedStops),
49
+ layer: [child],
50
+ };
51
+ });
52
+
53
+ const passThrough = { ...spec };
54
+ delete passThrough.multiscale;
55
+ delete passThrough.stops;
56
+
57
+ return {
58
+ ...passThrough,
59
+ layer,
60
+ };
61
+ }
62
+
63
+ /**
64
+ * @param {import("../spec/view.js").MultiscaleStopsDef} stops
65
+ * @param {number} stageCount
66
+ * @returns {ParsedStops}
67
+ */
68
+ function parseStops(stops, stageCount) {
69
+ /** @type {MultiscaleMetric} */
70
+ let metric = "unitsPerPixel";
71
+ /** @type {StopValue[]} */
72
+ let values;
73
+ /** @type {MultiscaleChannel} */
74
+ let channel = "auto";
75
+ let fade = DEFAULT_FADE;
76
+
77
+ if (isArray(stops)) {
78
+ values = parseStopValues(stops, stageCount, "stops");
79
+ } else if (isObject(stops)) {
80
+ metric = stops.metric ?? "unitsPerPixel";
81
+ values = parseStopValues(stops.values, stageCount, "stops.values");
82
+ channel = stops.channel ?? "auto";
83
+ fade = stops.fade ?? DEFAULT_FADE;
84
+ } else {
85
+ throw new Error('"stops" must be an array or an object with "values".');
86
+ }
87
+
88
+ if (metric !== "unitsPerPixel") {
89
+ throw new Error(
90
+ 'Only "unitsPerPixel" is supported for "stops.metric" in multiscale.'
91
+ );
92
+ }
93
+
94
+ if (!["x", "y", "auto"].includes(channel)) {
95
+ throw new Error('"stops.channel" must be one of "x", "y", or "auto".');
96
+ }
97
+
98
+ if (!Number.isFinite(fade) || fade < 0 || fade > 0.5) {
99
+ throw new Error(
100
+ '"stops.fade" must be a finite number in range [0, 0.5].'
101
+ );
102
+ }
103
+
104
+ values.forEach((value, index) => {
105
+ if (!isExprRef(value) && (!Number.isFinite(value) || value <= 0)) {
106
+ throw new Error(
107
+ "Invalid stop value at index " +
108
+ index +
109
+ ". Stop values must be positive finite numbers."
110
+ );
111
+ }
112
+ });
113
+
114
+ if (!values.some(isExprRef)) {
115
+ const numericValues = /** @type {number[]} */ (values);
116
+
117
+ for (let i = 1; i < numericValues.length; i++) {
118
+ if (numericValues[i - 1] <= numericValues[i]) {
119
+ throw new Error(
120
+ '"stops.values" must be strictly decreasing for "unitsPerPixel".'
121
+ );
122
+ }
123
+ }
124
+
125
+ for (let i = 0; i < numericValues.length - 1; i++) {
126
+ const leftLower = numericValues[i] * (1 - fade);
127
+ const rightUpper = numericValues[i + 1] * (1 + fade);
128
+ if (leftLower <= rightUpper) {
129
+ throw new Error(
130
+ "Adjacent transitions overlap. Reduce fade or increase stop spacing."
131
+ );
132
+ }
133
+ }
134
+ }
135
+
136
+ return {
137
+ metric,
138
+ values,
139
+ channel,
140
+ fade,
141
+ };
142
+ }
143
+
144
+ /**
145
+ * @param {unknown} rawValues
146
+ * @param {number} stageCount
147
+ * @param {string} path
148
+ * @returns {StopValue[]}
149
+ */
150
+ function parseStopValues(rawValues, stageCount, path) {
151
+ if (!isArray(rawValues)) {
152
+ throw new Error(
153
+ '"' + path + '" must be an array of numbers or ExprRefs.'
154
+ );
155
+ }
156
+
157
+ const expectedStopCount = stageCount - 1;
158
+ if (rawValues.length !== expectedStopCount) {
159
+ throw new Error(
160
+ "Invalid stop count for multiscale. Expected " +
161
+ expectedStopCount +
162
+ ", got " +
163
+ rawValues.length +
164
+ "."
165
+ );
166
+ }
167
+
168
+ for (const value of rawValues) {
169
+ if (!isExprRef(value) && !Number.isFinite(value)) {
170
+ throw new Error(
171
+ '"' + path + '" must contain only numbers or ExprRefs.'
172
+ );
173
+ }
174
+ }
175
+
176
+ return /** @type {StopValue[]} */ (rawValues);
177
+ }
178
+
179
+ /**
180
+ * @param {number} stageIndex
181
+ * @param {number} stageCount
182
+ * @param {ParsedStops} stops
183
+ * @returns {import("../spec/view.js").DynamicOpacity}
184
+ */
185
+ function createStageOpacity(stageIndex, stageCount, stops) {
186
+ /** @type {StopValue[]} */
187
+ let unitsPerPixel;
188
+ /** @type {number[]} */
189
+ let values;
190
+ const transitions = stops.values.map((stop) => ({
191
+ hi: scaleStop(stop, 1 + stops.fade),
192
+ lo: scaleStop(stop, 1 - stops.fade),
193
+ }));
194
+
195
+ if (stageIndex === 0) {
196
+ unitsPerPixel = [transitions[0].hi, transitions[0].lo];
197
+ } else if (stageIndex === stageCount - 1) {
198
+ const last = transitions.at(-1);
199
+ unitsPerPixel = [last.hi, last.lo];
200
+ } else {
201
+ const previous = transitions[stageIndex - 1];
202
+ const next = transitions[stageIndex];
203
+
204
+ unitsPerPixel = [previous.hi, previous.lo, next.hi, next.lo];
205
+ }
206
+
207
+ if (stageIndex === 0) {
208
+ values = [1, 0];
209
+ } else if (stageIndex === stageCount - 1) {
210
+ values = [0, 1];
211
+ } else {
212
+ values = [0, 1, 1, 0];
213
+ }
214
+
215
+ return {
216
+ channel: stops.channel,
217
+ unitsPerPixel,
218
+ values,
219
+ };
220
+ }
221
+
222
+ /**
223
+ * @param {StopValue} stop
224
+ * @param {number} factor
225
+ * @returns {StopValue}
226
+ */
227
+ function scaleStop(stop, factor) {
228
+ if (isExprRef(stop)) {
229
+ return { expr: "(" + stop.expr + ") * " + factor };
230
+ } else {
231
+ return stop * factor;
232
+ }
233
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=multiscale.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiscale.test.d.ts","sourceRoot":"","sources":["../../../src/view/multiscale.test.js"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../../src/view/testUtils.js"],"names":[],"mappings":"AAoBA;;;GAGG;AACH,2DAHW,OAAO,kBAAkB,EAAE,kBAAkB,6CA+DvD;AAGS,uBAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,uBAAuB,OAAO,kBAAkB,EAAE,kBAAkB,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAgBhL,oCAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,YAAY,WAAW,YAAY;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAC,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;;;;;uBAnGpL,OAAO,iBAAiB,EAAE,QAAQ;;;;;0BAClC,OAAO,yBAAyB,EAAE,OAAO"}
1
+ {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../../src/view/testUtils.js"],"names":[],"mappings":"AAoBA;;;GAGG;AACH,2DAHW,OAAO,kBAAkB,EAAE,kBAAkB,6CAoEvD;AAGS,uBAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,uBAAuB,OAAO,kBAAkB,EAAE,kBAAkB,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAgBhL,oCAAC,CAAC,SAAS,OAAO,WAAW,EAAE,OAAO,QAAQ,QAAQ,aAAa;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,YAAY,WAAW,YAAY;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAC,GAAK,OAAO,CAAC,CAAC,CAAC,CAAA;;;;;uBAxGpL,OAAO,iBAAiB,EAAE,QAAQ;;;;;0BAClC,OAAO,yBAAyB,EAAE,OAAO"}
@@ -38,6 +38,8 @@ export function createTestViewContext(viewFactoryOptions = {}) {
38
38
  ],
39
39
  });
40
40
 
41
+ const dataFlow = new DataFlow();
42
+
41
43
  // @ts-expect-error
42
44
  const c = /** @type {ViewContext} */ ({
43
45
  createOrImportView: async function (
@@ -55,7 +57,7 @@ export function createTestViewContext(viewFactoryOptions = {}) {
55
57
  );
56
58
  },
57
59
 
58
- dataFlow: new DataFlow(),
60
+ dataFlow,
59
61
  genomeStore,
60
62
 
61
63
  fontManager: new BmFontManager(),
@@ -78,6 +80,9 @@ export function createTestViewContext(viewFactoryOptions = {}) {
78
80
 
79
81
  isViewConfiguredVisible: () => true,
80
82
 
83
+ addBroadcastListener: () => undefined,
84
+ removeBroadcastListener: () => undefined,
85
+
81
86
  //...partialContext,
82
87
  });
83
88
 
@@ -33,25 +33,20 @@ export default class UnitView extends View {
33
33
  * @param {Channel} channel
34
34
  */
35
35
  getDataAccessor(channel: import("../spec/channel.js").Channel): import("../types/encoder.js").Accessor<import("../spec/channel.js").Scalar>;
36
+ /**
37
+ * Returns data accessors configured for the `search` channel.
38
+ *
39
+ * @returns {import("vega-util").AccessorFn[]}
40
+ */
41
+ getSearchAccessors(): import("vega-util").AccessorFn[];
36
42
  /**
37
43
  * Returns a collector that is associated with this view.
38
44
  */
39
45
  getCollector(): import("../data/collector.js").default;
40
46
  /**
41
- * Extracts the domain from the data.
42
- *
43
- * TODO: Optimize! Now this performs redundant work if multiple views share the same collector.
44
- * Also, all relevant fields should be processed in one iteration: https://jsbench.me/y5kkqy52jo/1
45
- * In fact, domain extraction could be a responsibility of the collector: As it handles data items,
46
- * it extracts domains for all fields (and data types) that need extracted domains.
47
- * Alternatively, extractor nodes could be added to the data flow, just like Vega does
48
- * (with aggregate and extent).
49
- *
50
- * @param {Channel} channel
51
- * @param {import("../spec/channel.js").Type} type
52
- * @returns {DomainArray}
47
+ * Registers collector subscriptions that keep scale domains up to date.
53
48
  */
54
- extractDataDomain(channel: import("../spec/channel.js").Channel, type: import("../spec/channel.js").Type): import("../utils/domainArray.js").DomainArray;
49
+ registerDomainSubscriptions(): void;
55
50
  getZoomLevel(): number;
56
51
  /**
57
52
  * @param {string} channel
@@ -1 +1 @@
1
- {"version":3,"file":"unitView.d.ts","sourceRoot":"","sources":["../../../src/view/unitView.js"],"names":[],"mappings":"AA6BA;;;;GAIG;AACH,wBAHU,MAAM,CAAC,OAAO,iBAAiB,EAAE,QAAQ,EAAE,cAAc,kBAAkB,EAAE,OAAO,CAAC,CAc7F;AAEF;IAeI;;;;;;;;OAQG;IACH,kBAPW,OAAO,iBAAiB,EAAE,QAAQ,WAClC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,WAAW,EAAE,OAAO,QAC3B,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,EAyCzC;IApCG,yCAAgB;IAIZ,iDAAiD;IACjD,MADW,OAAO,kBAAkB,EAAE,OAAO,CACnB;IAoKlC,2DAIC;IAgBD;;;;;OAKG;IAEH,iEAyJC;IAUD;;;;;OAKG;IACH,4IAMC;IAkBD;;OAEG;IACH,uDAEC;IAED;;;;;;;;;;;;;OAaG;IACH,uEAHW,OAAO,oBAAoB,EAAE,IAAI,iDAqB3C;IAED,uBAQC;IAgBD;;;;OAIG;IACH,8BAJW,MAAM,+DAEJ,OAAO,iBAAiB,EAAE,kBAAkB,CAKxD;;CACJ;iBAvgBgB,WAAW"}
1
+ {"version":3,"file":"unitView.d.ts","sourceRoot":"","sources":["../../../src/view/unitView.js"],"names":[],"mappings":"AA+BA;;;;GAIG;AACH,wBAHU,MAAM,CAAC,OAAO,iBAAiB,EAAE,QAAQ,EAAE,cAAc,kBAAkB,EAAE,OAAO,CAAC,CAc7F;AAEF;IAwBI;;;;;;;;OAQG;IACH,kBAPW,OAAO,iBAAiB,EAAE,QAAQ,WAClC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,WAAW,EAAE,OAAO,QAC3B,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,EAyCzC;IApCG,yCAAgB;IAIZ,iDAAiD;IACjD,MADW,OAAO,kBAAkB,EAAE,OAAO,CACnB;IAyKlC,2DAIC;IAoBD;;;;;OAKG;IAEH,iEAqJC;IAUD;;;;;OAKG;IACH,4IAMC;IAED;;;;OAIG;IACH,sBAFa,OAAO,WAAW,EAAE,UAAU,EAAE,CAS5C;IAkBD;;OAEG;IACH,uDAEC;IAED;;OAEG;IACH,oCA0EC;IAED,uBAQC;IAgBD;;;;OAIG;IACH,8BAJW,MAAM,+DAEJ,OAAO,iBAAiB,EAAE,kBAAkB,CAKxD;;CACJ;iBAllBgB,WAAW"}
@@ -14,7 +14,7 @@ import {
14
14
  isPrimaryPositionalChannel,
15
15
  isValueDefWithCondition,
16
16
  } from "../encoder/encoder.js";
17
- import createDomain from "../utils/domainArray.js";
17
+ import { isScaleAccessor } from "../encoder/accessor.js";
18
18
  import AxisResolution from "../scales/axisResolution.js";
19
19
  import View from "./view.js";
20
20
  import {
@@ -24,8 +24,10 @@ import {
24
24
  isPointSelectionConfig,
25
25
  updateMultiPointSelection,
26
26
  } from "../selection/selection.js";
27
+ import { getEncodingSearchFields } from "../encoder/metadataChannels.js";
27
28
  import { UNIQUE_ID_KEY } from "../data/transforms/identifier.js";
28
29
  import { createEventFilterFunction } from "../utils/expression.js";
30
+ import { field } from "../utils/field.js";
29
31
 
30
32
  /**
31
33
  *
@@ -48,7 +50,6 @@ export const markTypes = {
48
50
  export default class UnitView extends View {
49
51
  /**
50
52
  * @typedef {import("../spec/channel.js").Channel} Channel
51
- * @typedef {import("../utils/domainArray.js").DomainArray} DomainArray
52
53
  * @typedef {import("../spec/view.js").ResolutionTarget} ResolutionTarget
53
54
  * @typedef {((datum: import("../data/flowNode.js").Datum) => import("../spec/channel.js").Scalar) & { fieldDef: import("../spec/channel.js").FieldDef}} FieldAccessor
54
55
  *
@@ -60,6 +61,16 @@ export default class UnitView extends View {
60
61
  */
61
62
  #zoomLevelSetter;
62
63
 
64
+ /**
65
+ * @type {boolean}
66
+ */
67
+ #domainSubscriptionsRegistered = false;
68
+
69
+ /**
70
+ * @type {import("vega-util").AccessorFn[] | null}
71
+ */
72
+ #searchAccessors = null;
73
+
63
74
  /**
64
75
  *
65
76
  * @param {import("../spec/view.js").UnitSpec} spec
@@ -84,7 +95,7 @@ export default class UnitView extends View {
84
95
 
85
96
  this.resolve();
86
97
 
87
- this.#zoomLevelSetter = this.paramMediator.allocateSetter(
98
+ this.#zoomLevelSetter = this.paramRuntime.allocateSetter(
88
99
  "zoomLevel",
89
100
  1.0
90
101
  );
@@ -111,7 +122,7 @@ export default class UnitView extends View {
111
122
  }
112
123
 
113
124
  #setupPointSelection() {
114
- for (const [name, param] of this.paramMediator.paramConfigs) {
125
+ for (const [name, param] of this.paramRuntime.paramConfigs) {
115
126
  if (!("select" in param)) {
116
127
  continue;
117
128
  }
@@ -134,7 +145,12 @@ export default class UnitView extends View {
134
145
  const none = 0;
135
146
  let lastId = none;
136
147
 
137
- const setter = this.paramMediator.getSetter(name);
148
+ const setter = (
149
+ /** @type {any} */
150
+ selection
151
+ ) => {
152
+ this.paramRuntime.setValue(name, selection);
153
+ };
138
154
 
139
155
  const getHoveredDatum = () => {
140
156
  const h = this.context.getCurrentHover();
@@ -164,7 +180,7 @@ export default class UnitView extends View {
164
180
  if (toggle) {
165
181
  if (datum) {
166
182
  const previousSelection =
167
- this.paramMediator.getValue(name);
183
+ this.paramRuntime.getValue(name);
168
184
  selection = updateMultiPointSelection(
169
185
  previousSelection,
170
186
  {
@@ -253,6 +269,10 @@ export default class UnitView extends View {
253
269
  const encoding = super.getEncoding();
254
270
  const supportedChannels = this.mark.getSupportedChannels();
255
271
  for (const channel of Object.keys(encoding)) {
272
+ if (channel === "key") {
273
+ continue;
274
+ }
275
+
256
276
  if (!supportedChannels.includes(channel)) {
257
277
  delete encoding[channel];
258
278
  }
@@ -284,6 +304,10 @@ export default class UnitView extends View {
284
304
  continue;
285
305
  }
286
306
 
307
+ if (Array.isArray(channelDef)) {
308
+ continue;
309
+ }
310
+
287
311
  /** @type {import("../spec/channel.js").ChannelDefWithScale} */
288
312
  let channelDefWithScale;
289
313
 
@@ -392,23 +416,14 @@ export default class UnitView extends View {
392
416
  });
393
417
  }
394
418
 
395
- const dataDomainSource =
396
- this.getLayoutAncestors()
397
- // TODO: Should check until the resolved scale resolution
398
- .some(
399
- (view) => !view.options.contributesToScaleDomain
400
- ) ||
401
- (isChannelDefWithScale(channelDefWithScale) &&
402
- channelDefWithScale.contributesToScaleDomain === false)
403
- ? undefined
404
- : this.extractDataDomain.bind(this);
419
+ const contributesToDomain = !this.isDomainInert();
405
420
 
406
421
  const resolution = view.resolutions[type][targetChannel];
407
422
  const unregister = resolution.registerMember({
408
423
  view: this,
409
424
  channel,
410
425
  channelDef: channelDefWithScale,
411
- dataDomainSource,
426
+ contributesToDomain,
412
427
  });
413
428
  this.registerDisposer(() => {
414
429
  // Unregister returns true when it removed the last member.
@@ -416,6 +431,7 @@ export default class UnitView extends View {
416
431
  unregister() &&
417
432
  view.resolutions[type][targetChannel] === resolution
418
433
  ) {
434
+ resolution.dispose();
419
435
  delete view.resolutions[type][targetChannel];
420
436
  }
421
437
  });
@@ -445,6 +461,20 @@ export default class UnitView extends View {
445
461
  return encoders[channel]?.dataAccessor;
446
462
  }
447
463
 
464
+ /**
465
+ * Returns data accessors configured for the `search` channel.
466
+ *
467
+ * @returns {import("vega-util").AccessorFn[]}
468
+ */
469
+ getSearchAccessors() {
470
+ if (!this.#searchAccessors) {
471
+ const fields = getEncodingSearchFields(this.getEncoding()) ?? [];
472
+ this.#searchAccessors = fields.map((fieldName) => field(fieldName));
473
+ }
474
+
475
+ return this.#searchAccessors;
476
+ }
477
+
448
478
  /**
449
479
  * Returns an accessor that returns a (composite) key for partitioning the data
450
480
  *
@@ -469,37 +499,82 @@ export default class UnitView extends View {
469
499
  }
470
500
 
471
501
  /**
472
- * Extracts the domain from the data.
473
- *
474
- * TODO: Optimize! Now this performs redundant work if multiple views share the same collector.
475
- * Also, all relevant fields should be processed in one iteration: https://jsbench.me/y5kkqy52jo/1
476
- * In fact, domain extraction could be a responsibility of the collector: As it handles data items,
477
- * it extracts domains for all fields (and data types) that need extracted domains.
478
- * Alternatively, extractor nodes could be added to the data flow, just like Vega does
479
- * (with aggregate and extent).
480
- *
481
- * @param {Channel} channel
482
- * @param {import("../spec/channel.js").Type} type
483
- * @returns {DomainArray}
502
+ * Registers collector subscriptions that keep scale domains up to date.
484
503
  */
485
- extractDataDomain(channel, type) {
486
- /** @type {DomainArray} */
487
- let domain = createDomain(type);
488
-
489
- (this.mark.encoders[channel]?.accessors ?? [])
490
- .filter((a) => a.scaleChannel)
491
- .forEach((accessor) => {
492
- if (accessor.constant) {
493
- domain.extend(accessor({}));
494
- } else {
495
- const collector = this.getCollector();
496
- if (collector?.completed) {
497
- collector.visitData((d) => domain.extend(accessor(d)));
498
- }
504
+ registerDomainSubscriptions() {
505
+ if (this.#domainSubscriptionsRegistered) {
506
+ return;
507
+ }
508
+
509
+ if (this.isDomainInert()) {
510
+ return;
511
+ }
512
+
513
+ const collector = this.getCollector();
514
+ if (!collector) {
515
+ return;
516
+ }
517
+
518
+ const encoders = this.mark.encoders;
519
+ if (!encoders) {
520
+ throw new Error("Encoders are not initialized!");
521
+ }
522
+
523
+ this.#domainSubscriptionsRegistered = true;
524
+
525
+ /** @type {Map<import("../scales/scaleResolution.js").default, Set<import("../types/encoder.js").ScaleAccessor>>} */
526
+ const accessorsByResolution = new Map();
527
+
528
+ for (const encoder of Object.values(encoders)) {
529
+ if (!encoder) {
530
+ continue;
531
+ }
532
+
533
+ const accessors = encoder.accessors ?? [];
534
+ if (accessors.length === 0) {
535
+ continue;
536
+ }
537
+
538
+ for (const accessor of accessors) {
539
+ if (!isScaleAccessor(accessor)) {
540
+ continue;
541
+ }
542
+ if (accessor.channelDef.domainInert) {
543
+ continue;
544
+ }
545
+ const resolution = this.getScaleResolution(
546
+ accessor.scaleChannel
547
+ );
548
+ if (!resolution) {
549
+ throw new Error(
550
+ "Missing scale resolution for channel: " +
551
+ accessor.scaleChannel
552
+ );
499
553
  }
500
- });
501
554
 
502
- return domain;
555
+ let accessorsForResolution =
556
+ accessorsByResolution.get(resolution);
557
+ if (!accessorsForResolution) {
558
+ accessorsForResolution = new Set();
559
+ accessorsByResolution.set(
560
+ resolution,
561
+ accessorsForResolution
562
+ );
563
+ }
564
+ accessorsForResolution.add(accessor);
565
+ }
566
+ }
567
+
568
+ for (const [resolution, accessors] of accessorsByResolution) {
569
+ if (accessors.size === 0) {
570
+ continue;
571
+ }
572
+ const unregister = resolution.registerCollectorSubscriptions(
573
+ collector,
574
+ accessors
575
+ );
576
+ this.registerDisposer(unregister);
577
+ }
503
578
  }
504
579
 
505
580
  getZoomLevel() {