@genome-spy/core 0.48.1 → 0.49.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 (241) hide show
  1. package/dist/bundle/index.es.js +7485 -7097
  2. package/dist/bundle/index.js +124 -111
  3. package/dist/schema.json +838 -344
  4. package/dist/src/data/collector.d.ts +10 -8
  5. package/dist/src/data/collector.d.ts.map +1 -1
  6. package/dist/src/data/collector.js +131 -33
  7. package/dist/src/data/collector.test.d.ts +2 -0
  8. package/dist/src/data/collector.test.d.ts.map +1 -0
  9. package/dist/src/data/collector.test.js +55 -1
  10. package/dist/src/data/dataFlow.test.d.ts +2 -0
  11. package/dist/src/data/dataFlow.test.d.ts.map +1 -0
  12. package/dist/src/data/flow.test.d.ts +2 -0
  13. package/dist/src/data/flow.test.d.ts.map +1 -0
  14. package/dist/src/data/flow.test.js +19 -14
  15. package/dist/src/data/flowNode.test.d.ts +2 -0
  16. package/dist/src/data/flowNode.test.d.ts.map +1 -0
  17. package/dist/src/data/flowOptimizer.test.d.ts +2 -0
  18. package/dist/src/data/flowOptimizer.test.d.ts.map +1 -0
  19. package/dist/src/data/flowOptimizer.test.js +9 -10
  20. package/dist/src/data/formats/fasta.test.d.ts +2 -0
  21. package/dist/src/data/formats/fasta.test.d.ts.map +1 -0
  22. package/dist/src/data/sources/inlineSource.test.d.ts +2 -0
  23. package/dist/src/data/sources/inlineSource.test.d.ts.map +1 -0
  24. package/dist/src/data/sources/inlineSource.test.js +23 -16
  25. package/dist/src/data/sources/sequenceSource.test.d.ts +2 -0
  26. package/dist/src/data/sources/sequenceSource.test.d.ts.map +1 -0
  27. package/dist/src/data/sources/sequenceSource.test.js +59 -42
  28. package/dist/src/data/transforms/clone.test.d.ts +2 -0
  29. package/dist/src/data/transforms/clone.test.d.ts.map +1 -0
  30. package/dist/src/data/transforms/coverage.test.d.ts +2 -0
  31. package/dist/src/data/transforms/coverage.test.d.ts.map +1 -0
  32. package/dist/src/data/transforms/coverage.test.js +1 -1
  33. package/dist/src/data/transforms/filter.d.ts +10 -0
  34. package/dist/src/data/transforms/filter.d.ts.map +1 -1
  35. package/dist/src/data/transforms/filter.js +30 -1
  36. package/dist/src/data/transforms/filter.test.d.ts +2 -0
  37. package/dist/src/data/transforms/filter.test.d.ts.map +1 -0
  38. package/dist/src/data/transforms/flatten.test.d.ts +2 -0
  39. package/dist/src/data/transforms/flatten.test.d.ts.map +1 -0
  40. package/dist/src/data/transforms/flatten.test.js +10 -7
  41. package/dist/src/data/transforms/flattenDelimited.test.d.ts +2 -0
  42. package/dist/src/data/transforms/flattenDelimited.test.d.ts.map +1 -0
  43. package/dist/src/data/transforms/flattenDelimited.test.js +16 -13
  44. package/dist/src/data/transforms/flattenSequence.test.d.ts +2 -0
  45. package/dist/src/data/transforms/flattenSequence.test.d.ts.map +1 -0
  46. package/dist/src/data/transforms/flattenSequence.test.js +1 -1
  47. package/dist/src/data/transforms/formula.test.d.ts +2 -0
  48. package/dist/src/data/transforms/formula.test.d.ts.map +1 -0
  49. package/dist/src/data/transforms/formula.test.js +1 -1
  50. package/dist/src/data/transforms/identifier.d.ts +1 -1
  51. package/dist/src/data/transforms/identifier.d.ts.map +1 -1
  52. package/dist/src/data/transforms/identifier.js +2 -2
  53. package/dist/src/data/transforms/identifier.test.d.ts +2 -0
  54. package/dist/src/data/transforms/identifier.test.d.ts.map +1 -0
  55. package/dist/src/data/transforms/identifier.test.js +23 -14
  56. package/dist/src/data/transforms/pileup.test.d.ts +2 -0
  57. package/dist/src/data/transforms/pileup.test.d.ts.map +1 -0
  58. package/dist/src/data/transforms/project.test.d.ts +2 -0
  59. package/dist/src/data/transforms/project.test.d.ts.map +1 -0
  60. package/dist/src/data/transforms/project.test.js +1 -1
  61. package/dist/src/data/transforms/regexExtract.test.d.ts +2 -0
  62. package/dist/src/data/transforms/regexExtract.test.d.ts.map +1 -0
  63. package/dist/src/data/transforms/regexExtract.test.js +6 -3
  64. package/dist/src/data/transforms/regexFold.test.d.ts +2 -0
  65. package/dist/src/data/transforms/regexFold.test.d.ts.map +1 -0
  66. package/dist/src/data/transforms/sample.test.d.ts +2 -0
  67. package/dist/src/data/transforms/sample.test.d.ts.map +1 -0
  68. package/dist/src/data/transforms/stack.test.d.ts +2 -0
  69. package/dist/src/data/transforms/stack.test.d.ts.map +1 -0
  70. package/dist/src/data/transforms/stack.test.js +8 -8
  71. package/dist/src/encoder/accessor.d.ts +17 -14
  72. package/dist/src/encoder/accessor.d.ts.map +1 -1
  73. package/dist/src/encoder/accessor.js +127 -56
  74. package/dist/src/encoder/accessor.test.d.ts +2 -0
  75. package/dist/src/encoder/accessor.test.d.ts.map +1 -0
  76. package/dist/src/encoder/accessor.test.js +145 -31
  77. package/dist/src/encoder/encoder.d.ts +26 -13
  78. package/dist/src/encoder/encoder.d.ts.map +1 -1
  79. package/dist/src/encoder/encoder.js +98 -114
  80. package/dist/src/encoder/encoder.test.d.ts +2 -0
  81. package/dist/src/encoder/encoder.test.d.ts.map +1 -0
  82. package/dist/src/encoder/encoder.test.js +85 -82
  83. package/dist/src/fonts/bmFontManager.d.ts.map +1 -1
  84. package/dist/src/fonts/bmFontManager.js +10 -4
  85. package/dist/src/genome/genome.test.d.ts +2 -0
  86. package/dist/src/genome/genome.test.d.ts.map +1 -0
  87. package/dist/src/genome/scaleIndex.test.d.ts +2 -0
  88. package/dist/src/genome/scaleIndex.test.d.ts.map +1 -0
  89. package/dist/src/genome/scaleLocus.test.d.ts +2 -0
  90. package/dist/src/genome/scaleLocus.test.d.ts.map +1 -0
  91. package/dist/src/genomeSpy.d.ts +3 -2
  92. package/dist/src/genomeSpy.d.ts.map +1 -1
  93. package/dist/src/genomeSpy.js +29 -21
  94. package/dist/src/gl/dataToVertices.d.ts +5 -7
  95. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  96. package/dist/src/gl/dataToVertices.js +42 -30
  97. package/dist/src/gl/glslScaleGenerator.d.ts +84 -15
  98. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
  99. package/dist/src/gl/glslScaleGenerator.js +260 -73
  100. package/dist/src/gl/includes/picking.vertex.glsl.js +1 -1
  101. package/dist/src/marks/link.common.glsl.js +1 -1
  102. package/dist/src/marks/link.d.ts.map +1 -1
  103. package/dist/src/marks/link.js +10 -0
  104. package/dist/src/marks/link.vertex.glsl.js +1 -1
  105. package/dist/src/marks/mark.d.ts +6 -9
  106. package/dist/src/marks/mark.d.ts.map +1 -1
  107. package/dist/src/marks/mark.js +212 -95
  108. package/dist/src/marks/point.d.ts.map +1 -1
  109. package/dist/src/marks/point.js +5 -1
  110. package/dist/src/marks/rect.d.ts.map +1 -1
  111. package/dist/src/marks/rect.js +9 -4
  112. package/dist/src/marks/rule.d.ts.map +1 -1
  113. package/dist/src/marks/rule.js +4 -0
  114. package/dist/src/marks/text.d.ts.map +1 -1
  115. package/dist/src/marks/text.js +5 -1
  116. package/dist/src/scale/scale.test.d.ts +2 -0
  117. package/dist/src/scale/scale.test.d.ts.map +1 -0
  118. package/dist/src/scale/scale.test.js +2 -0
  119. package/dist/src/scale/ticks.test.d.ts +2 -0
  120. package/dist/src/scale/ticks.test.d.ts.map +1 -0
  121. package/dist/src/scale/ticks.test.js +6 -0
  122. package/dist/src/selection/selection.d.ts +39 -0
  123. package/dist/src/selection/selection.d.ts.map +1 -0
  124. package/dist/src/selection/selection.js +78 -0
  125. package/dist/src/spec/channel.d.ts +137 -83
  126. package/dist/src/spec/mark.d.ts +9 -0
  127. package/dist/src/spec/parameter.d.ts +112 -3
  128. package/dist/src/spec/root.d.ts +0 -1
  129. package/dist/src/spec/transform.d.ts +19 -1
  130. package/dist/src/spec/view.d.ts +3 -3
  131. package/dist/src/tooltip/dataTooltipHandler.js +1 -1
  132. package/dist/src/types/encoder.d.ts +80 -26
  133. package/dist/src/types/rendering.d.ts +1 -0
  134. package/dist/src/types/selectionTypes.d.ts +44 -0
  135. package/dist/src/types/viewContext.d.ts +1 -4
  136. package/dist/src/utils/addBaseUrl.test.d.ts +2 -0
  137. package/dist/src/utils/addBaseUrl.test.d.ts.map +1 -0
  138. package/dist/src/utils/animator.d.ts.map +1 -1
  139. package/dist/src/utils/animator.js +3 -1
  140. package/dist/src/utils/binnedIndex.test.d.ts +2 -0
  141. package/dist/src/utils/binnedIndex.test.d.ts.map +1 -0
  142. package/dist/src/utils/cloner.test.d.ts +2 -0
  143. package/dist/src/utils/cloner.test.d.ts.map +1 -0
  144. package/dist/src/utils/coalesce.test.d.ts +2 -0
  145. package/dist/src/utils/coalesce.test.d.ts.map +1 -0
  146. package/dist/src/utils/concatIterables.test.d.ts +2 -0
  147. package/dist/src/utils/concatIterables.test.d.ts.map +1 -0
  148. package/dist/src/utils/domainArray.test.d.ts +2 -0
  149. package/dist/src/utils/domainArray.test.d.ts.map +1 -0
  150. package/dist/src/utils/expression.d.ts +2 -2
  151. package/dist/src/utils/expression.d.ts.map +1 -1
  152. package/dist/src/utils/expression.js +11 -2
  153. package/dist/src/utils/indexer.test.d.ts +2 -0
  154. package/dist/src/utils/indexer.test.d.ts.map +1 -0
  155. package/dist/src/utils/inertia.d.ts.map +1 -1
  156. package/dist/src/utils/inertia.js +4 -0
  157. package/dist/src/utils/inputBinding.d.ts.map +1 -1
  158. package/dist/src/utils/inputBinding.js +4 -0
  159. package/dist/src/utils/iterateNestedMaps.d.ts +4 -3
  160. package/dist/src/utils/iterateNestedMaps.d.ts.map +1 -1
  161. package/dist/src/utils/iterateNestedMaps.js +3 -2
  162. package/dist/src/utils/iterateNestedMaps.test.d.ts +2 -0
  163. package/dist/src/utils/iterateNestedMaps.test.d.ts.map +1 -0
  164. package/dist/src/utils/kWayMerge.test.d.ts +2 -0
  165. package/dist/src/utils/kWayMerge.test.d.ts.map +1 -0
  166. package/dist/src/utils/mergeObjects.test.d.ts +2 -0
  167. package/dist/src/utils/mergeObjects.test.d.ts.map +1 -0
  168. package/dist/src/utils/numberExtractor.test.d.ts +2 -0
  169. package/dist/src/utils/numberExtractor.test.d.ts.map +1 -0
  170. package/dist/src/utils/propertyCacher.test.d.ts +2 -0
  171. package/dist/src/utils/propertyCacher.test.d.ts.map +1 -0
  172. package/dist/src/utils/propertyCoalescer.test.d.ts +2 -0
  173. package/dist/src/utils/propertyCoalescer.test.d.ts.map +1 -0
  174. package/dist/src/utils/propertyCoalescer.test.js +3 -0
  175. package/dist/src/utils/radixSort.d.ts +9 -0
  176. package/dist/src/utils/radixSort.d.ts.map +1 -0
  177. package/dist/src/utils/radixSort.js +130 -0
  178. package/dist/src/utils/radixSort.test.d.ts +2 -0
  179. package/dist/src/utils/radixSort.test.d.ts.map +1 -0
  180. package/dist/src/utils/radixSort.test.js +51 -0
  181. package/dist/src/utils/reservationMap.test.d.ts +2 -0
  182. package/dist/src/utils/reservationMap.test.d.ts.map +1 -0
  183. package/dist/src/utils/ringBuffer.test.d.ts +2 -0
  184. package/dist/src/utils/ringBuffer.test.d.ts.map +1 -0
  185. package/dist/src/utils/topK.test.d.ts +2 -0
  186. package/dist/src/utils/topK.test.d.ts.map +1 -0
  187. package/dist/src/utils/trees.test.d.ts +2 -0
  188. package/dist/src/utils/trees.test.d.ts.map +1 -0
  189. package/dist/src/utils/trees.test.js +8 -3
  190. package/dist/src/utils/variableTools.test.d.ts +2 -0
  191. package/dist/src/utils/variableTools.test.d.ts.map +1 -0
  192. package/dist/src/view/axisResolution.d.ts +19 -6
  193. package/dist/src/view/axisResolution.d.ts.map +1 -1
  194. package/dist/src/view/axisResolution.js +16 -7
  195. package/dist/src/view/axisResolution.test.d.ts +2 -0
  196. package/dist/src/view/axisResolution.test.d.ts.map +1 -0
  197. package/dist/src/view/axisResolution.test.js +16 -11
  198. package/dist/src/view/facetView.d.ts +1 -1
  199. package/dist/src/view/facetView.d.ts.map +1 -1
  200. package/dist/src/view/flowBuilder.d.ts +1 -1
  201. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  202. package/dist/src/view/flowBuilder.js +34 -5
  203. package/dist/src/view/flowBuilder.test.d.ts +2 -0
  204. package/dist/src/view/flowBuilder.test.d.ts.map +1 -0
  205. package/dist/src/view/gridView.d.ts +0 -6
  206. package/dist/src/view/gridView.d.ts.map +1 -1
  207. package/dist/src/view/layerView.d.ts +0 -6
  208. package/dist/src/view/layerView.d.ts.map +1 -1
  209. package/dist/src/view/layout/flexLayout.test.d.ts +2 -0
  210. package/dist/src/view/layout/flexLayout.test.d.ts.map +1 -0
  211. package/dist/src/view/layout/grid.test.d.ts +2 -0
  212. package/dist/src/view/layout/grid.test.d.ts.map +1 -0
  213. package/dist/src/view/layout/rectangle.test.d.ts +2 -0
  214. package/dist/src/view/layout/rectangle.test.d.ts.map +1 -0
  215. package/dist/src/view/paramMediator.d.ts +32 -5
  216. package/dist/src/view/paramMediator.d.ts.map +1 -1
  217. package/dist/src/view/paramMediator.js +97 -9
  218. package/dist/src/view/paramMediator.test.d.ts +2 -0
  219. package/dist/src/view/paramMediator.test.d.ts.map +1 -0
  220. package/dist/src/view/paramMediator.test.js +17 -1
  221. package/dist/src/view/scaleResolution.d.ts +17 -9
  222. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  223. package/dist/src/view/scaleResolution.js +51 -34
  224. package/dist/src/view/scaleResolution.test.d.ts +2 -0
  225. package/dist/src/view/scaleResolution.test.d.ts.map +1 -0
  226. package/dist/src/view/scaleResolution.test.js +2 -0
  227. package/dist/src/view/testUtils.d.ts.map +1 -1
  228. package/dist/src/view/testUtils.js +15 -3
  229. package/dist/src/view/unitView.d.ts +5 -15
  230. package/dist/src/view/unitView.d.ts.map +1 -1
  231. package/dist/src/view/unitView.js +81 -101
  232. package/dist/src/view/view.d.ts +1 -1
  233. package/dist/src/view/view.d.ts.map +1 -1
  234. package/dist/src/view/view.test.d.ts +2 -0
  235. package/dist/src/view/view.test.d.ts.map +1 -0
  236. package/dist/src/view/view.test.js +73 -55
  237. package/dist/src/view/viewFactory.test.d.ts +2 -0
  238. package/dist/src/view/viewFactory.test.d.ts.map +1 -0
  239. package/dist/src/view/viewFactory.test.js +2 -2
  240. package/dist/src/view/zoom.js +2 -2
  241. package/package.json +5 -2
