@genome-spy/core 0.48.2 → 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 (221) hide show
  1. package/dist/bundle/index.es.js +7226 -6923
  2. package/dist/bundle/index.js +121 -108
  3. package/dist/schema.json +838 -344
  4. package/dist/src/data/collector.test.d.ts +2 -0
  5. package/dist/src/data/collector.test.d.ts.map +1 -0
  6. package/dist/src/data/dataFlow.test.d.ts +2 -0
  7. package/dist/src/data/dataFlow.test.d.ts.map +1 -0
  8. package/dist/src/data/flow.test.d.ts +2 -0
  9. package/dist/src/data/flow.test.d.ts.map +1 -0
  10. package/dist/src/data/flow.test.js +19 -14
  11. package/dist/src/data/flowNode.test.d.ts +2 -0
  12. package/dist/src/data/flowNode.test.d.ts.map +1 -0
  13. package/dist/src/data/flowOptimizer.test.d.ts +2 -0
  14. package/dist/src/data/flowOptimizer.test.d.ts.map +1 -0
  15. package/dist/src/data/flowOptimizer.test.js +9 -10
  16. package/dist/src/data/formats/fasta.test.d.ts +2 -0
  17. package/dist/src/data/formats/fasta.test.d.ts.map +1 -0
  18. package/dist/src/data/sources/inlineSource.test.d.ts +2 -0
  19. package/dist/src/data/sources/inlineSource.test.d.ts.map +1 -0
  20. package/dist/src/data/sources/inlineSource.test.js +23 -16
  21. package/dist/src/data/sources/sequenceSource.test.d.ts +2 -0
  22. package/dist/src/data/sources/sequenceSource.test.d.ts.map +1 -0
  23. package/dist/src/data/sources/sequenceSource.test.js +59 -42
  24. package/dist/src/data/transforms/clone.test.d.ts +2 -0
  25. package/dist/src/data/transforms/clone.test.d.ts.map +1 -0
  26. package/dist/src/data/transforms/coverage.test.d.ts +2 -0
  27. package/dist/src/data/transforms/coverage.test.d.ts.map +1 -0
  28. package/dist/src/data/transforms/coverage.test.js +1 -1
  29. package/dist/src/data/transforms/filter.d.ts +10 -0
  30. package/dist/src/data/transforms/filter.d.ts.map +1 -1
  31. package/dist/src/data/transforms/filter.js +30 -1
  32. package/dist/src/data/transforms/filter.test.d.ts +2 -0
  33. package/dist/src/data/transforms/filter.test.d.ts.map +1 -0
  34. package/dist/src/data/transforms/flatten.test.d.ts +2 -0
  35. package/dist/src/data/transforms/flatten.test.d.ts.map +1 -0
  36. package/dist/src/data/transforms/flatten.test.js +10 -7
  37. package/dist/src/data/transforms/flattenDelimited.test.d.ts +2 -0
  38. package/dist/src/data/transforms/flattenDelimited.test.d.ts.map +1 -0
  39. package/dist/src/data/transforms/flattenDelimited.test.js +16 -13
  40. package/dist/src/data/transforms/flattenSequence.test.d.ts +2 -0
  41. package/dist/src/data/transforms/flattenSequence.test.d.ts.map +1 -0
  42. package/dist/src/data/transforms/flattenSequence.test.js +1 -1
  43. package/dist/src/data/transforms/formula.test.d.ts +2 -0
  44. package/dist/src/data/transforms/formula.test.d.ts.map +1 -0
  45. package/dist/src/data/transforms/formula.test.js +1 -1
  46. package/dist/src/data/transforms/identifier.test.d.ts +2 -0
  47. package/dist/src/data/transforms/identifier.test.d.ts.map +1 -0
  48. package/dist/src/data/transforms/pileup.test.d.ts +2 -0
  49. package/dist/src/data/transforms/pileup.test.d.ts.map +1 -0
  50. package/dist/src/data/transforms/project.test.d.ts +2 -0
  51. package/dist/src/data/transforms/project.test.d.ts.map +1 -0
  52. package/dist/src/data/transforms/project.test.js +1 -1
  53. package/dist/src/data/transforms/regexExtract.test.d.ts +2 -0
  54. package/dist/src/data/transforms/regexExtract.test.d.ts.map +1 -0
  55. package/dist/src/data/transforms/regexExtract.test.js +6 -3
  56. package/dist/src/data/transforms/regexFold.test.d.ts +2 -0
  57. package/dist/src/data/transforms/regexFold.test.d.ts.map +1 -0
  58. package/dist/src/data/transforms/sample.test.d.ts +2 -0
  59. package/dist/src/data/transforms/sample.test.d.ts.map +1 -0
  60. package/dist/src/data/transforms/stack.test.d.ts +2 -0
  61. package/dist/src/data/transforms/stack.test.d.ts.map +1 -0
  62. package/dist/src/data/transforms/stack.test.js +8 -8
  63. package/dist/src/encoder/accessor.d.ts +17 -14
  64. package/dist/src/encoder/accessor.d.ts.map +1 -1
  65. package/dist/src/encoder/accessor.js +127 -56
  66. package/dist/src/encoder/accessor.test.d.ts +2 -0
  67. package/dist/src/encoder/accessor.test.d.ts.map +1 -0
  68. package/dist/src/encoder/accessor.test.js +145 -31
  69. package/dist/src/encoder/encoder.d.ts +26 -13
  70. package/dist/src/encoder/encoder.d.ts.map +1 -1
  71. package/dist/src/encoder/encoder.js +98 -114
  72. package/dist/src/encoder/encoder.test.d.ts +2 -0
  73. package/dist/src/encoder/encoder.test.d.ts.map +1 -0
  74. package/dist/src/encoder/encoder.test.js +85 -82
  75. package/dist/src/fonts/bmFontManager.d.ts.map +1 -1
  76. package/dist/src/fonts/bmFontManager.js +10 -4
  77. package/dist/src/genome/genome.test.d.ts +2 -0
  78. package/dist/src/genome/genome.test.d.ts.map +1 -0
  79. package/dist/src/genome/scaleIndex.test.d.ts +2 -0
  80. package/dist/src/genome/scaleIndex.test.d.ts.map +1 -0
  81. package/dist/src/genome/scaleLocus.test.d.ts +2 -0
  82. package/dist/src/genome/scaleLocus.test.d.ts.map +1 -0
  83. package/dist/src/genomeSpy.d.ts +3 -2
  84. package/dist/src/genomeSpy.d.ts.map +1 -1
  85. package/dist/src/genomeSpy.js +15 -6
  86. package/dist/src/gl/dataToVertices.d.ts +6 -8
  87. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  88. package/dist/src/gl/dataToVertices.js +42 -33
  89. package/dist/src/gl/glslScaleGenerator.d.ts +84 -15
  90. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
  91. package/dist/src/gl/glslScaleGenerator.js +260 -73
  92. package/dist/src/marks/link.common.glsl.js +1 -1
  93. package/dist/src/marks/link.d.ts.map +1 -1
  94. package/dist/src/marks/link.js +10 -0
  95. package/dist/src/marks/link.vertex.glsl.js +1 -1
  96. package/dist/src/marks/mark.d.ts +6 -9
  97. package/dist/src/marks/mark.d.ts.map +1 -1
  98. package/dist/src/marks/mark.js +212 -95
  99. package/dist/src/marks/point.d.ts.map +1 -1
  100. package/dist/src/marks/point.js +5 -1
  101. package/dist/src/marks/rect.d.ts.map +1 -1
  102. package/dist/src/marks/rect.js +9 -4
  103. package/dist/src/marks/rule.d.ts.map +1 -1
  104. package/dist/src/marks/rule.js +4 -0
  105. package/dist/src/marks/text.d.ts.map +1 -1
  106. package/dist/src/marks/text.js +5 -1
  107. package/dist/src/scale/scale.test.d.ts +2 -0
  108. package/dist/src/scale/scale.test.d.ts.map +1 -0
  109. package/dist/src/scale/scale.test.js +2 -0
  110. package/dist/src/scale/ticks.test.d.ts +2 -0
  111. package/dist/src/scale/ticks.test.d.ts.map +1 -0
  112. package/dist/src/scale/ticks.test.js +6 -0
  113. package/dist/src/selection/selection.d.ts +39 -0
  114. package/dist/src/selection/selection.d.ts.map +1 -0
  115. package/dist/src/selection/selection.js +78 -0
  116. package/dist/src/spec/channel.d.ts +137 -83
  117. package/dist/src/spec/mark.d.ts +9 -0
  118. package/dist/src/spec/parameter.d.ts +112 -3
  119. package/dist/src/spec/root.d.ts +0 -1
  120. package/dist/src/spec/transform.d.ts +19 -1
  121. package/dist/src/spec/view.d.ts +3 -3
  122. package/dist/src/tooltip/dataTooltipHandler.js +1 -1
  123. package/dist/src/types/encoder.d.ts +80 -26
  124. package/dist/src/types/rendering.d.ts +1 -0
  125. package/dist/src/types/selectionTypes.d.ts +44 -0
  126. package/dist/src/types/viewContext.d.ts +1 -4
  127. package/dist/src/utils/addBaseUrl.test.d.ts +2 -0
  128. package/dist/src/utils/addBaseUrl.test.d.ts.map +1 -0
  129. package/dist/src/utils/binnedIndex.test.d.ts +2 -0
  130. package/dist/src/utils/binnedIndex.test.d.ts.map +1 -0
  131. package/dist/src/utils/cloner.test.d.ts +2 -0
  132. package/dist/src/utils/cloner.test.d.ts.map +1 -0
  133. package/dist/src/utils/coalesce.test.d.ts +2 -0
  134. package/dist/src/utils/coalesce.test.d.ts.map +1 -0
  135. package/dist/src/utils/concatIterables.test.d.ts +2 -0
  136. package/dist/src/utils/concatIterables.test.d.ts.map +1 -0
  137. package/dist/src/utils/domainArray.test.d.ts +2 -0
  138. package/dist/src/utils/domainArray.test.d.ts.map +1 -0
  139. package/dist/src/utils/expression.d.ts +2 -2
  140. package/dist/src/utils/expression.d.ts.map +1 -1
  141. package/dist/src/utils/expression.js +11 -2
  142. package/dist/src/utils/indexer.test.d.ts +2 -0
  143. package/dist/src/utils/indexer.test.d.ts.map +1 -0
  144. package/dist/src/utils/inputBinding.d.ts.map +1 -1
  145. package/dist/src/utils/inputBinding.js +4 -0
  146. package/dist/src/utils/iterateNestedMaps.test.d.ts +2 -0
  147. package/dist/src/utils/iterateNestedMaps.test.d.ts.map +1 -0
  148. package/dist/src/utils/kWayMerge.test.d.ts +2 -0
  149. package/dist/src/utils/kWayMerge.test.d.ts.map +1 -0
  150. package/dist/src/utils/mergeObjects.test.d.ts +2 -0
  151. package/dist/src/utils/mergeObjects.test.d.ts.map +1 -0
  152. package/dist/src/utils/numberExtractor.test.d.ts +2 -0
  153. package/dist/src/utils/numberExtractor.test.d.ts.map +1 -0
  154. package/dist/src/utils/propertyCacher.test.d.ts +2 -0
  155. package/dist/src/utils/propertyCacher.test.d.ts.map +1 -0
  156. package/dist/src/utils/propertyCoalescer.test.d.ts +2 -0
  157. package/dist/src/utils/propertyCoalescer.test.d.ts.map +1 -0
  158. package/dist/src/utils/propertyCoalescer.test.js +3 -0
  159. package/dist/src/utils/radixSort.test.d.ts +2 -0
  160. package/dist/src/utils/radixSort.test.d.ts.map +1 -0
  161. package/dist/src/utils/reservationMap.test.d.ts +2 -0
  162. package/dist/src/utils/reservationMap.test.d.ts.map +1 -0
  163. package/dist/src/utils/ringBuffer.test.d.ts +2 -0
  164. package/dist/src/utils/ringBuffer.test.d.ts.map +1 -0
  165. package/dist/src/utils/topK.test.d.ts +2 -0
  166. package/dist/src/utils/topK.test.d.ts.map +1 -0
  167. package/dist/src/utils/trees.test.d.ts +2 -0
  168. package/dist/src/utils/trees.test.d.ts.map +1 -0
  169. package/dist/src/utils/trees.test.js +8 -3
  170. package/dist/src/utils/variableTools.test.d.ts +2 -0
  171. package/dist/src/utils/variableTools.test.d.ts.map +1 -0
  172. package/dist/src/view/axisResolution.d.ts +19 -6
  173. package/dist/src/view/axisResolution.d.ts.map +1 -1
  174. package/dist/src/view/axisResolution.js +16 -7
  175. package/dist/src/view/axisResolution.test.d.ts +2 -0
  176. package/dist/src/view/axisResolution.test.d.ts.map +1 -0
  177. package/dist/src/view/axisResolution.test.js +16 -11
  178. package/dist/src/view/facetView.d.ts +1 -1
  179. package/dist/src/view/facetView.d.ts.map +1 -1
  180. package/dist/src/view/flowBuilder.d.ts +1 -1
  181. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  182. package/dist/src/view/flowBuilder.js +34 -5
  183. package/dist/src/view/flowBuilder.test.d.ts +2 -0
  184. package/dist/src/view/flowBuilder.test.d.ts.map +1 -0
  185. package/dist/src/view/gridView.d.ts +0 -6
  186. package/dist/src/view/gridView.d.ts.map +1 -1
  187. package/dist/src/view/layerView.d.ts +0 -6
  188. package/dist/src/view/layerView.d.ts.map +1 -1
  189. package/dist/src/view/layout/flexLayout.test.d.ts +2 -0
  190. package/dist/src/view/layout/flexLayout.test.d.ts.map +1 -0
  191. package/dist/src/view/layout/grid.test.d.ts +2 -0
  192. package/dist/src/view/layout/grid.test.d.ts.map +1 -0
  193. package/dist/src/view/layout/rectangle.test.d.ts +2 -0
  194. package/dist/src/view/layout/rectangle.test.d.ts.map +1 -0
  195. package/dist/src/view/paramMediator.d.ts +32 -5
  196. package/dist/src/view/paramMediator.d.ts.map +1 -1
  197. package/dist/src/view/paramMediator.js +97 -9
  198. package/dist/src/view/paramMediator.test.d.ts +2 -0
  199. package/dist/src/view/paramMediator.test.d.ts.map +1 -0
  200. package/dist/src/view/paramMediator.test.js +17 -1
  201. package/dist/src/view/scaleResolution.d.ts +17 -9
  202. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  203. package/dist/src/view/scaleResolution.js +51 -34
  204. package/dist/src/view/scaleResolution.test.d.ts +2 -0
  205. package/dist/src/view/scaleResolution.test.d.ts.map +1 -0
  206. package/dist/src/view/scaleResolution.test.js +2 -0
  207. package/dist/src/view/testUtils.d.ts.map +1 -1
  208. package/dist/src/view/testUtils.js +15 -3
  209. package/dist/src/view/unitView.d.ts +5 -15
  210. package/dist/src/view/unitView.d.ts.map +1 -1
  211. package/dist/src/view/unitView.js +81 -101
  212. package/dist/src/view/view.d.ts +1 -1
  213. package/dist/src/view/view.d.ts.map +1 -1
  214. package/dist/src/view/view.test.d.ts +2 -0
  215. package/dist/src/view/view.test.d.ts.map +1 -0
  216. package/dist/src/view/view.test.js +73 -55
  217. package/dist/src/view/viewFactory.test.d.ts +2 -0
  218. package/dist/src/view/viewFactory.test.d.ts.map +1 -0
  219. package/dist/src/view/viewFactory.test.js +2 -2
  220. package/dist/src/view/zoom.js +2 -2
  221. package/package.json +5 -2
