graphein 0.20.0 → 0.22.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 (319) hide show
  1. package/dist/animation/animate.d.ts +6 -1
  2. package/dist/animation/animate.d.ts.map +1 -1
  3. package/dist/animation/animate.js +2 -2
  4. package/dist/animation/animate.js.map +2 -2
  5. package/dist/animation/env.d.ts +5 -0
  6. package/dist/animation/env.d.ts.map +1 -1
  7. package/dist/animation/env.js +4 -0
  8. package/dist/animation/env.js.map +2 -2
  9. package/dist/animation/index.d.ts +1 -0
  10. package/dist/animation/index.d.ts.map +1 -1
  11. package/dist/animation/index.js +1 -0
  12. package/dist/animation/index.js.map +2 -2
  13. package/dist/animation/stagger.d.ts +13 -0
  14. package/dist/animation/stagger.d.ts.map +1 -0
  15. package/dist/animation/stagger.js +13 -0
  16. package/dist/animation/stagger.js.map +7 -0
  17. package/dist/axes/draw.d.ts +5 -1
  18. package/dist/axes/draw.d.ts.map +1 -1
  19. package/dist/axes/draw.js +13 -1
  20. package/dist/axes/draw.js.map +2 -2
  21. package/dist/axes/morph.d.ts +111 -0
  22. package/dist/axes/morph.d.ts.map +1 -0
  23. package/dist/axes/morph.js +207 -0
  24. package/dist/axes/morph.js.map +7 -0
  25. package/dist/axes/overlay.d.ts.map +1 -1
  26. package/dist/axes/overlay.js +88 -25
  27. package/dist/axes/overlay.js.map +2 -2
  28. package/dist/axes/text.d.ts +2 -0
  29. package/dist/axes/text.d.ts.map +1 -1
  30. package/dist/axes/text.js +1 -0
  31. package/dist/axes/text.js.map +2 -2
  32. package/dist/axes/tickLabels.d.ts +2 -0
  33. package/dist/axes/tickLabels.d.ts.map +1 -1
  34. package/dist/axes/tickLabels.js +2 -2
  35. package/dist/axes/tickLabels.js.map +2 -2
  36. package/dist/charts/annotations.d.ts +9 -3
  37. package/dist/charts/annotations.d.ts.map +1 -1
  38. package/dist/charts/annotations.js +82 -27
  39. package/dist/charts/annotations.js.map +2 -2
  40. package/dist/charts/area.d.ts +37 -1
  41. package/dist/charts/area.d.ts.map +1 -1
  42. package/dist/charts/area.js +35 -17
  43. package/dist/charts/area.js.map +2 -2
  44. package/dist/charts/bar.d.ts +53 -0
  45. package/dist/charts/bar.d.ts.map +1 -1
  46. package/dist/charts/bar.js +117 -83
  47. package/dist/charts/bar.js.map +2 -2
  48. package/dist/charts/box.d.ts +31 -0
  49. package/dist/charts/box.d.ts.map +1 -1
  50. package/dist/charts/box.js +93 -70
  51. package/dist/charts/box.js.map +2 -2
  52. package/dist/charts/bubbleMap.d.ts +20 -0
  53. package/dist/charts/bubbleMap.d.ts.map +1 -0
  54. package/dist/charts/bubbleMap.js +951 -0
  55. package/dist/charts/bubbleMap.js.map +7 -0
  56. package/dist/charts/bullet.d.ts.map +1 -1
  57. package/dist/charts/bullet.js +69 -51
  58. package/dist/charts/bullet.js.map +2 -2
  59. package/dist/charts/calendarHeatmap.d.ts.map +1 -1
  60. package/dist/charts/calendarHeatmap.js +56 -19
  61. package/dist/charts/calendarHeatmap.js.map +2 -2
  62. package/dist/charts/candlestick.d.ts +40 -0
  63. package/dist/charts/candlestick.d.ts.map +1 -0
  64. package/dist/charts/candlestick.js +325 -0
  65. package/dist/charts/candlestick.js.map +7 -0
  66. package/dist/charts/choropleth.d.ts.map +1 -1
  67. package/dist/charts/choropleth.js +46 -67
  68. package/dist/charts/choropleth.js.map +2 -2
  69. package/dist/charts/combo.d.ts.map +1 -1
  70. package/dist/charts/combo.js +127 -27
  71. package/dist/charts/combo.js.map +3 -3
  72. package/dist/charts/dumbbell.d.ts.map +1 -1
  73. package/dist/charts/dumbbell.js +100 -31
  74. package/dist/charts/dumbbell.js.map +2 -2
  75. package/dist/charts/funnel.d.ts.map +1 -1
  76. package/dist/charts/funnel.js +93 -28
  77. package/dist/charts/funnel.js.map +3 -3
  78. package/dist/charts/gantt.d.ts +22 -0
  79. package/dist/charts/gantt.d.ts.map +1 -0
  80. package/dist/charts/gantt.js +564 -0
  81. package/dist/charts/gantt.js.map +7 -0
  82. package/dist/charts/gauge.d.ts.map +1 -1
  83. package/dist/charts/gauge.js +30 -4
  84. package/dist/charts/gauge.js.map +2 -2
  85. package/dist/charts/geo.d.ts +87 -0
  86. package/dist/charts/geo.d.ts.map +1 -0
  87. package/dist/charts/geo.js +140 -0
  88. package/dist/charts/geo.js.map +7 -0
  89. package/dist/charts/geometry.d.ts +20 -0
  90. package/dist/charts/geometry.d.ts.map +1 -0
  91. package/dist/charts/geometry.js +25 -0
  92. package/dist/charts/geometry.js.map +7 -0
  93. package/dist/charts/heatmap.d.ts.map +1 -1
  94. package/dist/charts/heatmap.js +58 -49
  95. package/dist/charts/heatmap.js.map +2 -2
  96. package/dist/charts/histogram.d.ts +1 -1
  97. package/dist/charts/histogram.d.ts.map +1 -1
  98. package/dist/charts/histogram.js +49 -31
  99. package/dist/charts/histogram.js.map +2 -2
  100. package/dist/charts/index.d.ts +35 -1
  101. package/dist/charts/index.d.ts.map +1 -1
  102. package/dist/charts/index.js +12 -0
  103. package/dist/charts/index.js.map +2 -2
  104. package/dist/charts/legibility.d.ts +38 -0
  105. package/dist/charts/legibility.d.ts.map +1 -0
  106. package/dist/charts/legibility.js +72 -0
  107. package/dist/charts/legibility.js.map +7 -0
  108. package/dist/charts/line.d.ts +39 -1
  109. package/dist/charts/line.d.ts.map +1 -1
  110. package/dist/charts/line.js +48 -16
  111. package/dist/charts/line.js.map +2 -2
  112. package/dist/charts/matrix.d.ts +2 -1
  113. package/dist/charts/matrix.d.ts.map +1 -1
  114. package/dist/charts/matrix.js +481 -319
  115. package/dist/charts/matrix.js.map +3 -3
  116. package/dist/charts/morphFrame.d.ts +83 -0
  117. package/dist/charts/morphFrame.d.ts.map +1 -0
  118. package/dist/charts/morphFrame.js +128 -0
  119. package/dist/charts/morphFrame.js.map +7 -0
  120. package/dist/charts/pie.d.ts.map +1 -1
  121. package/dist/charts/pie.js +89 -26
  122. package/dist/charts/pie.js.map +2 -2
  123. package/dist/charts/pieState.d.ts +27 -0
  124. package/dist/charts/pieState.d.ts.map +1 -0
  125. package/dist/charts/pieState.js +55 -0
  126. package/dist/charts/pieState.js.map +7 -0
  127. package/dist/charts/radar.d.ts +62 -0
  128. package/dist/charts/radar.d.ts.map +1 -0
  129. package/dist/charts/radar.js +912 -0
  130. package/dist/charts/radar.js.map +7 -0
  131. package/dist/charts/radialBar.d.ts +60 -0
  132. package/dist/charts/radialBar.d.ts.map +1 -0
  133. package/dist/charts/radialBar.js +708 -0
  134. package/dist/charts/radialBar.js.map +7 -0
  135. package/dist/charts/sankey.d.ts.map +1 -1
  136. package/dist/charts/sankey.js +223 -57
  137. package/dist/charts/sankey.js.map +3 -3
  138. package/dist/charts/scatter.d.ts +31 -0
  139. package/dist/charts/scatter.d.ts.map +1 -1
  140. package/dist/charts/scatter.js +48 -12
  141. package/dist/charts/scatter.js.map +2 -2
  142. package/dist/charts/slope.d.ts.map +1 -1
  143. package/dist/charts/slope.js +55 -3
  144. package/dist/charts/slope.js.map +2 -2
  145. package/dist/charts/sunburst.d.ts +14 -0
  146. package/dist/charts/sunburst.d.ts.map +1 -0
  147. package/dist/charts/sunburst.js +885 -0
  148. package/dist/charts/sunburst.js.map +7 -0
  149. package/dist/charts/table.d.ts +2 -1
  150. package/dist/charts/table.d.ts.map +1 -1
  151. package/dist/charts/table.js +214 -224
  152. package/dist/charts/table.js.map +3 -3
  153. package/dist/charts/tableView/canvas.d.ts +16 -1
  154. package/dist/charts/tableView/canvas.d.ts.map +1 -1
  155. package/dist/charts/tableView/canvas.js +361 -252
  156. package/dist/charts/tableView/canvas.js.map +3 -3
  157. package/dist/charts/tableView/conditional.d.ts +66 -40
  158. package/dist/charts/tableView/conditional.d.ts.map +1 -1
  159. package/dist/charts/tableView/conditional.js +163 -256
  160. package/dist/charts/tableView/conditional.js.map +3 -3
  161. package/dist/charts/tableView/dom.d.ts +26 -2
  162. package/dist/charts/tableView/dom.d.ts.map +1 -1
  163. package/dist/charts/tableView/dom.js +609 -269
  164. package/dist/charts/tableView/dom.js.map +3 -3
  165. package/dist/charts/tableView/layout.d.ts +22 -0
  166. package/dist/charts/tableView/layout.d.ts.map +1 -0
  167. package/dist/charts/tableView/layout.js +246 -0
  168. package/dist/charts/tableView/layout.js.map +7 -0
  169. package/dist/charts/tableView/sketch.d.ts +3 -2
  170. package/dist/charts/tableView/sketch.d.ts.map +1 -1
  171. package/dist/charts/tableView/sketch.js +2 -2
  172. package/dist/charts/tableView/sketch.js.map +2 -2
  173. package/dist/charts/tableView/sketchBar.d.ts +7 -0
  174. package/dist/charts/tableView/sketchBar.d.ts.map +1 -0
  175. package/dist/charts/tableView/sketchBar.js +32 -0
  176. package/dist/charts/tableView/sketchBar.js.map +7 -0
  177. package/dist/charts/tableView/sort.d.ts +9 -0
  178. package/dist/charts/tableView/sort.d.ts.map +1 -0
  179. package/dist/charts/tableView/sort.js +70 -0
  180. package/dist/charts/tableView/sort.js.map +7 -0
  181. package/dist/charts/tableView/sparkline.d.ts +30 -0
  182. package/dist/charts/tableView/sparkline.d.ts.map +1 -0
  183. package/dist/charts/tableView/sparkline.js +63 -0
  184. package/dist/charts/tableView/sparkline.js.map +7 -0
  185. package/dist/charts/tableView/style.d.ts +67 -0
  186. package/dist/charts/tableView/style.d.ts.map +1 -0
  187. package/dist/charts/tableView/style.js +131 -0
  188. package/dist/charts/tableView/style.js.map +7 -0
  189. package/dist/charts/tableView/types.d.ts +69 -46
  190. package/dist/charts/tableView/types.d.ts.map +1 -1
  191. package/dist/charts/tableView/types.js +22 -87
  192. package/dist/charts/tableView/types.js.map +2 -2
  193. package/dist/charts/tableView.d.ts +10 -5
  194. package/dist/charts/tableView.d.ts.map +1 -1
  195. package/dist/charts/tableView.js +12 -8
  196. package/dist/charts/tableView.js.map +2 -2
  197. package/dist/charts/treemap.d.ts.map +1 -1
  198. package/dist/charts/treemap.js +177 -68
  199. package/dist/charts/treemap.js.map +3 -3
  200. package/dist/charts/trendline.d.ts +13 -5
  201. package/dist/charts/trendline.d.ts.map +1 -1
  202. package/dist/charts/trendline.js +205 -56
  203. package/dist/charts/trendline.js.map +2 -2
  204. package/dist/charts/waterfall.d.ts.map +1 -1
  205. package/dist/charts/waterfall.js +76 -5
  206. package/dist/charts/waterfall.js.map +2 -2
  207. package/dist/index.d.ts +1 -1
  208. package/dist/index.js +1 -1
  209. package/dist/index.js.map +1 -1
  210. package/dist/interaction/cartesian.d.ts +4 -1
  211. package/dist/interaction/cartesian.d.ts.map +1 -1
  212. package/dist/interaction/cartesian.js +104 -34
  213. package/dist/interaction/cartesian.js.map +2 -2
  214. package/dist/interaction/controller.d.ts +29 -1
  215. package/dist/interaction/controller.d.ts.map +1 -1
  216. package/dist/interaction/controller.js +131 -8
  217. package/dist/interaction/controller.js.map +2 -2
  218. package/dist/interaction/focus.d.ts +23 -0
  219. package/dist/interaction/focus.d.ts.map +1 -0
  220. package/dist/interaction/focus.js +65 -0
  221. package/dist/interaction/focus.js.map +7 -0
  222. package/dist/interaction/tooltip.d.ts +6 -0
  223. package/dist/interaction/tooltip.d.ts.map +1 -1
  224. package/dist/interaction/tooltip.js +41 -16
  225. package/dist/interaction/tooltip.js.map +2 -2
  226. package/dist/interaction/types.d.ts +19 -0
  227. package/dist/interaction/types.d.ts.map +1 -1
  228. package/dist/interaction/veil.d.ts +25 -0
  229. package/dist/interaction/veil.d.ts.map +1 -0
  230. package/dist/interaction/veil.js +35 -0
  231. package/dist/interaction/veil.js.map +7 -0
  232. package/dist/pivot/pivot.d.ts +18 -0
  233. package/dist/pivot/pivot.d.ts.map +1 -1
  234. package/dist/pivot/pivot.js +46 -34
  235. package/dist/pivot/pivot.js.map +2 -2
  236. package/dist/render/chromeMotion.d.ts +65 -0
  237. package/dist/render/chromeMotion.d.ts.map +1 -0
  238. package/dist/render/chromeMotion.js +79 -0
  239. package/dist/render/chromeMotion.js.map +7 -0
  240. package/dist/render/pathSample.d.ts +24 -0
  241. package/dist/render/pathSample.d.ts.map +1 -0
  242. package/dist/render/pathSample.js +76 -0
  243. package/dist/render/pathSample.js.map +7 -0
  244. package/dist/render/transient.d.ts +18 -0
  245. package/dist/render/transient.d.ts.map +1 -0
  246. package/dist/render/transient.js +19 -0
  247. package/dist/render/transient.js.map +7 -0
  248. package/dist/runtime/candlestick.d.ts +112 -0
  249. package/dist/runtime/candlestick.d.ts.map +1 -0
  250. package/dist/runtime/candlestick.js +531 -0
  251. package/dist/runtime/candlestick.js.map +7 -0
  252. package/dist/runtime/cartesian.d.ts +14 -3
  253. package/dist/runtime/cartesian.d.ts.map +1 -1
  254. package/dist/runtime/cartesian.js.map +2 -2
  255. package/dist/runtime/chartAnimation.d.ts +54 -7
  256. package/dist/runtime/chartAnimation.d.ts.map +1 -1
  257. package/dist/runtime/chartAnimation.js +146 -28
  258. package/dist/runtime/chartAnimation.js.map +2 -2
  259. package/dist/runtime/chartRuntime.d.ts +42 -0
  260. package/dist/runtime/chartRuntime.d.ts.map +1 -1
  261. package/dist/runtime/chartRuntime.js +196 -30
  262. package/dist/runtime/chartRuntime.js.map +2 -2
  263. package/dist/runtime/dashboardDom.d.ts.map +1 -1
  264. package/dist/runtime/dashboardDom.js +45 -0
  265. package/dist/runtime/dashboardDom.js.map +2 -2
  266. package/dist/runtime/facet.d.ts +1 -1
  267. package/dist/runtime/facet.d.ts.map +1 -1
  268. package/dist/runtime/gantt.d.ts +137 -0
  269. package/dist/runtime/gantt.d.ts.map +1 -0
  270. package/dist/runtime/gantt.js +647 -0
  271. package/dist/runtime/gantt.js.map +7 -0
  272. package/dist/runtime/morph.d.ts +33 -0
  273. package/dist/runtime/morph.d.ts.map +1 -0
  274. package/dist/runtime/morph.js +332 -0
  275. package/dist/runtime/morph.js.map +7 -0
  276. package/dist/runtime/radar.d.ts +75 -0
  277. package/dist/runtime/radar.d.ts.map +1 -0
  278. package/dist/runtime/radar.js +201 -0
  279. package/dist/runtime/radar.js.map +7 -0
  280. package/dist/runtime/radialBar.d.ts +81 -0
  281. package/dist/runtime/radialBar.d.ts.map +1 -0
  282. package/dist/runtime/radialBar.js +125 -0
  283. package/dist/runtime/radialBar.js.map +7 -0
  284. package/dist/runtime/report/constants.d.ts +2 -2
  285. package/dist/runtime/report/constants.d.ts.map +1 -1
  286. package/dist/runtime/runtimeShared.d.ts +3 -3
  287. package/dist/runtime/runtimeShared.d.ts.map +1 -1
  288. package/dist/runtime/sunburst.d.ts +74 -0
  289. package/dist/runtime/sunburst.d.ts.map +1 -0
  290. package/dist/runtime/sunburst.js +150 -0
  291. package/dist/runtime/sunburst.js.map +7 -0
  292. package/dist/runtime/wire.d.ts.map +1 -1
  293. package/dist/runtime/wire.js +3 -1
  294. package/dist/runtime/wire.js.map +2 -2
  295. package/dist/shape/arc.d.ts +15 -2
  296. package/dist/shape/arc.d.ts.map +1 -1
  297. package/dist/shape/arc.js +204 -32
  298. package/dist/shape/arc.js.map +2 -2
  299. package/dist/spec/chartDefinitions.d.ts +6 -0
  300. package/dist/spec/chartDefinitions.d.ts.map +1 -1
  301. package/dist/spec/chartDefinitions.js +7 -1
  302. package/dist/spec/chartDefinitions.js.map +2 -2
  303. package/dist/spec/templates.d.ts.map +1 -1
  304. package/dist/spec/templates.js +177 -2
  305. package/dist/spec/templates.js.map +2 -2
  306. package/dist/spec/types.d.ts +258 -6
  307. package/dist/spec/types.d.ts.map +1 -1
  308. package/dist/spec/types.js +6 -0
  309. package/dist/spec/types.js.map +2 -2
  310. package/dist/spec/validate/charts.js +147 -15
  311. package/dist/spec/validate/charts.js.map +2 -2
  312. package/dist/spec/validate/common.d.ts +6 -0
  313. package/dist/spec/validate/common.d.ts.map +1 -1
  314. package/dist/spec/validate/overlays.js +2 -2
  315. package/dist/spec/validate/overlays.js.map +2 -2
  316. package/dist/spec/validate.data.d.ts.map +1 -1
  317. package/dist/spec/validate.data.js +8 -3
  318. package/dist/spec/validate.data.js.map +2 -2
  319. package/package.json +1 -1