@@ -11,7 +11,17 @@ export function isExprRef(x: any): x is import("../spec/parameter.js").ExprRef;
11
11
  * @template T
12
12
  * @returns {T}
13
13
  */
14
- export function withoutExprRef<T>(x: T | import("../spec/parameter.js").ExprRef): T;
14
+ export function withoutExprRef<T>(x: import("../spec/parameter.js").ExprRef | T): T;
15
+ /**
16
+ * @param {Parameter} param
17
+ * @returns {param is import("../spec/parameter.js").VariableParameter}
18
+ */
19
+ export function isVariableParameter(param: import("../spec/parameter.js").Parameter): param is import("../spec/parameter.js").VariableParameter;
20
+ /**
21
+ * @param {Parameter} param
22
+ * @returns {param is import("../spec/parameter.js").SelectionParameter}
23
+ */
24
+ export function isSelectionParameter(param: import("../spec/parameter.js").Parameter): param is import("../spec/parameter.js").SelectionParameter<import("../spec/parameter.js").SelectionType>;
15
25
  /**
16
26
  * Takes a record of properties that may have ExprRefs as values. Converts the
17
27
  * ExprRefs to getters and setups a listener that is called when any of the
@@ -24,6 +34,23 @@ export function withoutExprRef<T>(x: T | import("../spec/parameter.js").ExprRef)
24
34
  * @template {Record<string, any | import("../spec/parameter.js").ExprRef>} T
25
35
  */