@@ -3,20 +3,23 @@
3
3
  *
4
4
  * TODO: This method should have a test. But how to mock Mark...
5
5
  *
6
- * @param {import("../marks/mark.js").default} mark
7
- * @param {import("../spec/channel.js").Encoding} [encoding] Taken from the mark if not provided
6
+ * @param {import("../view/unitView.js").default} unitView
7
+ * @param {import("../spec/channel.js").Encoding} encoding
8
8
  * @returns {Partial<Record<Channel, Encoder>>}
9
9
  */
10
- export default function createEncoders(mark: import("../marks/mark.js").default, encoding?: import("../spec/channel.js").Encoding): Partial<Record<import("../spec/channel.js").Channel, import("../types/encoder.js").Encoder>>;
10
+ export default function createEncoders(unitView: import("../view/unitView.js").default, encoding: import("../spec/channel.js").Encoding): Partial<Record<import("../spec/channel.js").Channel, import("../types/encoder.js").Encoder>>;
11
+ /**
12
+ * @param {import("../types/encoder.js").Accessor[]} accessors
13
+ * @param {(channel: import("../spec/channel.js").ChannelWithScale) => import("../types/encoder.js").VegaScale} scaleSource
14
+ * @returns {Encoder}
15
+ */
16
+ export function createSimpleOrConditionalEncoder(accessors: import("../types/encoder.js").Accessor[], scaleSource: (channel: import("../spec/channel.js").ChannelWithScale) => import("../types/encoder.js").VegaScale): import("../types/encoder.js").Encoder;
11
17
  /**
12
- * @param {import("../marks/mark.js").default} mark
13
- * @param {import("../spec/channel.js").ChannelDef} channelDef
14
- * @param {any} scale
15
18
  * @param {Accessor} accessor
16
- * @param {Channel} channel
19
+ * @param {(channel: import("../spec/channel.js").ChannelWithScale) => import("../types/encoder.js").VegaScale} scaleSource
17
20
  * @returns {Encoder}
18
21
  */