@@ -87,82 +87,76 @@ function computeBoxes(model) {
87
87
  });
88
88
  return geoms.length ? { geoms, showOutliers } : null;
89
89
  }
90
- function drawBoxWhiskers(ctx, geom, yLo, yHi, top, bottom, capHalf) {
90
+ function drawBoxWhiskers(ctx, mark, top, bottom, capHalf) {
91
91
  ctx.beginPath();
92
- ctx.moveTo(geom.cx, yHi);
93
- ctx.lineTo(geom.cx, top);
94
- ctx.moveTo(geom.cx, bottom);
95
- ctx.lineTo(geom.cx, yLo);
96
- ctx.moveTo(geom.cx - capHalf, yHi);
97
- ctx.lineTo(geom.cx + capHalf, yHi);
98
- ctx.moveTo(geom.cx - capHalf, yLo);
99
- ctx.lineTo(geom.cx + capHalf, yLo);
92
+ ctx.moveTo(mark.cx, mark.yHi);
93
+ ctx.lineTo(mark.cx, top);
94
+ ctx.moveTo(mark.cx, bottom);
95
+ ctx.lineTo(mark.cx, mark.yLo);
96
+ ctx.moveTo(mark.cx - capHalf, mark.yHi);
97
+ ctx.lineTo(mark.cx + capHalf, mark.yHi);
98
+ ctx.moveTo(mark.cx - capHalf, mark.yLo);
99
+ ctx.lineTo(mark.cx + capHalf, mark.yLo);
100
100
  ctx.stroke();
101
101
  }
102
- function drawBoxBody(ctx, geom, top, height, yMed) {
102
+ function drawBoxBody(ctx, mark, top, height) {
103
+ const left = mark.cx - mark.boxW / 2;
103
104
  ctx.beginPath();
104
- roundedRect(ctx, geom.left, top, geom.boxW, height, Math.min(3, geom.boxW / 4));
105
- ctx.fillStyle = withAlpha(geom.color, 0.16);
105
+ roundedRect(ctx, left, top, mark.boxW, height, Math.min(3, mark.boxW / 4));
106
+ ctx.fillStyle = withAlpha(mark.color, 0.16);
106
107
  ctx.fill();
107
108
  ctx.stroke();
108
109
  ctx.beginPath();
109
- ctx.moveTo(geom.left, yMed);
110
- ctx.lineTo(geom.right, yMed);
110
+ ctx.moveTo(left, mark.yMed);
111
+ ctx.lineTo(mark.cx + mark.boxW / 2, mark.yMed);
111
112
  ctx.lineWidth = 2;
112
113
  ctx.stroke();
113
114
  }
114
- function drawBoxOutliers(ctx, model, geom) {
115
- ctx.fillStyle = withAlpha(geom.color, 0.6);
116
- for (const o of geom.stats.outliers) {
115
+ function drawBoxOutliers(ctx, mark) {
116
+ ctx.fillStyle = withAlpha(mark.color, 0.6);
117
+ for (const y of mark.outliers) {
117
118
  ctx.beginPath();
118
- ctx.arc(geom.cx, model.y.pixel(o), 1.9, 0, Math.PI * 2);
119
+ ctx.arc(mark.cx, y, 1.9, 0, Math.PI * 2);
119
120
  ctx.fill();
120
121
  }
121
122
  }
122
- function drawOneBoxSketch(pen, model, geom, showOutliers, y, capHalf) {
123
- const { cx, left, right, boxW, stats, color } = geom;
124
- pen.polyline([{ x: cx, y: y.hi }, { x: cx, y: y.top }], { stroke: color });
125
- pen.polyline([{ x: cx, y: y.bottom }, { x: cx, y: y.lo }], { stroke: color });
126
- pen.polyline([{ x: cx - capHalf, y: y.hi }, { x: cx + capHalf, y: y.hi }], { stroke: color });
127
- pen.polyline([{ x: cx - capHalf, y: y.lo }, { x: cx + capHalf, y: y.lo }], { stroke: color });
128
- pen.rect(left, y.top, boxW, y.h, {
123
+ function drawOneBoxSketch(pen, mark, showOutliers, top, bottom, h, capHalf) {
124
+ const { cx, boxW, color } = mark;
125
+ const left = cx - boxW / 2;
126
+ pen.polyline([{ x: cx, y: mark.yHi }, { x: cx, y: top }], { stroke: color });
127
+ pen.polyline([{ x: cx, y: bottom }, { x: cx, y: mark.yLo }], { stroke: color });
128
+ pen.polyline([{ x: cx - capHalf, y: mark.yHi }, { x: cx + capHalf, y: mark.yHi }], { stroke: color });
129
+ pen.polyline([{ x: cx - capHalf, y: mark.yLo }, { x: cx + capHalf, y: mark.yLo }], { stroke: color });
130
+ pen.rect(left, top, boxW, h, {
129
131
  stroke: color,
130
132
  fill: color,
131
133
  fillStyle: "solid",
132
134
  fillAlpha: 0.16
133
135
  });
134
- pen.polyline([{ x: left, y: y.med }, { x: right, y: y.med }], { stroke: color, strokeWidth: 2 });
135
- if (showOutliers && stats.outliers.length) {
136
- for (const o of stats.outliers) {
137
- pen.circle(cx, model.y.pixel(o), 1.9, { fill: withAlpha(color, 0.6) });
136
+ pen.polyline([{ x: left, y: mark.yMed }, { x: cx + boxW / 2, y: mark.yMed }], { stroke: color, strokeWidth: 2 });
137
+ if (showOutliers && mark.outliers.length) {
138
+ for (const y of mark.outliers) {
139
+ pen.circle(cx, y, 1.9, { fill: withAlpha(color, 0.6) });
138
140
  }
139
141
  }
140
142
  }
141
- function drawOneBox(ctx, model, geom, showOutliers, pen) {
142
- const yPix = (v) => model.y.pixel(v);
143
- const { boxW, stats, color } = geom;
144
- const capHalf = boxW * 0.28;
145
- const yQ1 = yPix(stats.q1);
146
- const yQ3 = yPix(stats.q3);
147
- const yMed = yPix(stats.median);
148
- const yLo = yPix(stats.min);
149
- const yHi = yPix(stats.max);
150
- const top = Math.min(yQ1, yQ3);
151
- const bottom = Math.max(yQ1, yQ3);
143
+ function drawOneBox(ctx, mark, showOutliers, pen) {
144
+ const capHalf = mark.boxW * 0.28;
145
+ const top = Math.min(mark.yQ1, mark.yQ3);
146
+ const bottom = Math.max(mark.yQ1, mark.yQ3);
152
147
  const h = Math.max(1, bottom - top);
153
- const y = { q1: yQ1, q3: yQ3, med: yMed, lo: yLo, hi: yHi, top, bottom, h };
154
148
  if (pen) {
155
- drawOneBoxSketch(pen, model, geom, showOutliers, y, capHalf);
149
+ drawOneBoxSketch(pen, mark, showOutliers, top, bottom, h, capHalf);
156
150
  return;
157
151
  }
158
152
  ctx.save();
159
- ctx.strokeStyle = color;
153
+ ctx.strokeStyle = mark.color;
160
154
  ctx.lineWidth = 1.5;
161
155
  ctx.lineCap = "round";
162
- drawBoxWhiskers(ctx, geom, yLo, yHi, top, bottom, capHalf);
163
- drawBoxBody(ctx, geom, top, h, yMed);
164
- if (showOutliers && stats.outliers.length) {
165
- drawBoxOutliers(ctx, model, geom);
156
+ drawBoxWhiskers(ctx, mark, top, bottom, capHalf);
157
+ drawBoxBody(ctx, mark, top, h);
158
+ if (showOutliers && mark.outliers.length) {
159
+ drawBoxOutliers(ctx, mark);
166
160
  }
167
161
  ctx.restore();
168
162
  }
@@ -179,50 +173,65 @@ function hitsBoxGeom(model, geom, showOutliers, px, py) {
179
173
  (o) => Math.abs(px - geom.cx) <= 6 && Math.abs(py - model.y.pixel(o)) <= 6
180
174
  );
181
175
  }
182
- function drawBox(surface, model) {
183
- surface.evidence?.begin("aggregate");
184
- surface.evidence?.data(0, "aggregate");
176
+ function layoutBoxes(model) {
185
177
  const layout = computeBoxes(model);
186
- if (!layout) return;
178
+ if (!layout) return null;
179
+ const emphasis = model.emphasis ?? null;
180
+ const y = (v) => model.y.pixel(v);
181
+ const marks = layout.geoms.map((geom) => ({
182
+ key: geom.key,
183
+ category: toKey(geom.xValue),
184
+ seriesKey: geom.seriesValue === void 0 ? void 0 : toKey(geom.seriesValue),
185
+ color: geom.color,
186
+ cx: geom.cx,
187
+ boxW: geom.boxW,
188
+ yQ1: y(geom.stats.q1),
189
+ yQ3: y(geom.stats.q3),
190
+ yMed: y(geom.stats.median),
191
+ yLo: y(geom.stats.min),
192
+ yHi: y(geom.stats.max),
193
+ outliers: geom.stats.outliers.map(y),
194
+ alpha: emphasis ? emphasis.match(boxProbe(model, geom)) ? 1 : emphasis.dim : 1,
195
+ count: geom.stats.count
196
+ }));
197
+ return { kind: "box", marks, showOutliers: layout.showOutliers };
198
+ }
199
+ function paintBoxes(surface, model, geometry) {
187
200
  const ctx = surface.marks.ctx;
188
201
  const { plot } = model;
189
- const emphasis = model.emphasis ?? null;
190
202
  const pen = model.sketch ? new RoughPen(ctx, model.sketch) : null;
191
- surface.evidence?.data(
192
- layout.geoms.reduce((n, g) => n + g.stats.count, 0),
193
- "aggregate"
194
- );
195
203
  ctx.save();
196
204
  ctx.beginPath();
197
205
  ctx.rect(plot.x, plot.y - 2, plot.width, plot.height + 4);
198
206
  ctx.clip();
199
- for (const geom of layout.geoms) {
200
- const alpha = emphasis ? emphasis.match(boxProbe(model, geom)) ? 1 : emphasis.dim : 1;
207
+ for (const mark of geometry.marks) {
208
+ const alpha = mark.alpha;
201
209
  const prev = ctx.globalAlpha;
202
210
  if (alpha !== 1) ctx.globalAlpha = alpha;
203
- drawOneBox(ctx, model, geom, layout.showOutliers, pen);
211
+ drawOneBox(ctx, mark, geometry.showOutliers, pen);
212
+ const top = Math.min(mark.yHi, mark.yLo);
204
213
  surface.evidence?.mark(
205
214
  "box",
206
- geom.left,
207
- geom.top - 1,
208
- geom.boxW,
209
- Math.max(1, geom.bottom - geom.top) + 2,
210
- geom.color,
215
+ mark.cx - mark.boxW / 2,
216
+ top - 1,
217
+ mark.boxW,
218
+ Math.max(1, Math.max(mark.yHi, mark.yLo) - top) + 2,
219
+ mark.color,
211
220
  alpha,
212
221
  plot,
213
222
  1,
214
223
  void 0,
215
224
  alpha < 1
216
225
  );
217
- if (layout.showOutliers)
218
- for (const outlier of geom.stats.outliers) {
226
+ if (geometry.showOutliers)
227
+ for (const y of mark.outliers) {
219
228
  surface.evidence?.mark(
220
229
  "point",
221
- geom.cx - 1.9,
222
- model.y.pixel(outlier) - 1.9,
230
+ mark.cx - 1.9,
231
+ y - 1.9,
223
232
  3.8,
224
233
  3.8,
225
- geom.color,
234
+ mark.color,
226
235
  alpha * 0.6,
227
236
  plot,
228
237
  1,
@@ -234,6 +243,18 @@ function drawBox(surface, model) {
234
243
  }
235
244
  ctx.restore();
236
245
  }
246
+ function drawBox(surface, model) {
247
+ surface.evidence?.begin("aggregate");
248
+ surface.evidence?.data(0, "aggregate");
249
+ const geometry = layoutBoxes(model);
250
+ model.geometry = geometry ?? void 0;
251
+ if (!geometry) return;
252
+ surface.evidence?.data(
253
+ geometry.marks.reduce((n, mark) => n + mark.count, 0),
254
+ "aggregate"
255
+ );
256
+ paintBoxes(surface, model, geometry);
257
+ }
237
258
  function buildBoxInteraction(model) {
238
259
  const spec = model.spec;
239
260
  const tt = spec.tooltip;
@@ -298,6 +319,8 @@ export {
298
319
  buildBoxInteraction,
299
320
  computeBoxes,
300
321
  computeStats,
301
- drawBox
322
+ drawBox,
323
+ layoutBoxes,
324
+ paintBoxes
302
325
  };
303
326
  //# sourceMappingURL=box.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/charts/box.ts"],
4
- "sourcesContent": ["import type { Surface } from '../render/surface';\nimport type { CartesianModel } from '../runtime/cartesian';\nimport type { BoxSpec } from '../spec/types';\nimport type { Datum } from '../types';\nimport { withAlpha } from '../color';\nimport { formatValue } from '../format';\nimport { roundedRect } from '../shape';\nimport { RoughPen } from '../rough';\nimport { accessor, toKey, toNumber } from '../util/data';\nimport { quantileSorted } from '../util/math';\nimport type { InteractionModel, TooltipRow } from '../interaction/types';\n\nexport interface BoxStats {\n min: number;\n q1: number;\n median: number;\n q3: number;\n max: number;\n outliers: number[];\n count: number;\n}\n\nexport interface BoxGeom {\n key: string;\n title: string;\n color: string;\n /** Raw x-category value backing this box (for selection identity). */\n xValue: unknown;\n /** Raw series value, or undefined for single-series box plots. */\n seriesValue: unknown;\n cx: number;\n boxW: number;\n left: number;\n right: number;\n /** Vertical hit extent (whisker top to whisker bottom in px). */\n top: number;\n bottom: number;\n stats: BoxStats;\n}\n\nexport interface BoxLayout {\n geoms: BoxGeom[];\n showOutliers: boolean;\n}\n\n/** Type-7 (linear interpolation) quantile of a pre-sorted ascending array. */\nexport function computeStats(values: number[], whisker: 'tukey' | 'minMax'): BoxStats | null {\n const sorted = values.filter((v) => Number.isFinite(v)).sort((a, b) => a - b);\n if (sorted.length === 0) return null;\n const q1 = quantileSorted(sorted, 0.25);\n const median = quantileSorted(sorted, 0.5);\n const q3 = quantileSorted(sorted, 0.75);\n const dataMin = sorted[0];\n const dataMax = sorted[sorted.length - 1];\n const outliers: number[] = [];\n let lo = dataMin;\n let hi = dataMax;\n\n if (whisker === 'tukey') {\n const iqr = q3 - q1;\n const fenceLo = q1 - 1.5 * iqr;\n const fenceHi = q3 + 1.5 * iqr;\n let wLo = Infinity;\n let wHi = -Infinity;\n for (const v of sorted) {\n if (v < fenceLo || v > fenceHi) {\n outliers.push(v);\n continue;\n }\n if (v < wLo) wLo = v;\n if (v > wHi) wHi = v;\n }\n lo = wLo === Infinity ? q1 : wLo;\n hi = wHi === -Infinity ? q3 : wHi;\n }\n\n return { min: lo, q1, median, q3, max: hi, outliers, count: sorted.length };\n}\n\n/** Resolve per-category (and per-series) box geometry without drawing. */\nexport function computeBoxes(model: CartesianModel): BoxLayout | null {\n const spec = model.spec as BoxSpec;\n if (model.x.kind !== 'band' || model.x.bandwidth <= 0 || model.series.length === 0) return null;\n\n const whisker: 'tukey' | 'minMax' = spec.whisker === 'minMax' ? 'minMax' : 'tukey';\n const showOutliers = spec.outliers !== false && whisker === 'tukey';\n const readX = accessor(model.x.field);\n const readY = accessor(model.y.field ?? '');\n const seriesCount = model.series.length;\n const bandWidth = model.x.bandwidth;\n const subWidth = bandWidth / seriesCount;\n const gap = seriesCount > 1 ? Math.min(8, subWidth * 0.18) : 0;\n const boxW = Math.max(3, Math.min(subWidth - gap, 64));\n const grouped = seriesCount > 1;\n const yPix = (v: number): number => model.y.pixel(v);\n const geoms: BoxGeom[] = [];\n\n model.series.forEach((series, seriesIndex) => {\n const groups = new Map<string, { value: unknown; vals: number[] }>();\n for (const row of series.rows) {\n const xv = readX(row);\n const y = toNumber(readY(row));\n if (!Number.isFinite(y)) continue;\n const k = toKey(xv);\n let g = groups.get(k);\n if (!g) {\n g = { value: xv, vals: [] };\n groups.set(k, g);\n }\n g.vals.push(y);\n }\n\n for (const [k, g] of groups) {\n const cxRaw = model.x.pixel(g.value);\n if (cxRaw == null) continue;\n const stats = computeStats(g.vals, whisker);\n if (!stats) continue;\n const cx = cxRaw - bandWidth / 2 + (seriesIndex + 0.5) * subWidth;\n geoms.push({\n key: grouped ? `${k}\\u0000${series.key}` : k,\n title: grouped ? `${k} \u00B7 ${series.label}` : k,\n color: series.color,\n xValue: g.value,\n seriesValue: grouped ? series.value : undefined,\n cx,\n boxW,\n left: cx - boxW / 2,\n right: cx + boxW / 2,\n top: Math.min(yPix(stats.max), yPix(stats.min)),\n bottom: Math.max(yPix(stats.max), yPix(stats.min)),\n stats,\n });\n }\n });\n\n return geoms.length ? { geoms, showOutliers } : null;\n}\n\nfunction drawBoxWhiskers(ctx: CanvasRenderingContext2D, geom: BoxGeom, yLo: number, yHi: number, top: number, bottom: number, capHalf: number): void {\n ctx.beginPath();\n ctx.moveTo(geom.cx, yHi);\n ctx.lineTo(geom.cx, top);\n ctx.moveTo(geom.cx, bottom);\n ctx.lineTo(geom.cx, yLo);\n ctx.moveTo(geom.cx - capHalf, yHi);\n ctx.lineTo(geom.cx + capHalf, yHi);\n ctx.moveTo(geom.cx - capHalf, yLo);\n ctx.lineTo(geom.cx + capHalf, yLo);\n ctx.stroke();\n}\n\nfunction drawBoxBody(ctx: CanvasRenderingContext2D, geom: BoxGeom, top: number, height: number, yMed: number): void {\n ctx.beginPath();\n roundedRect(ctx, geom.left, top, geom.boxW, height, Math.min(3, geom.boxW / 4));\n ctx.fillStyle = withAlpha(geom.color, 0.16);\n ctx.fill();\n ctx.stroke();\n\n ctx.beginPath();\n ctx.moveTo(geom.left, yMed);\n ctx.lineTo(geom.right, yMed);\n ctx.lineWidth = 2;\n ctx.stroke();\n}\n\nfunction drawBoxOutliers(ctx: CanvasRenderingContext2D, model: CartesianModel, geom: BoxGeom): void {\n ctx.fillStyle = withAlpha(geom.color, 0.6);\n for (const o of geom.stats.outliers) {\n ctx.beginPath();\n ctx.arc(geom.cx, model.y.pixel(o), 1.9, 0, Math.PI * 2);\n ctx.fill();\n }\n}\n\nfunction drawOneBoxSketch(\n pen: RoughPen,\n model: CartesianModel,\n geom: BoxGeom,\n showOutliers: boolean,\n y: { q1: number; q3: number; med: number; lo: number; hi: number; top: number; bottom: number; h: number },\n capHalf: number,\n): void {\n const { cx, left, right, boxW, stats, color } = geom;\n pen.polyline([{ x: cx, y: y.hi }, { x: cx, y: y.top }], { stroke: color });\n pen.polyline([{ x: cx, y: y.bottom }, { x: cx, y: y.lo }], { stroke: color });\n pen.polyline([{ x: cx - capHalf, y: y.hi }, { x: cx + capHalf, y: y.hi }], { stroke: color });\n pen.polyline([{ x: cx - capHalf, y: y.lo }, { x: cx + capHalf, y: y.lo }], { stroke: color });\n pen.rect(left, y.top, boxW, y.h, {\n stroke: color,\n fill: color,\n fillStyle: 'solid',\n fillAlpha: 0.16,\n });\n pen.polyline([{ x: left, y: y.med }, { x: right, y: y.med }], { stroke: color, strokeWidth: 2 });\n if (showOutliers && stats.outliers.length) {\n for (const o of stats.outliers) {\n pen.circle(cx, model.y.pixel(o), 1.9, { fill: withAlpha(color, 0.6) });\n }\n }\n}\n\nfunction drawOneBox(\n ctx: CanvasRenderingContext2D,\n model: CartesianModel,\n geom: BoxGeom,\n showOutliers: boolean,\n pen: RoughPen | null,\n): void {\n const yPix = (v: number): number => model.y.pixel(v);\n const { boxW, stats, color } = geom;\n const capHalf = boxW * 0.28;\n const yQ1 = yPix(stats.q1);\n const yQ3 = yPix(stats.q3);\n const yMed = yPix(stats.median);\n const yLo = yPix(stats.min);\n const yHi = yPix(stats.max);\n const top = Math.min(yQ1, yQ3);\n const bottom = Math.max(yQ1, yQ3);\n const h = Math.max(1, bottom - top);\n const y = { q1: yQ1, q3: yQ3, med: yMed, lo: yLo, hi: yHi, top, bottom, h };\n\n if (pen) {\n drawOneBoxSketch(pen, model, geom, showOutliers, y, capHalf);\n return;\n }\n\n ctx.save();\n ctx.strokeStyle = color;\n ctx.lineWidth = 1.5;\n ctx.lineCap = 'round';\n\n drawBoxWhiskers(ctx, geom, yLo, yHi, top, bottom, capHalf);\n drawBoxBody(ctx, geom, top, h, yMed);\n\n if (showOutliers && stats.outliers.length) {\n drawBoxOutliers(ctx, model, geom);\n }\n\n ctx.restore();\n}\n\n/** Build the synthetic row a box represents, for emphasis/selection matching. */\nfunction boxProbe(model: CartesianModel, geom: BoxGeom): Datum {\n const probe: Datum = { [model.x.field]: geom.xValue };\n if (model.seriesField) probe[model.seriesField] = geom.seriesValue;\n return probe;\n}\n\nfunction hitsBoxGeom(\n model: CartesianModel,\n geom: BoxGeom,\n showOutliers: boolean,\n px: number,\n py: number,\n): boolean {\n const inWhiskerExtent =\n px >= geom.left - 4 && px <= geom.right + 4 && py >= geom.top - 6 && py <= geom.bottom + 6;\n if (inWhiskerExtent) return true;\n if (!showOutliers || geom.stats.outliers.length === 0) return false;\n return geom.stats.outliers.some(\n (o) => Math.abs(px - geom.cx) <= 6 && Math.abs(py - model.y.pixel(o)) <= 6,\n );\n}\n\nexport function drawBox(surface: Surface, model: CartesianModel): void {\n surface.evidence?.begin('aggregate');\n surface.evidence?.data(0, 'aggregate');\n const layout = computeBoxes(model);\n if (!layout) return;\n const ctx = surface.marks.ctx;\n const { plot } = model;\n const emphasis = model.emphasis ?? null;\n const pen = model.sketch ? new RoughPen(ctx, model.sketch) : null;\n surface.evidence?.data(\n layout.geoms.reduce((n, g) => n + g.stats.count, 0),\n 'aggregate',\n );\n\n ctx.save();\n ctx.beginPath();\n ctx.rect(plot.x, plot.y - 2, plot.width, plot.height + 4);\n ctx.clip();\n for (const geom of layout.geoms) {\n const alpha = emphasis ? (emphasis.match(boxProbe(model, geom)) ? 1 : emphasis.dim) : 1;\n const prev = ctx.globalAlpha;\n if (alpha !== 1) ctx.globalAlpha = alpha;\n drawOneBox(ctx, model, geom, layout.showOutliers, pen);\n surface.evidence?.mark(\n 'box',\n geom.left,\n geom.top - 1,\n geom.boxW,\n Math.max(1, geom.bottom - geom.top) + 2,\n geom.color,\n alpha,\n plot,\n 1,\n undefined,\n alpha < 1,\n );\n if (layout.showOutliers)\n for (const outlier of geom.stats.outliers) {\n surface.evidence?.mark(\n 'point',\n geom.cx - 1.9,\n model.y.pixel(outlier) - 1.9,\n 3.8,\n 3.8,\n geom.color,\n alpha * 0.6,\n plot,\n 1,\n undefined,\n alpha < 1,\n );\n }\n if (alpha !== 1) ctx.globalAlpha = prev;\n }\n ctx.restore();\n}\n\n/** Box-plot interaction (the runtime uses this instead of the generic cartesian one). */\nexport function buildBoxInteraction(model: CartesianModel): InteractionModel | void {\n const spec = model.spec as BoxSpec;\n const tt = spec.tooltip;\n if (tt === false || (tt && typeof tt === 'object' && tt.show === false)) return;\n const layout = computeBoxes(model);\n if (!layout) return;\n const { geoms, showOutliers } = layout;\n const fmt = (v: number): string => formatValue(v, spec.encoding.y.format);\n\n return {\n region: model.plot,\n hitTest: (px, py) => {\n const hit = geoms.find((g) => hitsBoxGeom(model, g, showOutliers, px, py));\n if (!hit) return null;\n const s = hit.stats;\n const rows: TooltipRow[] = [\n { label: 'Max', value: fmt(s.max) },\n { swatch: hit.color, label: 'Q3', value: fmt(s.q3) },\n { label: 'Median', value: fmt(s.median) },\n { swatch: hit.color, label: 'Q1', value: fmt(s.q1) },\n { label: 'Min', value: fmt(s.min) },\n { label: 'n', value: String(s.count), muted: true },\n ];\n if (showOutliers && s.outliers.length) {\n rows.push({ label: 'Outliers', value: String(s.outliers.length), muted: true });\n }\n return {\n key: hit.key,\n anchorX: hit.cx,\n anchorY: hit.top,\n content: { title: hit.title, rows },\n draw: (ictx) => {\n const top = Math.min(model.y.pixel(hit.stats.q1), model.y.pixel(hit.stats.q3));\n const h = Math.max(\n 1,\n Math.abs(model.y.pixel(hit.stats.q1) - model.y.pixel(hit.stats.q3)),\n );\n ictx.save();\n ictx.strokeStyle = hit.color;\n ictx.lineWidth = 2;\n ictx.beginPath();\n roundedRect(ictx, hit.left, top, hit.boxW, h, Math.min(3, hit.boxW / 4));\n ictx.stroke();\n ictx.restore();\n },\n };\n },\n pick: (px, py) => {\n const hit = geoms.find((g) => hitsBoxGeom(model, g, showOutliers, px, py));\n if (!hit) return null;\n if (model.series.length > 1 && model.seriesField && hit.seriesValue !== undefined) {\n return {\n kind: 'point',\n fields: [model.x.field, model.seriesField],\n tuples: [[hit.xValue, hit.seriesValue]],\n };\n }\n return { kind: 'point', fields: [model.x.field], tuples: [[hit.xValue]] };\n },\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Surface } from '../render/surface';\nimport type { CartesianModel } from '../runtime/cartesian';\nimport type { BoxSpec } from '../spec/types';\nimport type { Datum } from '../types';\nimport { withAlpha } from '../color';\nimport { formatValue } from '../format';\nimport { roundedRect } from '../shape';\nimport { RoughPen } from '../rough';\nimport { accessor, toKey, toNumber } from '../util/data';\nimport { quantileSorted } from '../util/math';\nimport type { InteractionModel, TooltipRow } from '../interaction/types';\n\nexport interface BoxStats {\n min: number;\n q1: number;\n median: number;\n q3: number;\n max: number;\n outliers: number[];\n count: number;\n}\n\nexport interface BoxGeom {\n key: string;\n title: string;\n color: string;\n /** Raw x-category value backing this box (for selection identity). */\n xValue: unknown;\n /** Raw series value, or undefined for single-series box plots. */\n seriesValue: unknown;\n cx: number;\n boxW: number;\n left: number;\n right: number;\n /** Vertical hit extent (whisker top to whisker bottom in px). */\n top: number;\n bottom: number;\n stats: BoxStats;\n}\n\nexport interface BoxLayout {\n geoms: BoxGeom[];\n showOutliers: boolean;\n}\n\n/** One box as drawn: pixel-space whiskers, quartiles and outliers. */\nexport interface BoxMark {\n key: string;\n /** Category key (x) and series key, for hover focus subsets. */\n category: string;\n seriesKey?: string;\n color: string;\n cx: number;\n boxW: number;\n yQ1: number;\n yQ3: number;\n yMed: number;\n yLo: number;\n yHi: number;\n /** Outlier centers (px). */\n outliers: number[];\n /** Opacity: the highlight's dim, times any morph fade. */\n alpha: number;\n /** Observations summarized (render evidence). */\n count: number;\n}\n\n/** A box plot's resolved marks \u2014 what {@link paintBoxes} draws and update morphs tween. */\nexport interface BoxGeometry {\n kind: 'box';\n marks: BoxMark[];\n showOutliers: boolean;\n}\n\n/** Type-7 (linear interpolation) quantile of a pre-sorted ascending array. */\nexport function computeStats(values: number[], whisker: 'tukey' | 'minMax'): BoxStats | null {\n const sorted = values.filter((v) => Number.isFinite(v)).sort((a, b) => a - b);\n if (sorted.length === 0) return null;\n const q1 = quantileSorted(sorted, 0.25);\n const median = quantileSorted(sorted, 0.5);\n const q3 = quantileSorted(sorted, 0.75);\n const dataMin = sorted[0];\n const dataMax = sorted[sorted.length - 1];\n const outliers: number[] = [];\n let lo = dataMin;\n let hi = dataMax;\n\n if (whisker === 'tukey') {\n const iqr = q3 - q1;\n const fenceLo = q1 - 1.5 * iqr;\n const fenceHi = q3 + 1.5 * iqr;\n let wLo = Infinity;\n let wHi = -Infinity;\n for (const v of sorted) {\n if (v < fenceLo || v > fenceHi) {\n outliers.push(v);\n continue;\n }\n if (v < wLo) wLo = v;\n if (v > wHi) wHi = v;\n }\n lo = wLo === Infinity ? q1 : wLo;\n hi = wHi === -Infinity ? q3 : wHi;\n }\n\n return { min: lo, q1, median, q3, max: hi, outliers, count: sorted.length };\n}\n\n/** Resolve per-category (and per-series) box geometry without drawing. */\nexport function computeBoxes(model: CartesianModel): BoxLayout | null {\n const spec = model.spec as BoxSpec;\n if (model.x.kind !== 'band' || model.x.bandwidth <= 0 || model.series.length === 0) return null;\n\n const whisker: 'tukey' | 'minMax' = spec.whisker === 'minMax' ? 'minMax' : 'tukey';\n const showOutliers = spec.outliers !== false && whisker === 'tukey';\n const readX = accessor(model.x.field);\n const readY = accessor(model.y.field ?? '');\n const seriesCount = model.series.length;\n const bandWidth = model.x.bandwidth;\n const subWidth = bandWidth / seriesCount;\n const gap = seriesCount > 1 ? Math.min(8, subWidth * 0.18) : 0;\n const boxW = Math.max(3, Math.min(subWidth - gap, 64));\n const grouped = seriesCount > 1;\n const yPix = (v: number): number => model.y.pixel(v);\n const geoms: BoxGeom[] = [];\n\n model.series.forEach((series, seriesIndex) => {\n const groups = new Map<string, { value: unknown; vals: number[] }>();\n for (const row of series.rows) {\n const xv = readX(row);\n const y = toNumber(readY(row));\n if (!Number.isFinite(y)) continue;\n const k = toKey(xv);\n let g = groups.get(k);\n if (!g) {\n g = { value: xv, vals: [] };\n groups.set(k, g);\n }\n g.vals.push(y);\n }\n\n for (const [k, g] of groups) {\n const cxRaw = model.x.pixel(g.value);\n if (cxRaw == null) continue;\n const stats = computeStats(g.vals, whisker);\n if (!stats) continue;\n const cx = cxRaw - bandWidth / 2 + (seriesIndex + 0.5) * subWidth;\n geoms.push({\n key: grouped ? `${k}\\u0000${series.key}` : k,\n title: grouped ? `${k} \u00B7 ${series.label}` : k,\n color: series.color,\n xValue: g.value,\n seriesValue: grouped ? series.value : undefined,\n cx,\n boxW,\n left: cx - boxW / 2,\n right: cx + boxW / 2,\n top: Math.min(yPix(stats.max), yPix(stats.min)),\n bottom: Math.max(yPix(stats.max), yPix(stats.min)),\n stats,\n });\n }\n });\n\n return geoms.length ? { geoms, showOutliers } : null;\n}\n\nfunction drawBoxWhiskers(ctx: CanvasRenderingContext2D, mark: BoxMark, top: number, bottom: number, capHalf: number): void {\n ctx.beginPath();\n ctx.moveTo(mark.cx, mark.yHi);\n ctx.lineTo(mark.cx, top);\n ctx.moveTo(mark.cx, bottom);\n ctx.lineTo(mark.cx, mark.yLo);\n ctx.moveTo(mark.cx - capHalf, mark.yHi);\n ctx.lineTo(mark.cx + capHalf, mark.yHi);\n ctx.moveTo(mark.cx - capHalf, mark.yLo);\n ctx.lineTo(mark.cx + capHalf, mark.yLo);\n ctx.stroke();\n}\n\nfunction drawBoxBody(ctx: CanvasRenderingContext2D, mark: BoxMark, top: number, height: number): void {\n const left = mark.cx - mark.boxW / 2;\n ctx.beginPath();\n roundedRect(ctx, left, top, mark.boxW, height, Math.min(3, mark.boxW / 4));\n ctx.fillStyle = withAlpha(mark.color, 0.16);\n ctx.fill();\n ctx.stroke();\n\n ctx.beginPath();\n ctx.moveTo(left, mark.yMed);\n ctx.lineTo(mark.cx + mark.boxW / 2, mark.yMed);\n ctx.lineWidth = 2;\n ctx.stroke();\n}\n\nfunction drawBoxOutliers(ctx: CanvasRenderingContext2D, mark: BoxMark): void {\n ctx.fillStyle = withAlpha(mark.color, 0.6);\n for (const y of mark.outliers) {\n ctx.beginPath();\n ctx.arc(mark.cx, y, 1.9, 0, Math.PI * 2);\n ctx.fill();\n }\n}\n\nfunction drawOneBoxSketch(pen: RoughPen, mark: BoxMark, showOutliers: boolean, top: number, bottom: number, h: number, capHalf: number): void {\n const { cx, boxW, color } = mark;\n const left = cx - boxW / 2;\n pen.polyline([{ x: cx, y: mark.yHi }, { x: cx, y: top }], { stroke: color });\n pen.polyline([{ x: cx, y: bottom }, { x: cx, y: mark.yLo }], { stroke: color });\n pen.polyline([{ x: cx - capHalf, y: mark.yHi }, { x: cx + capHalf, y: mark.yHi }], { stroke: color });\n pen.polyline([{ x: cx - capHalf, y: mark.yLo }, { x: cx + capHalf, y: mark.yLo }], { stroke: color });\n pen.rect(left, top, boxW, h, {\n stroke: color,\n fill: color,\n fillStyle: 'solid',\n fillAlpha: 0.16,\n });\n pen.polyline([{ x: left, y: mark.yMed }, { x: cx + boxW / 2, y: mark.yMed }], { stroke: color, strokeWidth: 2 });\n if (showOutliers && mark.outliers.length) {\n for (const y of mark.outliers) {\n pen.circle(cx, y, 1.9, { fill: withAlpha(color, 0.6) });\n }\n }\n}\n\nfunction drawOneBox(ctx: CanvasRenderingContext2D, mark: BoxMark, showOutliers: boolean, pen: RoughPen | null): void {\n const capHalf = mark.boxW * 0.28;\n const top = Math.min(mark.yQ1, mark.yQ3);\n const bottom = Math.max(mark.yQ1, mark.yQ3);\n const h = Math.max(1, bottom - top);\n\n if (pen) {\n drawOneBoxSketch(pen, mark, showOutliers, top, bottom, h, capHalf);\n return;\n }\n\n ctx.save();\n ctx.strokeStyle = mark.color;\n ctx.lineWidth = 1.5;\n ctx.lineCap = 'round';\n\n drawBoxWhiskers(ctx, mark, top, bottom, capHalf);\n drawBoxBody(ctx, mark, top, h);\n\n if (showOutliers && mark.outliers.length) {\n drawBoxOutliers(ctx, mark);\n }\n\n ctx.restore();\n}\n\n/** Build the synthetic row a box represents, for emphasis/selection matching. */\nfunction boxProbe(model: CartesianModel, geom: BoxGeom): Datum {\n const probe: Datum = { [model.x.field]: geom.xValue };\n if (model.seriesField) probe[model.seriesField] = geom.seriesValue;\n return probe;\n}\n\nfunction hitsBoxGeom(\n model: CartesianModel,\n geom: BoxGeom,\n showOutliers: boolean,\n px: number,\n py: number,\n): boolean {\n const inWhiskerExtent =\n px >= geom.left - 4 && px <= geom.right + 4 && py >= geom.top - 6 && py <= geom.bottom + 6;\n if (inWhiskerExtent) return true;\n if (!showOutliers || geom.stats.outliers.length === 0) return false;\n return geom.stats.outliers.some(\n (o) => Math.abs(px - geom.cx) <= 6 && Math.abs(py - model.y.pixel(o)) <= 6,\n );\n}\n\n/** Resolve the boxes' pixel geometry (including highlight dimming) without drawing. */\nexport function layoutBoxes(model: CartesianModel): BoxGeometry | null {\n const layout = computeBoxes(model);\n if (!layout) return null;\n const emphasis = model.emphasis ?? null;\n const y = (v: number): number => model.y.pixel(v);\n const marks = layout.geoms.map((geom): BoxMark => ({\n key: geom.key,\n category: toKey(geom.xValue),\n seriesKey: geom.seriesValue === undefined ? undefined : toKey(geom.seriesValue),\n color: geom.color,\n cx: geom.cx,\n boxW: geom.boxW,\n yQ1: y(geom.stats.q1),\n yQ3: y(geom.stats.q3),\n yMed: y(geom.stats.median),\n yLo: y(geom.stats.min),\n yHi: y(geom.stats.max),\n outliers: geom.stats.outliers.map(y),\n alpha: emphasis ? (emphasis.match(boxProbe(model, geom)) ? 1 : emphasis.dim) : 1,\n count: geom.stats.count,\n }));\n return { kind: 'box', marks, showOutliers: layout.showOutliers };\n}\n\n/** Paint box geometry (clipped to the plot), recording evidence for each box and outlier. */\nexport function paintBoxes(surface: Surface, model: CartesianModel, geometry: BoxGeometry): void {\n const ctx = surface.marks.ctx;\n const { plot } = model;\n const pen = model.sketch ? new RoughPen(ctx, model.sketch) : null;\n ctx.save();\n ctx.beginPath();\n ctx.rect(plot.x, plot.y - 2, plot.width, plot.height + 4);\n ctx.clip();\n for (const mark of geometry.marks) {\n const alpha = mark.alpha;\n const prev = ctx.globalAlpha;\n if (alpha !== 1) ctx.globalAlpha = alpha;\n drawOneBox(ctx, mark, geometry.showOutliers, pen);\n const top = Math.min(mark.yHi, mark.yLo);\n surface.evidence?.mark(\n 'box',\n mark.cx - mark.boxW / 2,\n top - 1,\n mark.boxW,\n Math.max(1, Math.max(mark.yHi, mark.yLo) - top) + 2,\n mark.color,\n alpha,\n plot,\n 1,\n undefined,\n alpha < 1,\n );\n if (geometry.showOutliers)\n for (const y of mark.outliers) {\n surface.evidence?.mark(\n 'point',\n mark.cx - 1.9,\n y - 1.9,\n 3.8,\n 3.8,\n mark.color,\n alpha * 0.6,\n plot,\n 1,\n undefined,\n alpha < 1,\n );\n }\n if (alpha !== 1) ctx.globalAlpha = prev;\n }\n ctx.restore();\n}\n\nexport function drawBox(surface: Surface, model: CartesianModel): void {\n surface.evidence?.begin('aggregate');\n surface.evidence?.data(0, 'aggregate');\n const geometry = layoutBoxes(model);\n model.geometry = geometry ?? undefined;\n if (!geometry) return;\n surface.evidence?.data(\n geometry.marks.reduce((n, mark) => n + mark.count, 0),\n 'aggregate',\n );\n paintBoxes(surface, model, geometry);\n}\n\n/** Box-plot interaction (the runtime uses this instead of the generic cartesian one). */\nexport function buildBoxInteraction(model: CartesianModel): InteractionModel | void {\n const spec = model.spec as BoxSpec;\n const tt = spec.tooltip;\n if (tt === false || (tt && typeof tt === 'object' && tt.show === false)) return;\n const layout = computeBoxes(model);\n if (!layout) return;\n const { geoms, showOutliers } = layout;\n const fmt = (v: number): string => formatValue(v, spec.encoding.y.format);\n\n return {\n region: model.plot,\n hitTest: (px, py) => {\n const hit = geoms.find((g) => hitsBoxGeom(model, g, showOutliers, px, py));\n if (!hit) return null;\n const s = hit.stats;\n const rows: TooltipRow[] = [\n { label: 'Max', value: fmt(s.max) },\n { swatch: hit.color, label: 'Q3', value: fmt(s.q3) },\n { label: 'Median', value: fmt(s.median) },\n { swatch: hit.color, label: 'Q1', value: fmt(s.q1) },\n { label: 'Min', value: fmt(s.min) },\n { label: 'n', value: String(s.count), muted: true },\n ];\n if (showOutliers && s.outliers.length) {\n rows.push({ label: 'Outliers', value: String(s.outliers.length), muted: true });\n }\n return {\n key: hit.key,\n anchorX: hit.cx,\n anchorY: hit.top,\n content: { title: hit.title, rows },\n draw: (ictx) => {\n const top = Math.min(model.y.pixel(hit.stats.q1), model.y.pixel(hit.stats.q3));\n const h = Math.max(\n 1,\n Math.abs(model.y.pixel(hit.stats.q1) - model.y.pixel(hit.stats.q3)),\n );\n ictx.save();\n ictx.strokeStyle = hit.color;\n ictx.lineWidth = 2;\n ictx.beginPath();\n roundedRect(ictx, hit.left, top, hit.boxW, h, Math.min(3, hit.boxW / 4));\n ictx.stroke();\n ictx.restore();\n },\n };\n },\n pick: (px, py) => {\n const hit = geoms.find((g) => hitsBoxGeom(model, g, showOutliers, px, py));\n if (!hit) return null;\n if (model.series.length > 1 && model.seriesField && hit.seriesValue !== undefined) {\n return {\n kind: 'point',\n fields: [model.x.field, model.seriesField],\n tuples: [[hit.xValue, hit.seriesValue]],\n };\n }\n return { kind: 'point', fields: [model.x.field], tuples: [[hit.xValue]] };\n },\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Bubble map — one circle per row at its longitude/latitude, its area ∝ `size`,
3
+ * colored by an optional numeric (sequential ramp) or categorical (palette)
4
+ * field, over an optional GeoJSON basemap.
5
+ *
6
+ * With a basemap the projection is fitted to it, so the map stays put as data
7
+ * changes; without one it is fitted to the bubbles. Rows that can't be placed
8
+ * (non-finite or out-of-range coordinates, non-finite sizes, or — over a
9
+ * basemap — positions outside the map) are counted as omitted, never guessed.
10
+ * Negative sizes can't be drawn as area, so their location is marked by a
11
+ * hollow ring instead of a sized disc.
12
+ */
13
+ import type { Surface } from '../render/surface.js';
14
+ import type { ChartSpec } from '../spec/types.js';
15
+ import type { ThemeTokens } from '../theme/index.js';
16
+ import type { Size } from '../types.js';
17
+ import type { InteractionModel } from '../interaction/types.js';
18
+ import type { RenderContext } from './index.js';
19
+ export declare function drawBubbleMap(surface: Surface, spec: ChartSpec, tokens: ThemeTokens, size: Size, context?: RenderContext): InteractionModel | void;
20
+ //# sourceMappingURL=bubbleMap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bubbleMap.d.ts","sourceRoot":"","sources":["../../src/charts/bubbleMap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAMjD,OAAO,KAAK,EAAiB,SAAS,EAAuC,MAAM,eAAe,CAAC;AACnG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAqB,IAAI,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAA8B,MAAM,sBAAsB,CAAC;AAUzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AA27B7C,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE,aAAa,GACtB,gBAAgB,GAAG,IAAI,CA6JzB"}