26
36
  export function activateExprRefProps<T extends Record<string, any>>(paramMediator: ParamMediator, props: T, listener?: (props: (keyof T)[]) => void): T;
37
+ /**
38
+ * Validates a parameter name. If the name is invalid, throws an error.
39
+ * Otherwise, returns the name.
40
+ *
41
+ * @param {string} name
42
+ * @returns {string} the name
43
+ */
44
+ export function validateParameterName(name: string): string;
45
+ /**
46
+ * Creates a function that always returns the same value.
47
+ * Provides functionality for creating a constant expression reference.
48
+ * They just do nothing.
49
+ *
50
+ * @param {any} value
51
+ * @returns {ExprRefFunction}
52
+ */
53
+ export function makeConstantExprRef(value: any): ExprRefFunction;
27
54
  /**
28
55
  * A class that manages parameters and expressions.
29
56
  * Supports nesting and scoped parameters.
@@ -44,10 +71,10 @@ export default class ParamMediator {
44
71
  */
45
72
  protected paramListeners: Map<string, Set<() => void>>;
46
73
  /**
47
- * @param {VariableParameter} param
74
+ * @param {Parameter} param
48
75
  * @returns {ParameterSetter}
49
76
  */
50
- registerParam(param: import("../spec/parameter.js").VariableParameter): (value: any) => void;
77
+ registerParam(param: import("../spec/parameter.js").Parameter): (value: any) => void;
51
78
  /**
52
79
  *
53
80
  * @param {string} paramName
@@ -75,7 +102,7 @@ export default class ParamMediator {
75
102
  /**
76
103
  * Returns configs for all parameters that have been registered using `registerParam`.
77
104
  */
78
- get paramConfigs(): ReadonlyMap<string, import("../spec/parameter.js").VariableParameter>;
105
+ get paramConfigs(): ReadonlyMap<string, import("../spec/parameter.js").Parameter>;
79
106
  /**
80
107
  *
81
108
  * @param {string} paramName
@@ -101,7 +128,7 @@ export default class ParamMediator {
101
128
  * A class that manages parameters and expressions.
102
129
  * Supports nesting and scoped parameters.
103
130
  */