19
- export function createEncoder(mark: import("../marks/mark.js").default, channelDef: import("../spec/channel.js").ChannelDef, scale: any, accessor: import("../types/encoder.js").Accessor, channel: import("../spec/channel.js").Channel): import("../types/encoder.js").Encoder;
22
+ export function createEncoder(accessor: import("../types/encoder.js").Accessor<import("../spec/channel.js").Scalar>, scaleSource: (channel: import("../spec/channel.js").ChannelWithScale) => import("../types/encoder.js").VegaScale): import("../types/encoder.js").Encoder;
20
23
  /**
21
24
  * TODO: Move to a more generic place
22
25
  *
@@ -26,14 +29,14 @@ export function createEncoder(mark: import("../marks/mark.js").default, channelD
26
29
  export function isValueDef(channelDef: import("../spec/channel.js").ChannelDef): channelDef is import("../spec/channel.js").ValueDef<import("../spec/channel.js").Scalar>;
27
30
  /**
28
31
  * @param {import("../spec/channel.js").ChannelDef} channelDef
29
- * @returns {channelDef is import("../spec/channel.js").FieldDefBase<string>}
32
+ * @returns {channelDef is import("../spec/channel.js").FieldDefBase}
30
33
  */
31
- export function isFieldDef(channelDef: import("../spec/channel.js").ChannelDef): channelDef is import("../spec/channel.js").FieldDefBase<string>;
34
+ export function isFieldDef(channelDef: import("../spec/channel.js").ChannelDef): channelDef is import("../spec/channel.js").FieldDefBase;
32
35
  /**
33
36
  * @param {import("../spec/channel.js").ChannelDef} channelDef
34
37
  * @returns {channelDef is import("../spec/channel.js").DatumDef}
35
38
  */
36
- export function isDatumDef(channelDef: import("../spec/channel.js").ChannelDef): channelDef is import("../spec/channel.js").DatumDef;
39
+ export function isDatumDef(channelDef: import("../spec/channel.js").ChannelDef): channelDef is import("../spec/channel.js").DatumDef<import("../spec/parameter.js").ExprRef | import("../spec/channel.js").Scalar>;
37
40
  /**
38
41
  * @param {import("../spec/channel.js").ChannelDef} channelDef
39
42
  * @returns {channelDef is import("../spec/channel.js").ChannelDefWithScale}
@@ -43,7 +46,7 @@ export function isChannelDefWithScale(channelDef: import("../spec/channel.js").C
43
46
  * @param {import("../view/unitView.js").default} view
44
47
  * @param {import("../spec/channel.js").Channel} channel
45
48
  */