104
- export type ExprRefFunction = ((datum?: object) => any) & import("../utils/expression.js").ExpressionProps & {
131
+ export type ExprRefFunction = ((datum?: import("../data/flowNode.js").Datum) => any) & import("../utils/expression.js").ExpressionProps & {
105
132
  addListener: (listener: () => void) => void;
106
133
  invalidate: () => void;
107
134
  identifier: () => string;
@@ -1 +1 @@
1
- {"version":3,"file":"paramMediator.d.ts","sourceRoot":"","sources":["../../../src/view/paramMediator.js"],"names":[],"mappings":"AAuQA;;;GAGG;AACH,6BAHW,GAAG,+CAKb;AAED;;;;;;;GAOG;AACH,oFASC;AAED;;;;;;;;;;GAUG;AACH,mFANW,aAAa,+CAEW,IAAI,KAwCtC;AA9UD;;;;;GAKG;AACH;IA2BI;;;;;OAKG;IACH,2BALW,MAAM,aAAa,EAU7B;IA7BD;;;OAGG;IACH,0BAHU,IAAI,MAAM,EAAE,IAAI,MAAM,IAAI,CAAC,CAAC,CAGvB;IA2Bf;;;OAGG;IACH,gFAzCqB,GAAG,KAAK,IAAI,CAkEhC;IAED;;;;;;;OAOG;IACH,6BANW,MAAM,6BAEN,OAAO,iBACS,IAAI,CA8B9B;IAED;;;OAGG;IACH,qBAFW,MAAM,WA/Fc,GAAG,KAAK,IAAI,CAuG1C;IAED;;;OAGG;IACH,oBAFW,MAAM,OAIhB;IAED;;;OAGG;IACH,qBAFW,MAAM,OAKhB;IAED;;OAEG;IACH,0FAIC;IAED;;;;;OAKG;IACH,0CAJW,MAAM,GACJ,aAAa,CASzB;IAID;;;;OAIG;IACH,uBAFW,MAAM,mBA4EhB;IAED;;;;OAIG;IACH,qBAFW,MAAM,OAKhB;;CACJ;;;;;;4BA9P4F,MAAM,IAAI,KAAK,IAAI;gBAAc,MAAM,IAAI;gBAAc,MAAM,MAAM"}
1
+ {"version":3,"file":"paramMediator.d.ts","sourceRoot":"","sources":["../../../src/view/paramMediator.js"],"names":[],"mappings":"AA2SA;;;GAGG;AACH,6BAHW,GAAG,+CAKb;AAED;;;;;;;GAOG;AACH,oFASC;AAED;;;GAGG;AACH,gJAEC;AAED;;;GAGG;AACH,gMAEC;AAED;;;;;;;;;;GAUG;AACH,mFANW,aAAa,+CAEW,IAAI,KAwCtC;AAED;;;;;;GAMG;AACH,4CAHW,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;GAOG;AACH,2CAHW,GAAG,GACD,eAAe,CAW3B;AAraD;;;;;GAKG;AACH;IA2BI;;;;;OAKG;IACH,2BALW,MAAM,aAAa,EAU7B;IA7BD;;;OAGG;IACH,0BAHU,IAAI,MAAM,EAAE,IAAI,MAAM,IAAI,CAAC,CAAC,CAGvB;IA2Bf;;;OAGG;IACH,wEAzCqB,GAAG,KAAK,IAAI,CAmGhC;IAED;;;;;;;OAOG;IACH,6BANW,MAAM,6BAEN,OAAO,iBACS,IAAI,CAgC9B;IAED;;;OAGG;IACH,qBAFW,MAAM,WAlIc,GAAG,KAAK,IAAI,CA0I1C;IAED;;;OAGG;IACH,oBAFW,MAAM,OAIhB;IAED;;;OAGG;IACH,qBAFW,MAAM,OAKhB;IAED;;OAEG;IACH,kFAIC;IAED;;;;;OAKG;IACH,0CAJW,MAAM,GACJ,aAAa,CASzB;IAID;;;;OAIG;IACH,uBAFW,MAAM,mBA4EhB;IAED;;;;OAIG;IACH,qBAFW,MAAM,OAKhB;;CACJ;;;;;;4BAjS4F,MAAM,IAAI,KAAK,IAAI;gBAAc,MAAM,IAAI;gBAAc,MAAM,MAAM"}
@@ -1,5 +1,6 @@
1
1
  import { isString } from "vega-util";
2
2
  import createFunction from "../utils/expression.js";
3
+ import { createSinglePointSelection } from "../selection/selection.js";
3
4
 
4
5
  /**
5
6
  * A class that manages parameters and expressions.
@@ -9,7 +10,7 @@ import createFunction from "../utils/expression.js";
9
10
  */
10
11
  export default class ParamMediator {
11
12
  /**
12
- * @typedef {import("../spec/parameter.js").VariableParameter} VariableParameter
13
+ * @typedef {import("../spec/parameter.js").Parameter} Parameter
13
14
  * @typedef {(value: any) => void} ParameterSetter
14
15
  */
15
16
 
@@ -28,7 +29,7 @@ export default class ParamMediator {
28
29
  /** @type {Map<string, ExprRefFunction>} */
29
30
  #expressions = new Map();
30
31
 
31
- /** @type {Map<string, VariableParameter>} */
32
+ /** @type {Map<string, Parameter>} */
32
33
  #paramConfigs = new Map();
33
34
 
34
35
  /** @type {() => ParamMediator} */
@@ -48,32 +49,65 @@ export default class ParamMediator {
48
49
  }
49
50
 
50
51
  /**
51
- * @param {VariableParameter} param
52
+ * @param {Parameter} param
52
53
  * @returns {ParameterSetter}
53
54
  */
54
55
  registerParam(param) {
56
+ const name = param.name;
57
+
55
58
  if ("value" in param && "expr" in param) {
56
59
  throw new Error(
57
- "Parameter must not have both value and expr: " + param.name
60
+ `The parameter "${name}" must not have both value and expr properties!`
58
61
  );
59
62
  }
60
63
 
61
64
  /** @type {ParameterSetter} */
62
65
  let setter;
63
66
 
64
- if ("value" in param) {
65
- setter = this.allocateSetter(param.name, param.value);
67
+ if (param.push == "outer") {
68
+ const outerMediator = this.findMediatorForParam(name);
69
+ if (!outerMediator) {
70
+ throw new Error(
71
+ `Parameter "${name}" not found in outer scope!`
72
+ );
73
+ }
74
+
75
+ const outerProps = outerMediator.paramConfigs.get(name);
76
+ if ("expr" in outerProps || "select" in outerProps) {
77
+ throw new Error(
78
+ `The outer parameter "${name}" must not have expr or select properties!`
79
+ );
80
+ }
81
+ setter = outerMediator.getSetter(name);
82
+ // The following will become a bit fragile if the view hierarchy is going to
83
+ // support mutation (i.e. adding/removing children) in future.
84
+ this.#allocatedSetters.set(name, setter);
85
+ } else if ("value" in param) {
86
+ setter = this.allocateSetter(name, param.value);
66
87
  } else if ("expr" in param) {
67
88
  const expr = this.createExpression(param.expr);
68
89
  // TODO: getSetter(param) should return a setter that throws if
69
90
  // modifying the value is attempted.
70
- const realSetter = this.allocateSetter(param.name, expr(null));
91
+ const realSetter = this.allocateSetter(name, expr(null));
71
92
  expr.addListener(() => realSetter(expr(null)));
72
93
  // NOP
73
94
  setter = (_) => undefined;
95
+ } else {
96
+ setter = this.allocateSetter(name, null);
74
97
  }
75
98
 
76
- this.#paramConfigs.set(param.name, param);
99
+ if ("select" in param) {
100
+ const type = isString(param.select)
101
+ ? param.select
102
+ : param.select.type;
103
+
104
+ // Set initial value so that production rules in shaders can be generated, etc.
105
+ if (type == "point") {
106
+ setter(createSinglePointSelection(null));
107
+ }
108
+ }
109
+
110
+ this.#paramConfigs.set(name, param);
77
111
 
78
112
  return setter;
79
113
  }
@@ -87,6 +121,8 @@ export default class ParamMediator {
87
121
  * @template T
88
122
  */
89
123
  allocateSetter(paramName, initialValue, passive = false) {
124
+ validateParameterName(paramName);
125
+
90
126
  if (this.#allocatedSetters.has(paramName)) {
91
127
  throw new Error(
92
128
  "Setter already allocated for parameter: " + paramName
@@ -148,7 +184,7 @@ export default class ParamMediator {
148
184
  * Returns configs for all parameters that have been registered using `registerParam`.
149
185
  */
150
186
  get paramConfigs() {
151
- return /** @type {ReadonlyMap<string, VariableParameter>} */ (
187
+ return /** @type {ReadonlyMap<string, Parameter>} */ (
152
188
  this.#paramConfigs
153
189
  );
154
190
  }
@@ -288,6 +324,22 @@ export function withoutExprRef(x) {
288
324
  return /** @type {T} */ (x);
289
325
  }
290
326
 
327
+ /**
328
+ * @param {Parameter} param
329
+ * @returns {param is import("../spec/parameter.js").VariableParameter}
330
+ */
331
+ export function isVariableParameter(param) {
332
+ return ("expr" in param || "bind" in param) && !("select" in param);
333
+ }
334
+
335
+ /**
336
+ * @param {Parameter} param
337
+ * @returns {param is import("../spec/parameter.js").SelectionParameter}
338
+ */
339
+ export function isSelectionParameter(param) {
340
+ return !("expr" in param || "bind" in param) && "select" in param;
341
+ }
342
+
291
343
  /**
292
344
  * Takes a record of properties that may have ExprRefs as values. Converts the
293
345
  * ExprRefs to getters and setups a listener that is called when any of the
@@ -336,3 +388,39 @@ export function activateExprRefProps(paramMediator, props, listener) {
336
388
 
337
389
  return /** @type {T} */ (activatedProps);
338
390
  }
391
+
392
+ /**
393
+ * Validates a parameter name. If the name is invalid, throws an error.
394
+ * Otherwise, returns the name.
395
+ *
396
+ * @param {string} name
397
+ * @returns {string} the name
398
+ */
399
+ export function validateParameterName(name) {
400
+ if (!/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) {
401
+ throw new Error(
402
+ `Invalid parameter name: ${name}. Must be a valid JavaScript identifier.`
403
+ );
404
+ }
405
+
406
+ return name;
407
+ }
408
+
409
+ /**
410
+ * Creates a function that always returns the same value.
411
+ * Provides functionality for creating a constant expression reference.
412
+ * They just do nothing.
413
+ *
414
+ * @param {any} value
415
+ * @returns {ExprRefFunction}
416
+ */
417
+ export function makeConstantExprRef(value) {
418
+ return Object.assign(() => value, {
419
+ addListener: () => undefined,
420
+ invalidate: () => undefined,
421
+ identifier: () => "constant",
422
+ fields: [],
423
+ globals: [],
424
+ code: JSON.stringify(value),
425
+ });
426
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=paramMediator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paramMediator.test.d.ts","sourceRoot":"","sources":["../../../src/view/paramMediator.test.js"],"names":[],"mappings":""}
@@ -173,6 +173,22 @@ describe("Nested ParamMediators", () => {
173
173
  childSetter(20);
174
174
  expect(result).toBe(30);
175
175
  });
176
+
177
+ test("Pushing to outer parameter", () => {
178
+ const parent = new ParamMediator();
179
+ const child = new ParamMediator(() => parent);
180
+
181
+ parent.registerParam({ name: "foo", value: 1 });
182
+ const childSetter = child.registerParam({ name: "foo", push: "outer" });
183
+
184
+ expect(parent.findValue("foo")).toBe(1);
185
+ expect(child.findValue("foo")).toBe(1);
186
+
187
+ childSetter(2);
188
+
189
+ expect(parent.findValue("foo")).toBe(2);
190
+ expect(child.findValue("foo")).toBe(2);
191
+ });
176
192
  });
177
193
 
178
194
  test("activateExprRefProps", async () => {
@@ -181,7 +197,7 @@ test("activateExprRefProps", async () => {
181
197
  const fooSetter = pm.registerParam({ name: "foo", value: 7 });
182
198
  const barSetter = pm.registerParam({ name: "bar", value: 11 });
183
199
 
184
- /** @type {Record<string, any | import("../spec/parameter.js").ExprRef} */
200
+ /** @type {Record<string, any | import("../spec/parameter.js").ExprRef>} */
185
201
  const props = {
186
202
  a: 42,
187
203
  b: { expr: "foo" },
@@ -17,8 +17,12 @@ export const LOCUS: "locus";
17
17
  export const INDEX: "index";
18
18
  /**
19
19
  * @template {ChannelWithScale}[T=ChannelWithScale]
20
- * @typedef {{view: import("./unitView.js").default, channel: T}} ResolutionMember
21
20
  *
21
+ * @typedef {object} ScaleResolutionMember
22
+ * @prop {import("./unitView.js").default} view TODO: Get rid of the view reference
23
+ * @prop {T} channel
24
+ * @prop {import("../spec/channel.js").ChannelDefWithScale} channelDef
25
+ * @prop {(channel: ChannelWithScale, type: import("../spec/channel.js").Type) => DomainArray} dataDomainSource
22
26
  */
23
27
  /**
24
28
  * Resolution takes care of merging domains and scales from multiple views.
@@ -34,10 +38,10 @@ export default class ScaleResolution implements ScaleResolutionApi {
34
38
  */
35
39
  constructor(channel: import("../spec/channel.js").Channel);
36
40
  channel: import("../spec/channel.js").Channel;
37
- /** @type {ResolutionMember[]} The involved views */
38
- members: ResolutionMember[];
39
- /** @type {string} Data type (quantitative, nominal, etc...) */
40
- type: string;
41
+ /** @type {ScaleResolutionMember[]} The involved views */
42
+ members: ScaleResolutionMember[];
43
+ /** @type {import("../spec/channel.js").Type} Data type (quantitative, nominal, etc...) */
44
+ type: import("../spec/channel.js").Type;
41
45
  /** @type {string} An optional unique identifier for the scale */
42
46
  name: string;
43
47
  /**
@@ -58,10 +62,9 @@ export default class ScaleResolution implements ScaleResolutionApi {
58
62
  * Add a view to this resolution.
59
63
  * N.B. This is expected to be called in depth-first order
60
64
  *
61
- * @param {UnitView} view
62
- * @param {ChannelWithScale} channel
65
+ * @param {ScaleResolutionMember} newMember
63
66
  */
64
- pushUnitView(view: import("./unitView.js").default, channel: import("../spec/channel.js").ChannelWithScale): void;
67
+ pushUnitView(newMember: ScaleResolutionMember): void;
65
68
  /**
66
69
  * Unions the configured domains of all participating views.
67
70
  *
@@ -157,8 +160,13 @@ export default class ScaleResolution implements ScaleResolutionApi {
157
160
  fromComplexInterval(interval: import("../spec/scale.js").ScalarDomain | import("../spec/scale.js").ComplexDomain): number[];
158
161
  #private;
159
162
  }
160
- export type ResolutionMember<T extends import("../spec/channel.js").ChannelWithScale = import("../spec/channel.js").ChannelWithScale> = {
163
+ export type ScaleResolutionMember<T extends import("../spec/channel.js").ChannelWithScale = import("../spec/channel.js").ChannelWithScale> = {
164
+ /**
165
+ * TODO: Get rid of the view reference
166
+ */
161
167
  view: import("./unitView.js").default;
162
168
  channel: T;
169
+ channelDef: import("../spec/channel.js").ChannelDefWithScale;
170
+ dataDomainSource: (channel: import("../spec/channel.js").ChannelWithScale, type: import("../spec/channel.js").Type) => import("../utils/domainArray.js").DomainArray;
163
171
  };
164
172
  //# sourceMappingURL=scaleResolution.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scaleResolution.d.ts","sourceRoot":"","sources":["../../../src/view/scaleResolution.js"],"names":[],"mappings":"AA86BA;;;;;;;;;;GAUG;AACH,6CAFW,OAAO,WAAW,EAAE,OAAO,GAAG,OAAO,WAAW,EAAE,OAAO,EAAE,QA4BrE;AAr6BD,0CAA2C;AAC3C,gCAAiC;AACjC,gCAAiC;AACjC,4BAA6B;AAC7B,4BAA6B;AAE7B;;;;GAIG;AACH;;;;;;;GAOG;AACH;IAyCI;;OAEG;IACH,2DASC;IARG,8CAAsB;IACtB,oDAAoD;IACpD,SADW,gBAAgB,EAAE,CACZ;IACjB,+DAA+D;IAC/D,MADW,MAAM,CACD;IAEhB,iEAAiE;IACjE,MADW,MAAM,CACI;IAWzB;;;;;;;OAOG;IACH,4KAEC;IAED;;;OAGG;IACH,+KAEC;IAcD;;;;;;OAMG;IACH,kHA0BC;IAmLD;;;;OAIG;IACH,qEAMC;IAED;;;;OAIG;IACH,+DAQC;IAED;;OAEG;IACH,oBAyCC;IAED;;OAEG;IACH;eAhXkC,OAAO,kBAAkB,EAAE,KAAK;MAuZjE;IAED,mBAEC;IAED;;OAEG;IACH,oBAFa,mFAA6B,CAOzC;IAED;;;;OAIG;IACH,oBAKC;IAED;;OAEG;IACH,sBAGC;IAUD;;;;;;;OAOG;IACH,kBALW,MAAM,eACN,MAAM,OACN,MAAM,GACJ,OAAO,CAwEnB;IAED;;;;;;OAMG;IACH,eAJW,mFAA6B,aAC7B,OAAO,GAAG,MAAM,iBAgD1B;IAED;;;;OAIG;IACH,qBAcC;IAED;;;;;OAKG;IACH,uBAOC;IA8DD;;;OAGG;IACH,aAFa,OAAO,qBAAqB,EAAE,OAAO,CAajD;IAID;;;;;OAKG;IACH,uBAFW,MAAM,yDAUhB;IAED;;OAEG;IACH,iBAFW,MAAM,yDAKhB;IAED;;;OAGG;IACH,6EAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,mHAFa,MAAM,EAAE,CAOpB;;CA6BJ;wIAjyBY;IAAC,IAAI,EAAE,OAAO,eAAe,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,CAAC,CAAA;CAAC"}
1
+ {"version":3,"file":"scaleResolution.d.ts","sourceRoot":"","sources":["../../../src/view/scaleResolution.js"],"names":[],"mappings":"AA+7BA;;;;;;;;;;GAUG;AACH,6CAFW,OAAO,WAAW,EAAE,OAAO,GAAG,OAAO,WAAW,EAAE,OAAO,EAAE,QA4BrE;AAv7BD,0CAA2C;AAC3C,gCAAiC;AACjC,gCAAiC;AACjC,4BAA6B;AAC7B,4BAA6B;AAE7B;;;;;;;;GAQG;AACH;;;;;;;GAOG;AACH;IAyCI;;OAEG;IACH,2DASC;IARG,8CAAsB;IACtB,yDAAyD;IACzD,SADW,qBAAqB,EAAE,CACjB;IACjB,0FAA0F;IAC1F,MADW,OAAO,oBAAoB,EAAE,IAAI,CAC5B;IAEhB,iEAAiE;IACjE,MADW,MAAM,CACI;IAWzB;;;;;;;OAOG;IACH,4KAEC;IAED;;;OAGG;IACH,+KAEC;IAcD;;;;;OAKG;IACH,wBAFW,qBAAqB,QA4B/B;IAuLD;;;;OAIG;IACH,qEAgBC;IAED;;;;OAIG;IACH,+DAMC;IAED;;OAEG;IACH,oBAyCC;IAED;;OAEG;IACH;eA3XkC,OAAO,kBAAkB,EAAE,KAAK;MAuajE;IAED,mBAEC;IAED;;OAEG;IACH,oBAFa,mFAA6B,CAOzC;IAED;;;;OAIG;IACH,oBAKC;IAED;;OAEG;IACH,sBAGC;IAUD;;;;;;;OAOG;IACH,kBALW,MAAM,eACN,MAAM,OACN,MAAM,GACJ,OAAO,CAwEnB;IAED;;;;;;OAMG;IACH,eAJW,mFAA6B,aAC7B,OAAO,GAAG,MAAM,iBAgD1B;IAED;;;;OAIG;IACH,qBAcC;IAED;;;;;OAKG;IACH,uBAOC;IA8DD;;;OAGG;IACH,aAFa,OAAO,qBAAqB,EAAE,OAAO,CAajD;IAID;;;;;OAKG;IACH,uBAFW,MAAM,yDAUhB;IAED;;OAEG;IACH,iBAFW,MAAM,yDAKhB;IAED;;;OAGG;IACH,6EAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,mHAFa,MAAM,EAAE,CAOpB;;CA2BJ;;;;;UAjzBS,OAAO,eAAe,EAAE,OAAO;aAC/B,CAAC;gBACD,OAAO,oBAAoB,EAAE,mBAAmB;qFACd,OAAO,oBAAoB,EAAE,IAAI"}
@@ -21,7 +21,6 @@ import mergeObjects from "../utils/mergeObjects.js";
21
21
  import createScale, { configureScale } from "../scale/scale.js";
22
22
 
23
23
  import {
24
- getChannelDefWithScale,
25
24
  isColorChannel,
26
25
  isDiscreteChannel,
27
26
  isPositionalChannel,
@@ -32,7 +31,7 @@ import {
32
31
  isChromosomalLocus,
33
32
  isChromosomalLocusInterval,
34
33
  } from "../genome/genome.js";
35
- import { NominalDomain } from "../utils/domainArray.js";
34
+ import createDomain, { NominalDomain } from "../utils/domainArray.js";
36
35
  import { easeCubicInOut } from "d3-ease";
37
36
  import { asArray, shallowArrayEquals } from "../utils/arrayUtils.js";
38
37
  import eerp from "../utils/eerp.js";
@@ -52,8 +51,12 @@ export const INDEX = "index";
52
51
 
53
52
  /**
54
53
  * @template {ChannelWithScale}[T=ChannelWithScale]
55
- * @typedef {{view: import("./unitView.js").default, channel: T}} ResolutionMember
56
54
  *
55
+ * @typedef {object} ScaleResolutionMember
56
+ * @prop {import("./unitView.js").default} view TODO: Get rid of the view reference
57
+ * @prop {T} channel
58
+ * @prop {import("../spec/channel.js").ChannelDefWithScale} channelDef
59
+ * @prop {(channel: ChannelWithScale, type: import("../spec/channel.js").Type) => DomainArray} dataDomainSource
57
60
  */
58
61
  /**
59
62
  * Resolution takes care of merging domains and scales from multiple views.
@@ -109,9 +112,9 @@ export default class ScaleResolution {
109
112
  */
110
113
  constructor(channel) {
111
114
  this.channel = channel;
112
- /** @type {ResolutionMember[]} The involved views */
115
+ /** @type {ScaleResolutionMember[]} The involved views */
113
116
  this.members = [];
114
- /** @type {string} Data type (quantitative, nominal, etc...) */
117
+ /** @type {import("../spec/channel.js").Type} Data type (quantitative, nominal, etc...) */
115
118
  this.type = null;
116
119
 
117
120
  /** @type {string} An optional unique identifier for the scale */
@@ -162,11 +165,10 @@ export default class ScaleResolution {
162
165
  * Add a view to this resolution.
163
166
  * N.B. This is expected to be called in depth-first order
164
167
  *
165
- * @param {UnitView} view
166
- * @param {ChannelWithScale} channel
168
+ * @param {ScaleResolutionMember} newMember
167
169
  */
168
- pushUnitView(view, channel) {
169
- const channelDef = getChannelDefWithScale(view, channel);
170
+ pushUnitView(newMember) {
171
+ const { channel, channelDef } = newMember;
170
172
  const type = channelDef.type;
171
173
  const name = channelDef?.scale?.name;
172
174
 
@@ -190,7 +192,7 @@ export default class ScaleResolution {
190
192
  // TODO: Use the same merging logic as in: https://github.com/vega/vega-lite/blob/master/src/scale.ts
191
193
  }
192
194
 
193
- this.members.push({ view, channel });
195
+ this.members.push(newMember);
194
196
  }
195
197
 
196
198
  /**
@@ -227,10 +229,7 @@ export default class ScaleResolution {
227
229
  */
228
230
  #getMergedScaleProps() {
229
231
  const propArray = this.members
230
- .map(
231
- (member) =>
232
- getChannelDefWithScale(member.view, member.channel).scale
233
- )
232
+ .map((member) => member.channelDef.scale)
234
233
  .filter((props) => props !== undefined);
235
234
 
236
235
  // TODO: Disabled scale: https://vega.github.io/vega-lite/docs/scale.html#disable
@@ -241,9 +240,10 @@ export default class ScaleResolution {
241
240
  * Returns the merged scale properties supplemented with inferred properties
242
241
  * and domain.
243
242
  *
243
+ * @param {boolean} [extractDataDomain]
244
244
  * @returns {import("../spec/scale.js").Scale}
245
245
  */
246
- #getScaleProps() {
246
+ #getScaleProps(extractDataDomain = false) {
247
247
  const mergedProps = this.#getMergedScaleProps();
248
248
  if (mergedProps === null || mergedProps.type == "null") {
249
249
  // No scale (pass-thru)
@@ -260,7 +260,7 @@ export default class ScaleResolution {
260
260
  props.type = getDefaultScaleType(this.channel, this.type);
261
261
  }
262
262
 
263
- const domain = this.#getInitialDomain();
263
+ const domain = this.#getInitialDomain(extractDataDomain);
264
264
 
265
265
  if (domain && domain.length > 0) {
266
266
  props.domain = domain;
@@ -360,13 +360,19 @@ export default class ScaleResolution {
360
360
  }
361
361
  }
362
362
 
363
- #getInitialDomain() {
363
+ /**
364
+ *
365
+ * @param {boolean} extractDataDomain
366
+ */
367
+ #getInitialDomain(extractDataDomain = false) {
364
368
  // TODO: intersect the domain with zoom extent (if it's defined)
365
369
  return (
366
370
  this.getConfiguredDomain() ??
367
371
  (this.type == LOCUS
368
372
  ? this.getGenome().getExtent()
369
- : this.getDataDomain())
373
+ : extractDataDomain
374
+ ? this.getDataDomain()
375
+ : [])
370
376
  );
371
377
  }
372
378
 
@@ -376,11 +382,21 @@ export default class ScaleResolution {
376
382
  * @return { DomainArray }
377
383
  */
378
384
  getConfiguredDomain() {
379
- return this.#reduceDomains((member) =>
380
- isSecondaryChannel(member.channel)
381
- ? undefined
382
- : member.view.getConfiguredDomain(member.channel)
383
- );
385
+ const domains = this.members
386
+ .map((member) => member.channelDef)
387
+ .filter((channelDef) => channelDef.scale?.domain)
388
+ .map((channelDef) =>
389
+ // TODO: Handle ExprRefs and Param in domain
390
+ createDomain(
391
+ channelDef.type,
392
+ // Chrom/pos must be linearized first
393
+ this.fromComplexInterval(channelDef.scale.domain)
394
+ )
395
+ );
396
+
397
+ if (domains.length > 0) {
398
+ return domains.reduce((acc, curr) => acc.extendAll(curr));
399
+ }
384
400
  }
385
401
 
386
402
  /**
@@ -392,9 +408,7 @@ export default class ScaleResolution {
392
408
  // TODO: Optimize: extract domain only once if the views share the data.
393
409
  // In fact, this should be a responsibility of collectors.
394
410
  return this.#reduceDomains((member) =>
395
- isSecondaryChannel(member.channel)
396
- ? undefined
397
- : member.view.extractDataDomain(member.channel)
411
+ member.dataDomainSource(member.channel, this.type)
398
412
  );
399
413
  }
400
414
 
@@ -411,7 +425,7 @@ export default class ScaleResolution {
411
425
  const domainWasInitialized = this.#isDomainInitialized();
412
426
  const previousDomain = scale.domain();
413
427
 
414
- const props = this.#getScaleProps();
428
+ const props = this.#getScaleProps(true);
415
429
  configureScale({ ...props, range: undefined }, scale);
416
430
 
417
431
  // Annotate the scale with the new props
@@ -458,6 +472,11 @@ export default class ScaleResolution {
458
472
  // Annotate the scale with props
459
473
  scale.props = props;
460
474
 
475
+ if ("unknown" in scale) {
476
+ // Never allow implicit domain construction
477
+ scale.unknown(null);
478
+ }
479
+
461
480
  this.#scale = scale;
462
481
  this.#configureRange();
463
482
 
@@ -630,7 +649,7 @@ export default class ScaleResolution {
630
649
 
631
650
  // TODO: Intersect the domain with zoom extent
632
651
 
633
- const animator = this.members[0]?.view.context.animator;
652
+ const animator = this.#viewContext.animator;
634
653
 
635
654
  const scale = this.scale;
636
655
  const from = /** @type {number[]} */ (scale.domain());
@@ -770,7 +789,7 @@ export default class ScaleResolution {
770
789
  }
771
790
 
772
791
  // TODO: Support multiple assemblies
773
- const genome = this.members[0].view.context.genomeStore?.getGenome();
792
+ const genome = this.#viewContext.genomeStore?.getGenome();
774
793
  if (!genome) {
775
794
  throw new Error("No genome has been defined!");
776
795
  }
@@ -826,21 +845,19 @@ export default class ScaleResolution {
826
845
  return /** @type {number[]} */ (interval);
827
846
  }
828
847
 
829
- #getViewPaths() {
830
- return this.members.map((v) => v.view.getPathString()).join(", ");
831
- }
832
-
833
848
  /**
834
849
  * Iterate all participanting views and reduce (union) their domains using an accessor.
835
850
  * Accessor may return the an explicitly configured domain or a domain extracted from the data.
836
851
  *
837
- * @param {function(ResolutionMember):DomainArray} domainAccessor
852
+ * @param {function(ScaleResolutionMember):DomainArray} domainAccessor
838
853
  * @returns {DomainArray}
839
854
  */
840
855
  #reduceDomains(domainAccessor) {
841
856
  const domains = this.members
842
857
  .filter(
843
858
  (member) =>
859
+ // View is missing if ScaleResolution is used within tests
860
+ !member.view ||
844
861
  !member.view
845
862
  .getLayoutAncestors()
846
863
  // TODO: Should check until the resolved scale resolution
@@ -0,0 +1,2 @@
1
+ export type Channel = import("../spec/channel.js").Channel;
2
+ //# sourceMappingURL=scaleResolution.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaleResolution.test.d.ts","sourceRoot":"","sources":["../../../src/view/scaleResolution.test.js"],"names":[],"mappings":"sBAWa,OAAO,oBAAoB,EAAE,OAAO"}
@@ -1,3 +1,5 @@
1
+ // @ts-nocheck
2
+
1
3
  import { describe, expect, test } from "vitest";
2
4
  import { createAndInitialize } from "./testUtils.js";
3
5
  import createDomain, { toRegularArray as r } from "../utils/domainArray.js";
@@ -1 +1 @@
1
- {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../../src/view/testUtils.js"],"names":[],"mappings":"AAeA;;;GAGG;AACH,2DAHW,OAAO,kBAAkB,EAAE,kBAAkB,6CAqDvD;AAGS,oEAA8C,QAAQ,2BAA4B,GAAG,EAAE,6BAA6B,OAAO,kBAAkB,EAAE,kBAAkB,cAAe;AAgBhL,iFAA8C,QAAQ,2BAA4B,GAAG,EAAE,kBAAkB,WAAW,YAAY;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAC,cAAe;;;;;uBApFpL,OAAO,iBAAiB,EAAE,QAAQ;;;;;0BAClC,OAAO,yBAAyB,EAAE,OAAO"}
1
+ {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../../src/view/testUtils.js"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,2DAHW,OAAO,kBAAkB,EAAE,kBAAkB,6CAmDvD;AAGS,oEAA8C,QAAQ,2BAA4B,GAAG,EAAE,6BAA6B,OAAO,kBAAkB,EAAE,kBAAkB,cAAe;AAgBhL,iFAA8C,QAAQ,2BAA4B,GAAG,EAAE,kBAAkB,WAAW,YAAY;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAC,cAAe;;;;;uBApFpL,OAAO,iBAAiB,EAAE,QAAQ;;;;;0BAClC,OAAO,yBAAyB,EAAE,OAAO"}
@@ -7,11 +7,13 @@
7
7
  */
8
8
 
9
9
  import { checkForDuplicateScaleNames, initializeData } from "./viewUtils.js";
10
- import AccessorFactory from "../encoder/accessor.js";
11
10
  import DataFlow from "../data/dataFlow.js";
12
11
  import { VIEW_ROOT_NAME, ViewFactory } from "./viewFactory.js";
13
12
  import GenomeStore from "../genome/genomeStore.js";
14
13
  import BmFontManager from "../fonts/bmFontManager.js";
14
+ import { reconfigureScales } from "./scaleResolution.js";
15
+ import UnitView from "./unitView.js";
16
+ import ContainerView from "./containerView.js";
15
17
 
16
18
  /**
17
19
  * @param {import("./viewFactory.js").ViewFactoryOptions} [viewFactoryOptions]
@@ -35,8 +37,6 @@ export function createTestViewContext(viewFactoryOptions = {}) {
35
37
 
36
38
  // @ts-expect-error
37
39
  const c = /** @type {ViewContext} */ ({
38
- accessorFactory: new AccessorFactory(),
39
-
40
40
  createView: function (spec, parent, defaultName) {
41
41
  throw new Error("Not implemented: createView");
42
42
  },
@@ -92,6 +92,18 @@ export async function createAndInitialize(spec, viewClass) {
92
92
  const view = await create(spec, viewClass);
93
93
 
94
94
  checkForDuplicateScaleNames(view);
95
+
96
+ if (view instanceof UnitView) {
97
+ view.mark.initializeEncoders();
98
+ } else if (view instanceof ContainerView) {
99
+ view.visit((v) => {
100
+ if (v instanceof UnitView) {
101
+ v.mark.initializeEncoders();
102
+ }
103
+ });
104
+ }
105
+
95
106
  await initializeData(view, view.context.dataFlow);
107
+ reconfigureScales(view);
96
108
  return view;
97
109
  }