46
- export function getChannelDefWithScale(view: import("../view/unitView.js").default, channel: import("../spec/channel.js").Channel): import("../spec/channel.js").MarkPropExprDef<import("../spec/channel.js").Type> | import("../spec/channel.js").MarkPropDatumDef<import("../spec/channel.js").Type> | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").PositionDatumDef | (import("../spec/channel.js").ChromPosDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").TypeMixins<"locus"> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").DatumDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | import("../spec/channel.js").MarkPropDatumDef<import("../spec/channel.js").TypeForShape> | import("../spec/channel.js").MarkPropFieldDef<string, import("../spec/channel.js").Type> | import("../spec/channel.js").PositionFieldDef<string> | (import("../spec/channel.js").FieldDefBase<string> & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | import("../spec/channel.js").MarkPropFieldDef<string, import("../spec/channel.js").TypeForShape>;
49
+ export function getChannelDefWithScale(view: import("../view/unitView.js").default, channel: import("../spec/channel.js").Channel): import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, string> | import("../spec/channel.js").PositionFieldDef | import("../spec/channel.js").PositionDatumDef | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, number> | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").TypeForShape>, string> | (import("../spec/channel.js").FieldDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").DatumDef<import("../spec/parameter.js").ExprRef | import("../spec/channel.js").Scalar> & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ChromPosDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").TypeMixins<"locus"> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").XIndexDef);
47
50
  /**
48
51
  * @param {import("../spec/channel.js").ChannelDef} channelDef
49
52
  * @returns {channelDef is import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>}
@@ -59,6 +62,16 @@ export function isChromPosDef(channelDef: import("../spec/channel.js").ChannelDe
59
62
  * @returns {channelDef is import("../spec/channel.js").ExprDef}
60
63
  */
61
64
  export function isExprDef(channelDef: import("../spec/channel.js").ChannelDef): channelDef is import("../spec/channel.js").ExprDef;
65
+ /**
66
+ * @param {import("../spec/channel.js").ChannelDef} channelDef
67
+ * @returns {channelDef is import("../spec/channel.js").FieldOrDatumDefWithCondition}
68
+ */
69
+ export function isFieldOrDatumDefWithCondition(channelDef: import("../spec/channel.js").ChannelDef): channelDef is import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").FieldDef<any> | import("../spec/channel.js").DatumDef<any>, import("../spec/channel.js").Value>;
70
+ /**
71
+ * @param {import("../spec/channel.js").ChannelDef} channelDef
72
+ * @returns {channelDef is import("../spec/channel.js").ValueDefWithCondition}
73
+ */
74
+ export function isValueDefWithCondition(channelDef: import("../spec/channel.js").ChannelDef): channelDef is import("../spec/channel.js").ValueDefWithCondition<import("../spec/channel.js").Value>;
62
75
  /**
63
76
  * @param {import("../spec/channel.js").Channel} channel
64
77
  * @returns {channel is import("../spec/channel.js").PrimaryPositionalChannel}
@@ -92,7 +105,7 @@ export function getPrimaryChannel(channel: import("../spec/channel.js").Channel)
92
105
  *
93
106
  * @param {import("../spec/channel.js").Channel} channel
94
107
  */
95
- export function getChannelWithSecondarys(channel: import("../spec/channel.js").Channel): import("../spec/channel.js").Channel[];
108
+ export function getChannelWithSecondarys(channel: import("../spec/channel.js").Channel): ("search" | "fill" | "stroke" | "angle" | "sample" | "color" | "fillOpacity" | "opacity" | "strokeOpacity" | "strokeWidth" | "text" | "size" | "x" | "y" | "x2" | "y2" | "shape" | "dx" | "dy" | "uniqueId" | "facetIndex" | "semanticScore")[];
96
109
  /**
97
110
  * @param {import("../spec/channel.js").Channel} channel
98
111
  */
@@ -1 +1 @@
1
- {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/encoder/encoder.js"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,6CAJW,OAAO,kBAAkB,EAAE,OAAO,aAClC,OAAO,oBAAoB,EAAE,QAAQ,gGAuC/C;AAED;;;;;;;GAOG;AACH,oCAPW,OAAO,kBAAkB,EAAE,OAAO,cAClC,OAAO,oBAAoB,EAAE,UAAU,SACvC,GAAG,0IAqGb;AAED;;;;;GAKG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,mEAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,uDAKjD;AAED;;;GAGG;AACH,kDAHW,OAAO,oBAAoB,EAAE,UAAU,kEAWjD;AAED;;;GAGG;AACH,6CAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,oBAAoB,EAAE,OAAO,27CAS9C;AAED;;;GAGG;AACH,iDAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,0CAHW,OAAO,oBAAoB,EAAE,UAAU,0DAKjD;AAED;;;GAGG;AACH,sCAHW,OAAO,oBAAoB,EAAE,UAAU,sDAKjD;AAoBD;;;GAGG;AACH,oDAHW,OAAO,oBAAoB,EAAE,OAAO,oEAM9C;AAED;;;GAGG;AACH,6CAHW,OAAO,oBAAoB,EAAE,OAAO,6DAM9C;AAqBD;;;GAGG;AACH,4CAFW,MAAM,WAIhB;AAED;;;;GAIG;AACH,oDAFW,OAAO,oBAAoB,EAAE,OAAO,2DAS9C;AAED;;;;;GAKG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,wCAI9C;AAED;;;;GAIG;AACH,kDAFW,OAAO,oBAAoB,EAAE,OAAO,0CAM9C;AAED;;GAEG;AACH,wCAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;;GAIG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,OAAO,4DAuB9C;AAED;;;;;GAKG;AACH,0CAHW,OAAO,oBAAoB,EAAE,OAAO,GAClC,GAAG,EAAE,CAsBjB;AAED;;;GAGG;AACH,gDAHW,OAAO,oBAAoB,EAAE,OAAO,UACzB,GAAG,KAAE,MAAM,CAmBhC;AA7LD;;GAEG;AACH,wCAFU,OAAO,oBAAoB,EAAE,wBAAwB,EAAE,CAEb;AAEpD;;GAEG;AACH,0CAFU,OAAO,oBAAoB,EAAE,0BAA0B,EAAE,CAEX;AAExD;;GAEG;AACH,iCAFU,OAAO,oBAAoB,EAAE,iBAAiB,EAAE,CAKxD;AAoBF;;;;GAIG;AACH,gCAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,0BAA0B,CAAC,CAAC,CAKtH;AAEF;;;;GAIG;AACH,8BAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAInG"}
1
+ {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/encoder/encoder.js"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,iDAJW,OAAO,qBAAqB,EAAE,OAAO,YACrC,OAAO,oBAAoB,EAAE,QAAQ,gGAgC/C;AAED;;;;GAIG;AACH,4DAJW,OAAO,qBAAqB,EAAE,QAAQ,EAAE,yBAC9B,OAAO,oBAAoB,EAAE,gBAAgB,KAAK,OAAO,qBAAqB,EAAE,SAAS,yCAqC7G;AAED;;;;GAIG;AACH,4IAHqB,OAAO,oBAAoB,EAAE,gBAAgB,KAAK,OAAO,qBAAqB,EAAE,SAAS,yCAqC7G;AAED;;;;;GAKG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,2DAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,qIAKjD;AAED;;;GAGG;AACH,kDAHW,OAAO,oBAAoB,EAAE,UAAU,kEAWjD;AAED;;;GAGG;AACH,6CAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,oBAAoB,EAAE,OAAO,s9CAS9C;AAED;;;GAGG;AACH,iDAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,0CAHW,OAAO,oBAAoB,EAAE,UAAU,0DAKjD;AAED;;;GAGG;AACH,sCAHW,OAAO,oBAAoB,EAAE,UAAU,sDAKjD;AAED;;;GAGG;AACH,2DAHW,OAAO,oBAAoB,EAAE,UAAU,wMAQjD;AAED;;;GAGG;AACH,oDAHW,OAAO,oBAAoB,EAAE,UAAU,wGAKjD;AAoBD;;;GAGG;AACH,oDAHW,OAAO,oBAAoB,EAAE,OAAO,oEAM9C;AAED;;;GAGG;AACH,6CAHW,OAAO,oBAAoB,EAAE,OAAO,6DAM9C;AAqBD;;;GAGG;AACH,4CAFW,MAAM,WAIhB;AAED;;;;GAIG;AACH,oDAFW,OAAO,oBAAoB,EAAE,OAAO,2DAS9C;AAED;;;;;GAKG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,wCAI9C;AAED;;;;GAIG;AACH,kDAFW,OAAO,oBAAoB,EAAE,OAAO,mPAM9C;AAED;;GAEG;AACH,wCAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;;GAIG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,OAAO,4DAsB9C;AAED;;;;;GAKG;AACH,0CAHW,OAAO,oBAAoB,EAAE,OAAO,GAClC,GAAG,EAAE,CAsBjB;AAED;;;GAGG;AACH,gDAHW,OAAO,oBAAoB,EAAE,OAAO,UACzB,GAAG,KAAE,MAAM,CAmBhC;AA5LD;;GAEG;AACH,wCAFU,OAAO,oBAAoB,EAAE,wBAAwB,EAAE,CAEb;AAEpD;;GAEG;AACH,0CAFU,OAAO,oBAAoB,EAAE,0BAA0B,EAAE,CAEX;AAExD;;GAEG;AACH,iCAFU,OAAO,oBAAoB,EAAE,iBAAiB,EAAE,CAKxD;AAoBF;;;;GAIG;AACH,gCAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,0BAA0B,CAAC,CAAC,CAKtH;AAEF;;;;GAIG;AACH,8BAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAInG"}
@@ -1,18 +1,15 @@
1
- import { isDiscrete } from "vega-scale";
2
- import createIndexer from "../utils/indexer.js";
3
- import scaleNull from "../utils/scaleNull.js";
4
- import { isExprRef } from "../view/paramMediator.js";
1
+ import { createConditionalAccessors } from "./accessor.js";
5
2
 
6
3
  /**
7
4
  * Creates an object that contains encoders for every channel of a mark
8
5
  *
9
6
  * TODO: This method should have a test. But how to mock Mark...
10
7
  *
11
- * @param {import("../marks/mark.js").default} mark
12
- * @param {import("../spec/channel.js").Encoding} [encoding] Taken from the mark if not provided
8
+ * @param {import("../view/unitView.js").default} unitView
9
+ * @param {import("../spec/channel.js").Encoding} encoding
13
10
  * @returns {Partial<Record<Channel, Encoder>>}
14
11
  */
15
- export default function createEncoders(mark, encoding) {
12
+ export default function createEncoders(unitView, encoding) {
16
13
  /**
17
14
  * @typedef {import("../spec/channel.js").Channel} Channel
18
15
  * @typedef {import("../types/encoder.js").Encoder} Encoder
@@ -21,29 +18,22 @@ export default function createEncoders(mark, encoding) {
21
18
  /** @type {Partial<Record<Channel, Encoder>>} */
22
19
  const encoders = {};
23
20
 
24
- if (!encoding) {
25
- encoding = mark.encoding;
26
- }
21
+ const scaleSource = (
22
+ /** @type {import("../spec/channel.js").ChannelWithScale}*/ channel
23
+ ) => unitView.getScaleResolution(channel)?.scale;
27
24
 
28
25
  for (const [channel, channelDef] of Object.entries(encoding)) {
29
26
  if (!channelDef) {
30
27
  continue;
31
28
  }
32
29
 
33
- const channelWithScale =
34
- ((isChannelDefWithScale(channelDef) &&
35
- channelDef.resolutionChannel) ??
36
- (isChannelWithScale(channel) && channel)) ||
37
- undefined;
38
-
39
- const resolution = mark.unitView.getScaleResolution(channelWithScale);
40
-
41
- encoders[channel] = createEncoder(
42
- mark,
43
- encoding[channel],
44
- resolution?.scale,
45
- mark.unitView.getAccessor(channel),
46
- channel
30
+ encoders[channel] = createSimpleOrConditionalEncoder(
31
+ createConditionalAccessors(
32
+ channel,
33
+ channelDef,
34
+ unitView.paramMediator
35
+ ),
36
+ scaleSource
47
37
  );
48
38
  }
49
39
 
@@ -51,109 +41,85 @@ export default function createEncoders(mark, encoding) {
51
41
  }
52
42
 
53
43
  /**
54
- * @param {import("../marks/mark.js").default} mark
55
- * @param {import("../spec/channel.js").ChannelDef} channelDef
56
- * @param {any} scale
57
- * @param {Accessor} accessor
58
- * @param {Channel} channel
44
+ * @param {import("../types/encoder.js").Accessor[]} accessors
45
+ * @param {(channel: import("../spec/channel.js").ChannelWithScale) => import("../types/encoder.js").VegaScale} scaleSource
59
46
  * @returns {Encoder}
60
47
  */
61
- export function createEncoder(mark, channelDef, scale, accessor, channel) {
48
+ export function createSimpleOrConditionalEncoder(accessors, scaleSource) {
62
49
  /**
63
- * @typedef {import("../spec/channel.js").Channel} Channel
64
50
  * @typedef {import("../types/encoder.js").Encoder} Encoder
65
51
  * @typedef {import("../types/encoder.js").Accessor} Accessor
52
+ * @typedef {import("../data/flowNode.js").Datum} Datum
66
53
  */
54
+ if (accessors.length === 1) {
55
+ return createEncoder(accessors[0], scaleSource);
56
+ }
67
57
 
68
- /** @type {Encoder} */
69
- let encoder;
70
-
71
- if (isValueDef(channelDef)) {
72
- if (isExprRef(channelDef.value)) {
73
- const fn = mark.unitView.paramMediator.createExpression(
74
- channelDef.value.expr
75
- );
76
- encoder = /** @type {Encoder} */ ((datum) => fn(null));
77
- encoder.constant = true;
78
- encoder.constantValue = false;
79
- encoder.accessor = accessor;
80
- } else {
81
- const value = channelDef.value;
82
- encoder = /** @type {Encoder} */ ((datum) => value);
83
- encoder.constant = true;
84
- encoder.constantValue = true;
85
- encoder.accessor = undefined;
86
- }
87
- } else if (accessor) {
88
- if (channel == "text") {
89
- // TODO: Define somewhere channels that don't use a scale
90
- encoder = /** @type {Encoder} */ ((datum) => undefined);
91
- encoder.accessor = accessor;
92
- encoder.constant = accessor.constant;
93
- } else {
94
- if (!scale) {
95
- if (!isChannelWithScale(channel)) {
96
- // Channels like uniqueId are passed as is.
97
- scale = scaleNull();
98
- } else {
99
- throw new Error(
100
- `Missing scale! "${channel}": ${JSON.stringify(
101
- channelDef
102
- )}`
103
- );
58
+ const predicates = accessors.map((a) => a.predicate);
59
+
60
+ const encoders = accessors.map((a) => createEncoder(a, scaleSource));
61
+
62
+ const encoder = Object.assign(
63
+ (/** @type {Datum} */ datum) => {
64
+ for (let i = 0; i < encoders.length; i++) {
65
+ if (predicates[i](datum)) {
66
+ return encoders[i](datum);
104
67
  }
105
68
  }
69
+ },
70
+ {
71
+ constant: false,
72
+ accessors: /** @type {Accessor[]} */ (
73
+ encoders.map((e) => e.accessors[0])
74
+ ),
75
+ dataAccessor: encoders.map((e) => e.dataAccessor).find((a) => a),
76
+ scale: encoders.map((e) => e.scale).find((s) => s),
77
+ channelDef: accessors.at(-1).channelDef,
78
+ }
79
+ );
106
80
 
107
- encoder = /** @type {Encoder} */ (
108
- (datum) => scale(accessor(datum))
109
- );
110
-
111
- if (isDiscrete(scale.type)) {
112
- // TODO: pass the found values back to the scale/resolution
113
- const indexer = createIndexer();
114
- // Warning: There's a chance that the domain and indexer get out of sync.
115
- // TODO: Make this more robust
116
- indexer.addAll(scale.domain());
117
- encoder.indexer = indexer;
118
- }
81
+ return encoder;
82
+ }
119
83
 
120
- encoder.constant = accessor.constant;
121
- encoder.accessor = accessor;
122
- encoder.scale = scale;
123
- }
124
- } else {
84
+ /**
85
+ * @param {Accessor} accessor
86
+ * @param {(channel: import("../spec/channel.js").ChannelWithScale) => import("../types/encoder.js").VegaScale} scaleSource
87
+ * @returns {Encoder}
88
+ */
89
+ export function createEncoder(accessor, scaleSource) {
90
+ /**
91
+ * @typedef {import("../types/encoder.js").Encoder} Encoder
92
+ * @typedef {import("../types/encoder.js").Accessor} Accessor
93
+ * @typedef {import("../data/flowNode.js").Datum} Datum
94
+ */
95
+
96
+ const { channel, scaleChannel, channelDef } = accessor;
97
+
98
+ const scale = accessor.scaleChannel ? scaleSource(scaleChannel) : undefined;
99
+
100
+ if (scaleChannel && !scale) {
125
101
  throw new Error(
126
- `Missing value or accessor (field, expr, datum) on channel "${channel}": ${JSON.stringify(
127
- channelDef
128
- )}`
102
+ `Missing scale! "${channel}": ${JSON.stringify(channelDef)}`
129
103
  );
130
104
  }
131
105
 
132
- // TODO: Modifier should be inverted too
133
- encoder.invert = scale
134
- ? (value) => scale.invert(value)
135
- : (value) => {
136
- throw new Error(
137
- "No scale available, cannot invert: " +
138
- JSON.stringify(channelDef)
139
- );
140
- };
141
-
142
- // Just to provide a convenient access to the config
143
- encoder.channelDef = channelDef;
144
-
145
- /** @param {Encoder} target */
146
- encoder.applyMetadata = (target) => {
147
- for (const prop in encoder) {
148
- if (prop in encoder) {
149
- // @ts-ignore
150
- target[prop] = encoder[prop];
151
- }
106
+ return Object.assign(
107
+ scale
108
+ ? (/** @type {Datum} */ datum) =>
109
+ scale(
110
+ // @ts-ignore Bad d3 types
111
+ accessor(datum)
112
+ )
113
+ : (/** @type {Datum} */ datum) => accessor(datum),
114
+ {
115
+ scale,
116
+ constant: accessor.constant,
117
+ accessors: [accessor],
118
+ dataAccessor: accessor.constant ? undefined : accessor,
119
+ // TODO: Accessor already has the channelDef
120
+ channelDef,
152
121
  }
153
- return target;
154
- };
155
-
156
- return encoder;
122
+ );
157
123
  }
158
124
 
159
125
  /**
@@ -168,7 +134,7 @@ export function isValueDef(channelDef) {
168
134
 
169
135
  /**
170
136
  * @param {import("../spec/channel.js").ChannelDef} channelDef
171
- * @returns {channelDef is import("../spec/channel.js").FieldDefBase<string>}
137
+ * @returns {channelDef is import("../spec/channel.js").FieldDefBase}
172
138
  */
173
139
  export function isFieldDef(channelDef) {
174
140
  return channelDef && "field" in channelDef;
@@ -233,6 +199,25 @@ export function isExprDef(channelDef) {
233
199
  return channelDef && "expr" in channelDef;
234
200
  }
235
201
 
202
+ /**
203
+ * @param {import("../spec/channel.js").ChannelDef} channelDef
204
+ * @returns {channelDef is import("../spec/channel.js").FieldOrDatumDefWithCondition}
205
+ */
206
+ export function isFieldOrDatumDefWithCondition(channelDef) {
207
+ return (
208
+ (isFieldDef(channelDef) || isDatumDef(channelDef)) &&
209
+ "condition" in channelDef
210
+ );
211
+ }
212
+
213
+ /**
214
+ * @param {import("../spec/channel.js").ChannelDef} channelDef
215
+ * @returns {channelDef is import("../spec/channel.js").ValueDefWithCondition}
216
+ */
217
+ export function isValueDefWithCondition(channelDef) {
218
+ return isValueDef(channelDef) && "condition" in channelDef;
219
+ }
220
+
236
221
  /**
237
222
  * @type {import("../spec/channel.js").PrimaryPositionalChannel[]}
238
223
  */
@@ -344,7 +329,7 @@ export function isColorChannel(channel) {
344
329
  * @param {import("../spec/channel.js").Channel} channel
345
330
  */
346
331
  export function isDiscreteChannel(channel) {
347
- return ["shape", "squeeze"].includes(channel);
332
+ return ["shape"].includes(channel);
348
333
  }
349
334
 
350
335
  /**
@@ -369,7 +354,6 @@ export function isChannelWithScale(channel) {
369
354
  "angle",
370
355
  "dx",
371
356
  "dy",
372
- "sample",
373
357
  ].includes(channel);
374
358
  }
375
359
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=encoder.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoder.test.d.ts","sourceRoot":"","sources":["../../../src/encoder/encoder.test.js"],"names":[],"mappings":""}
@@ -1,101 +1,104 @@
1
1
  import { describe, expect, test } from "vitest";
2
- import AccessorFactory from "./accessor.js";
3
- import { scale as vegaScale } from "vega-scale";
4
2
 
5
- import { createEncoder } from "./encoder.js";
6
-
7
- describe("Encoder", () => {
8
- /** @type {Record<string, import("../view/viewUtils.js").ChannelDef>} */
9
- const encodingSpecs = {
10
- x: { value: 0 },
11
- y: { field: "a" },
12
- z: { datum: 2 },
13
- size: { value: 5 },
14
- };
15
-
16
- const scaleLinear = vegaScale("linear");
17
-
18
- /** @type {Record<string, import("./encoder.js").VegaScale>} */
19
- const scales = {
20
- y: scaleLinear().domain([0, 10]),
21
- z: scaleLinear().domain([0, 20]),
22
- };
23
-
24
- const accessorFactory = new AccessorFactory();
25
-
26
- /** @param {Record<string, import("../view/viewUtils.js").ChannelDef>} encoding */
27
- function createEncoders(encoding) {
28
- /** @type {Record<string, import("./encoder.js").Encoder>} */
29
- const encoders = {};
30
- for (const [channel, channelDef] of Object.entries(encoding)) {
31
- encoders[channel] = createEncoder(
32
- null, // TODO: stub the mark
33
- channelDef,
34
- scales[channel],
35
- accessorFactory.createAccessor(encodingSpecs[channel]),
36
- channel
37
- );
3
+ import { createAccessor, createConditionalAccessors } from "./accessor.js";
4
+ import ParamMediator from "../view/paramMediator.js";
5
+ import { createEncoder, createSimpleOrConditionalEncoder } from "./encoder.js";
6
+ import { UNIQUE_ID_KEY } from "../data/transforms/identifier.js";
7
+ import { createSinglePointSelection } from "../selection/selection.js";
8
+ import { isArray } from "vega-util";
9
+ import { scaleLinear } from "d3-scale";
10
+
11
+ /** @type {import("../spec/channel.js").Encoding} */
12
+ const encoding = {
13
+ x: { value: 42 },
14
+ y: {
15
+ field: "a",
16
+ type: "quantitative",
17
+ scale: { domain: [0, 100], range: [0, 1] },
18
+ },
19
+ size: {
20
+ field: "a",
21
+ type: "quantitative",
22
+ scale: { domain: [0, 100], range: [0, 10] },
23
+ condition: {
24
+ param: "p",
25
+ empty: false,
26
+ value: 5000,
27
+ },
28
+ },
29
+ };
30
+
31
+ const scaleSource = (
32
+ /** @type {import("../spec/channel.js").ChannelWithScale} */ channel
33
+ ) => {
34
+ // @ts-ignore
35
+ const props = encoding[channel].scale ?? encoding[channel].condition?.scale;
36
+
37
+ return Object.assign(
38
+ scaleLinear().domain(props.domain).range(props.range),
39
+ {
40
+ type: "linear",
38
41
  }
39
- return encoders;
40
- }
42
+ );
43
+ };
41
44
 
42
- const datum = {
43
- a: 5,
44
- b: 6,
45
- c: "Pink Floyd",
46
- };
45
+ const datum = {
46
+ a: 100,
47
+ b: 6,
48
+ c: "Pink Floyd",
49
+ [UNIQUE_ID_KEY]: 1234,
50
+ };
47
51
 
48
- test("Throws on a broken spec", () =>
49
- expect(() => createEncoders({ x: {} })).toThrow());
52
+ describe("Encoder", () => {
53
+ const pm = new ParamMediator();
54
+ /** @type {Partial<Record<import("../spec/channel.js").Channel, import("../types/encoder.js").Encoder>>} */
55
+ const e = Object.fromEntries(
56
+ Object.entries(encoding).map(([channel, channelDef]) => {
57
+ const accessor = createAccessor(channel, channelDef, pm);
58
+ return [channel, createEncoder(accessor, scaleSource)];
59
+ })
60
+ );
61
+
62
+ test("has a single accessors", () => {
63
+ expect(e.x.accessors?.length).toBe(1);
64
+ });
50
65
 
51
- const encoders = createEncoders(encodingSpecs);
66
+ test("provides a data accessor for a FieldDef", () =>
67
+ expect(e.y.dataAccessor.fields).toContain("a"));
52
68
 
53
- test("The encoder object contains all channels", () =>
54
- expect(
55
- ["x", "y", "z", "size"].every(
56
- (channel) => typeof encoders[channel] === "function"
57
- )
58
- ).toBeTruthy());
69
+ test("doesn't provide a data accessor for a ValueDef", () =>
70
+ expect(e.x.dataAccessor).toBeUndefined());
59
71
 
60
- test("Returns a value", () => expect(encoders.x(datum)).toEqual(0));
72
+ test("returns a value", () => expect(e.x(datum)).toEqual(42));
61
73
 
62
- test("Encodes and returns a constant using a scale", () =>
63
- expect(encoders.z(datum)).toBeCloseTo(0.1));
74
+ test("accesses a field and uses a scale", () => expect(e.y(datum)).toBe(1));
64
75
 
65
- test("Accesses a field and uses a scale", () =>
66
- expect(encoders.y(datum)).toBeCloseTo(0.5));
76
+ // TODO: Text ExprRef
77
+ });
67
78
 
68
- /*
69
- test("Accesses a field on a secondary channel and uses the scale from the primary", () =>
70
- expect(encoders.y2(datum)).toBeCloseTo(0.6));
71
- */
79
+ describe("Conditional encoder with a field and a conditional value", () => {
80
+ const pm = new ParamMediator();
81
+ const setter = pm.allocateSetter("p", createSinglePointSelection(null));
72
82
 
73
- test("Constant encoder is annotated", () => {
74
- expect(encoders.y.constant).toBeFalsy();
75
- expect(encoders.z.constant).toBeTruthy();
76
- expect(encoders.size.constant).toBeTruthy();
77
- });
83
+ const e = createSimpleOrConditionalEncoder(
84
+ createConditionalAccessors("size", encoding.size, pm),
85
+ scaleSource
86
+ );
78
87
 
79
- test("Constant value encoder is annotated", () => {
80
- expect(encoders.y.constantValue).toBeFalsy();
81
- expect(encoders.z.constantValue).toBeFalsy();
82
- expect(encoders.size.constantValue).toBeTruthy();
88
+ test("has multiple accessors", () => {
89
+ expect(e.accessors.length).toBe(2);
83
90
  });
84
91
 
85
- test("Inverts a value", () => {
86
- expect(encoders.y.invert(0.5)).toBeCloseTo(5);
87
- expect(encoders.z.invert(0.5)).toBeCloseTo(10);
88
- // A value, no scale, can't invert
89
- expect(() => encoders.size.invert(123)).toThrow();
90
- });
92
+ test("accesses the field using the dataAccessor", () =>
93
+ expect(e.dataAccessor(datum)).toBe(100));
91
94
 
92
- test("Accessors are provided", () => {
93
- expect(encoders.y.accessor).toBeDefined();
94
- expect(encoders.z.accessor).toBeDefined();
95
- expect(encoders.x.accessor).toBeUndefined();
95
+ test("encodes the default when a predicate is false", () => {
96
+ setter(createSinglePointSelection(null));
97
+ expect(e(datum)).toBe(10);
96
98
  });
97
99
 
98
- // TODO: Test indexer
99
-
100
- // TODO: Text ExprRef
100
+ test("encodes the conditional value when a predicate is true", () => {
101
+ setter(createSinglePointSelection(datum));
102
+ expect(e(datum)).toBe(5000);
103
+ });
101
104
  });
@@ -1 +1 @@
1
- {"version":3,"file":"bmFontManager.d.ts","sourceRoot":"","sources":["../../../src/fonts/bmFontManager.js"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IACI;;OAEG;IACH,0BAFW,OAAO,sBAAsB,EAAE,OAAO,EAgChD;IA7BG,qDAA+B;IAE/B,uBACiF;IAEjF;;OAEG;IACH,QAFU,IAAI,OAAO,EAAE,SAAS,CAAC,CAEc;IAE/C,8DAA8D;IAC9D,mBADW,IAAI,MAAM,EAAE,QAAQ,uBAAuB,EAAE,CAAC,CAAC,CACxB;IAElC,kDAAkD;IAClD,eADW,IAAI,MAAM,EAAE,QAAQ,aAAa,CAAC,CAAC,CAChB;IAE9B,uEAAuE;IACvE,WADW,QAAQ,IAAI,CAAC,EAAE,CACP;IAEnB;;;OAGG;IACH,mBAFU,SAAS,CAOlB;IAGL,gCAEC;IAED;;;;;;OAMG;IACH,gBALW,MAAM,UACN,SAAS,WACT,UAAU,GAAG;;;;;;;;KAAa,GACxB,SAAS,CAyBrB;IAED;;;;OAIG;IACH,0BAHW,SAAS,OACT,OAAO,iBAwBjB;IAED;;OAEG;IACH,eAFW,MAAM,uDAoBhB;IAED;;;OAGG;IACH,sBAFW,MAAM,sCA2BhB;IAED,4BAEC;IAED;;;;OAIG;IACH,0BAHW,MAAM,GACJ,QAAQ,YAAY,CAAC,CAqBjC;IAED;;;;OAIG;IACH,6BAHW,MAAM,GACJ,YAAY,CA0BxB;CACJ;;;;;;;;;;UAgBS,MAAM;;;;WACN,MAAM;;;;YACN,MAAM;;;;cACN,MAAM;;;;sBACN,MAAM;;;;eACN,MAAM;;;;eACN,MAAM;;;;;;;;;qBA5PH,OAAO,oBAAoB,EAAE,MAAM;;;;;;;;4BACnC,OAAO,oBAAoB,EAAE,aAAa;;;;;;;;wBAE1C,QAAQ,GAAG,QAAQ;;;;;;;;yBACnB,MAAM;;;;;;;;;YAGT,MAAM;WACN,SAAS;YACT,UAAU;;;;;;;;;;aAGV,aAAa;aACb,YAAY"}
1
+ {"version":3,"file":"bmFontManager.d.ts","sourceRoot":"","sources":["../../../src/fonts/bmFontManager.js"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IACI;;OAEG;IACH,0BAFW,OAAO,sBAAsB,EAAE,OAAO,EAgChD;IA7BG,qDAA+B;IAE/B,uBACiF;IAEjF;;OAEG;IACH,QAFU,IAAI,OAAO,EAAE,SAAS,CAAC,CAEc;IAE/C,8DAA8D;IAC9D,mBADW,IAAI,MAAM,EAAE,QAAQ,uBAAuB,EAAE,CAAC,CAAC,CACxB;IAElC,kDAAkD;IAClD,eADW,IAAI,MAAM,EAAE,QAAQ,aAAa,CAAC,CAAC,CAChB;IAE9B,uEAAuE;IACvE,WADW,QAAQ,IAAI,CAAC,EAAE,CACP;IAEnB;;;OAGG;IACH,mBAFU,SAAS,CAOlB;IAGL,gCAEC;IAED;;;;;;OAMG;IACH,gBALW,MAAM,UACN,SAAS,WACT,UAAU,GAAG;;;;;;;;KAAa,GACxB,SAAS,CAyBrB;IAED;;;;OAIG;IACH,0BAHW,SAAS,OACT,OAAO,iBA0BjB;IAED;;OAEG;IACH,eAFW,MAAM,uDAoBhB;IAED;;;OAGG;IACH,sBAFW,MAAM,sCA+BhB;IAED,4BAEC;IAED;;;;OAIG;IACH,0BAHW,MAAM,GACJ,QAAQ,YAAY,CAAC,CAqBjC;IAED;;;;OAIG;IACH,6BAHW,MAAM,GACJ,YAAY,CA0BxB;CACJ;;;;;;;;;;UAgBS,MAAM;;;;WACN,MAAM;;;;YACN,MAAM;;;;cACN,MAAM;;;;sBACN,MAAM;;;;eACN,MAAM;;;;eACN,MAAM;;;;;;;;;qBAlQH,OAAO,oBAAoB,EAAE,MAAM;;;;;;;;4BACnC,OAAO,oBAAoB,EAAE,aAAa;;;;;;;;wBAE1C,QAAQ,GAAG,QAAQ;;;;;;;;yBACnB,MAAM;;;;;;;;;YAGT,MAAM;WACN,SAAS;YACT,UAAU;;;;;;;;;;aAGV,aAAa;aACb,YAAY"}
@@ -132,7 +132,9 @@ export default class BmFontManager {
132
132
  fontEntry.texture = await texturePromise;
133
133
  fontEntry.metrics = await metricsPromise;
134
134
  } catch (error) {
135
- console.log("Cannot load font. Using default.", error);
135
+ console.warn(
136
+ `Cannot load font: "${key.family}". Using the embedded default font.`
137
+ );
136
138
 
137
139
  fontEntry.metrics = this._defaultFontEntry.metrics;
138
140
  fontEntry.texture = this._defaultFontEntry.texture;
@@ -171,11 +173,15 @@ export default class BmFontManager {
171
173
 
172
174
  let promise = this._metadataPromises.get(dir);
173
175
  if (!promise) {
174
- promise = fetch(this.fontRepository + dir + "/METADATA.pb")
176
+ const url = this.fontRepository + dir + "/METADATA.pb";
177
+ promise = fetch(url)
175
178
  .then((response) => {
176
179
  if (!response.ok) {
177
180
  throw new Error(
178
- "Could not load font metadata: " + response.status
181
+ "Could not load font metadata. Response status: " +
182
+ response.status +
183
+ ", url: " +
184
+ url
179
185
  );
180
186
  }
181
187
  return response;
@@ -183,7 +189,7 @@ export default class BmFontManager {
183
189
  .then((response) => response.text())
184
190
  .then((text) => parseMetadataPb(text))
185
191
  .catch((error) => {
186
- console.warn(error);
192
+ console.warn(error.message);
187
193
  return undefined;
188
194
  });
189
195
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=genome.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"genome.test.d.ts","sourceRoot":"","sources":["../../../src/genome/genome.test.js"],"names":[],"mappings":""}