@fundar/data-chart-telling 1.17.0 → 1.19.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 (353) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +2 -1
  3. package/dist/configuration/config.svelte.js +4 -3
  4. package/dist/index.d.ts +10 -3
  5. package/dist/index.js +4 -1
  6. package/dist/layout/coordinates/CoordinatesLayout.svelte +3 -1
  7. package/dist/layout/geometry/GeometryLayout.svelte +222 -53
  8. package/dist/layout/geometry/ScaleFreeContext.d.ts +31 -0
  9. package/dist/layout/geometry/ScaleFreeContext.js +65 -0
  10. package/dist/layout/geometry/ScaleFreeMarks.svelte +14 -0
  11. package/dist/layout/geometry/ScaleFreeMarks.svelte.d.ts +7 -0
  12. package/dist/layout/geometry/ScaleGate.svelte.d.ts +8 -0
  13. package/dist/layout/geometry/ScaleGate.svelte.js +95 -0
  14. package/dist/layout/geometry/ScaleGateMarks.svelte +15 -0
  15. package/dist/layout/geometry/ScaleGateMarks.svelte.d.ts +7 -0
  16. package/dist/layout/hover/HoverDefaults.d.ts +52 -0
  17. package/dist/layout/hover/HoverDefaults.js +96 -0
  18. package/dist/layout/hover/HoverLayers.d.ts +35 -0
  19. package/dist/layout/hover/HoverLayers.js +122 -0
  20. package/dist/layout/hover/HoverSettings.d.ts +1 -3
  21. package/dist/layout/hover/HoverSettings.js +3 -2
  22. package/dist/layout/hover/HoverShapes.d.ts +56 -0
  23. package/dist/layout/hover/HoverShapes.js +163 -0
  24. package/dist/layout/hover/PlotHover.svelte.d.ts +18 -0
  25. package/dist/layout/hover/PlotHover.svelte.js +54 -1
  26. package/dist/layout/legend/LegendState.svelte.d.ts +2 -0
  27. package/dist/layout/legend/LegendState.svelte.js +5 -0
  28. package/dist/layout/margins/Box.d.ts +4 -0
  29. package/dist/layout/margins/Box.js +14 -0
  30. package/dist/layout/margins/PlotMargins.svelte.js +26 -1
  31. package/dist/layout/plot/{Plot.svelte.d.ts → AbstractPlot.svelte.d.ts} +3 -3
  32. package/dist/layout/plot/Core.svelte +2 -2
  33. package/dist/layout/plot/PublicPlotContext.d.ts +6 -0
  34. package/dist/layout/plot/PublicPlotContext.js +8 -0
  35. package/dist/layout/styles/ValueLabels.d.ts +118 -59
  36. package/dist/layout/styles/ValueLabels.js +313 -146
  37. package/dist/layout/tooltip/TooltipState.svelte.d.ts +8 -9
  38. package/dist/layout/tooltip/TooltipState.svelte.js +28 -29
  39. package/dist/markers/MarkerKinds.d.ts +84 -1
  40. package/dist/markers/MarkerKinds.js +150 -23
  41. package/dist/markers/area/AreaMarker.svelte +1 -1
  42. package/dist/markers/band/BandMarker.svelte +74 -0
  43. package/dist/markers/band/BandMarker.svelte.d.ts +7 -0
  44. package/dist/markers/band/Bands.d.ts +16 -0
  45. package/dist/markers/band/Bands.js +48 -0
  46. package/dist/markers/bar/BarMarker.svelte +29 -70
  47. package/dist/markers/bollinger/BollingerMarker.svelte +1 -1
  48. package/dist/markers/box/BoxMarker.svelte +1 -1
  49. package/dist/markers/dot/DotRadius.d.ts +11 -0
  50. package/dist/markers/dot/DotRadius.js +21 -0
  51. package/dist/markers/hover/HoverMarker.svelte +7 -265
  52. package/dist/markers/hover/HoverMarker.svelte.d.ts +4 -27
  53. package/dist/markers/labels/CurveLabel.svelte +56 -0
  54. package/dist/markers/labels/CurveLabel.svelte.d.ts +9 -0
  55. package/dist/markers/labels/LabelMerge.d.ts +11 -0
  56. package/dist/markers/labels/LabelMerge.js +87 -0
  57. package/dist/markers/labels/MarkerLabel.svelte +36 -0
  58. package/dist/markers/labels/MarkerLabel.svelte.d.ts +10 -0
  59. package/dist/markers/labels/MarkerLabels.d.ts +52 -0
  60. package/dist/markers/labels/MarkerLabels.js +97 -0
  61. package/dist/markers/labels/geometry/BoxGeometry.d.ts +8 -0
  62. package/dist/markers/labels/geometry/BoxGeometry.js +101 -0
  63. package/dist/markers/labels/geometry/CurveGeometry.d.ts +34 -0
  64. package/dist/markers/labels/geometry/CurveGeometry.js +193 -0
  65. package/dist/markers/labels/geometry/PointGeometry.d.ts +9 -0
  66. package/dist/markers/labels/geometry/PointGeometry.js +22 -0
  67. package/dist/markers/labels/layouts/BoxLayout.d.ts +10 -0
  68. package/dist/markers/labels/layouts/BoxLayout.js +49 -0
  69. package/dist/markers/labels/layouts/PathLayout.d.ts +11 -0
  70. package/dist/markers/labels/layouts/PathLayout.js +91 -0
  71. package/dist/markers/labels/layouts/PointLayout.d.ts +19 -0
  72. package/dist/markers/labels/layouts/PointLayout.js +94 -0
  73. package/dist/markers/regression/RegressionMarker.svelte +1 -1
  74. package/dist/markers/text/Covering.d.ts +13 -0
  75. package/dist/markers/text/Covering.js +29 -0
  76. package/dist/markers/text/Declutter.d.ts +24 -3
  77. package/dist/markers/text/Declutter.js +46 -3
  78. package/dist/markers/text/TextMarker.svelte +90 -17
  79. package/dist/markers/text/TextMarker.svelte.d.ts +1 -1
  80. package/dist/markers/tick/TickMarker.svelte +1 -1
  81. package/dist/markers/utils/MarkerChannels.d.ts +1 -1
  82. package/dist/markers/utils/MarkerChannels.js +3 -2
  83. package/dist/markers/utils/PointPixel.d.ts +37 -0
  84. package/dist/markers/utils/PointPixel.js +44 -0
  85. package/dist/markers/violin/ViolinMarker.svelte +1 -1
  86. package/dist/markers/waffle/WaffleMarker.svelte +1 -1
  87. package/dist/phases/Pipeline.d.ts +7 -7
  88. package/dist/phases/Pipeline.js +12 -9
  89. package/dist/phases/context/ContextPhase.d.ts +22 -0
  90. package/dist/phases/context/ContextPhase.js +23 -0
  91. package/dist/phases/context/RowContext.d.ts +37 -0
  92. package/dist/phases/context/RowContext.js +97 -0
  93. package/dist/phases/data/DataPhase.d.ts +4 -4
  94. package/dist/phases/data/DataPhase.js +7 -7
  95. package/dist/phases/hover/HoverPhase.d.ts +6 -7
  96. package/dist/phases/hover/HoverPhase.js +28 -23
  97. package/dist/phases/mapping/MappingPhase.d.ts +4 -4
  98. package/dist/phases/mapping/MappingPhase.js +2 -2
  99. package/dist/phases/markers/MarkerStyles.d.ts +8 -0
  100. package/dist/phases/markers/MarkerStyles.js +24 -6
  101. package/dist/phases/markers/MarkersPhase.d.ts +6 -7
  102. package/dist/phases/markers/MarkersPhase.js +18 -12
  103. package/dist/phases/scales/ScalesPhase.d.ts +4 -4
  104. package/dist/phases/scales/ScalesPhase.js +4 -4
  105. package/dist/phases/sharedScales/SharedScalesPhase.d.ts +2 -2
  106. package/dist/phases/sharedScales/SharedScalesPhase.js +2 -2
  107. package/dist/phases/statistics/MarkerGrouping.d.ts +0 -9
  108. package/dist/phases/statistics/MarkerGrouping.js +5 -48
  109. package/dist/phases/statistics/MarkerInheritance.d.ts +11 -0
  110. package/dist/phases/statistics/MarkerInheritance.js +25 -0
  111. package/dist/phases/statistics/MarkerOrientation.d.ts +26 -0
  112. package/dist/phases/statistics/MarkerOrientation.js +29 -0
  113. package/dist/phases/statistics/StatisticsPhase.js +15 -15
  114. package/dist/phases/styles/StylesPhase.d.ts +3 -3
  115. package/dist/phases/styles/StylesPhase.js +2 -2
  116. package/dist/phases/tooltip/TooltipPhase.d.ts +4 -4
  117. package/dist/phases/tooltip/TooltipPhase.js +10 -7
  118. package/dist/phases/transforms/TransformsPhase.d.ts +3 -3
  119. package/dist/phases/transforms/TransformsPhase.js +7 -5
  120. package/dist/plots/correlation/heatmap/Plot.svelte +2 -2
  121. package/dist/plots/correlation/heatmap/Plot.svelte.d.ts +0 -1
  122. package/dist/plots/correlation/heatmap/defaults.d.ts +2 -2
  123. package/dist/plots/correlation/heatmap/defaults.js +35 -7
  124. package/dist/plots/correlation/heatmap/markers.d.ts +2 -8
  125. package/dist/plots/correlation/heatmap/markers.js +8 -11
  126. package/dist/plots/correlation/scatter/Plot.svelte +2 -2
  127. package/dist/plots/correlation/scatter/Plot.svelte.d.ts +0 -1
  128. package/dist/plots/correlation/scatter/defaults.d.ts +2 -2
  129. package/dist/plots/correlation/scatter/defaults.js +18 -6
  130. package/dist/plots/correlation/scatter/markers.d.ts +2 -11
  131. package/dist/plots/correlation/scatter/markers.js +24 -30
  132. package/dist/plots/distribution/box/BoxSummaries.d.ts +22 -8
  133. package/dist/plots/distribution/box/BoxSummaries.js +99 -40
  134. package/dist/plots/distribution/box/Plot.svelte +2 -2
  135. package/dist/plots/distribution/box/Plot.svelte.d.ts +0 -1
  136. package/dist/plots/distribution/box/defaults.d.ts +2 -2
  137. package/dist/plots/distribution/box/defaults.js +20 -6
  138. package/dist/plots/distribution/box/markers.d.ts +2 -2
  139. package/dist/plots/distribution/box/markers.js +13 -4
  140. package/dist/plots/distribution/density/Plot.svelte +2 -2
  141. package/dist/plots/distribution/density/Plot.svelte.d.ts +0 -1
  142. package/dist/plots/distribution/density/defaults.d.ts +2 -2
  143. package/dist/plots/distribution/density/defaults.js +33 -1
  144. package/dist/plots/distribution/density/markers.d.ts +2 -2
  145. package/dist/plots/distribution/density/markers.js +9 -5
  146. package/dist/plots/distribution/histogram/Plot.svelte +2 -2
  147. package/dist/plots/distribution/histogram/Plot.svelte.d.ts +0 -1
  148. package/dist/plots/distribution/histogram/defaults.d.ts +2 -2
  149. package/dist/plots/distribution/histogram/defaults.js +36 -36
  150. package/dist/plots/distribution/histogram/markers.d.ts +2 -2
  151. package/dist/plots/distribution/histogram/markers.js +7 -6
  152. package/dist/plots/distribution/pyramid/Plot.svelte +2 -2
  153. package/dist/plots/distribution/pyramid/Plot.svelte.d.ts +0 -1
  154. package/dist/plots/distribution/pyramid/defaults.d.ts +2 -2
  155. package/dist/plots/distribution/pyramid/defaults.js +13 -3
  156. package/dist/plots/distribution/pyramid/markers.d.ts +2 -10
  157. package/dist/plots/distribution/pyramid/markers.js +9 -18
  158. package/dist/plots/distribution/violin/Plot.svelte +2 -2
  159. package/dist/plots/distribution/violin/Plot.svelte.d.ts +0 -1
  160. package/dist/plots/distribution/violin/defaults.d.ts +2 -2
  161. package/dist/plots/distribution/violin/defaults.js +20 -7
  162. package/dist/plots/distribution/violin/markers.d.ts +2 -2
  163. package/dist/plots/distribution/violin/markers.js +30 -6
  164. package/dist/plots/evolution/area/Plot.svelte +2 -2
  165. package/dist/plots/evolution/area/Plot.svelte.d.ts +0 -1
  166. package/dist/plots/evolution/area/defaults.d.ts +2 -2
  167. package/dist/plots/evolution/area/defaults.js +5 -8
  168. package/dist/plots/evolution/area/markers.d.ts +2 -2
  169. package/dist/plots/evolution/area/markers.js +7 -5
  170. package/dist/plots/evolution/line/Plot.svelte +2 -2
  171. package/dist/plots/evolution/line/Plot.svelte.d.ts +0 -1
  172. package/dist/plots/evolution/line/defaults.d.ts +2 -2
  173. package/dist/plots/evolution/line/defaults.js +5 -7
  174. package/dist/plots/evolution/line/markers.d.ts +2 -2
  175. package/dist/plots/evolution/line/markers.js +6 -4
  176. package/dist/plots/evolution/slope/Plot.svelte +2 -2
  177. package/dist/plots/evolution/slope/Plot.svelte.d.ts +0 -1
  178. package/dist/plots/evolution/slope/defaults.d.ts +2 -2
  179. package/dist/plots/evolution/slope/defaults.js +11 -6
  180. package/dist/plots/evolution/slope/markers.d.ts +6 -5
  181. package/dist/plots/evolution/slope/markers.js +19 -12
  182. package/dist/plots/evolution/sparkline/Plot.svelte +2 -2
  183. package/dist/plots/evolution/sparkline/Plot.svelte.d.ts +0 -1
  184. package/dist/plots/evolution/sparkline/defaults.d.ts +2 -2
  185. package/dist/plots/evolution/sparkline/defaults.js +5 -2
  186. package/dist/plots/evolution/sparkline/markers.d.ts +2 -2
  187. package/dist/plots/evolution/sparkline/markers.js +6 -4
  188. package/dist/plots/generic/Plot.svelte +42 -0
  189. package/dist/plots/generic/Plot.svelte.d.ts +25 -0
  190. package/dist/plots/generic/defaults.d.ts +4 -0
  191. package/dist/plots/generic/defaults.js +7 -0
  192. package/dist/plots/map/geo/Core.svelte +3 -3
  193. package/dist/plots/map/geo/Plot.svelte +2 -2
  194. package/dist/plots/map/geo/Plot.svelte.d.ts +0 -1
  195. package/dist/plots/map/geo/defaults.d.ts +2 -2
  196. package/dist/plots/map/geo/phases/data.d.ts +1 -1
  197. package/dist/plots/map/geo/phases/data.js +1 -1
  198. package/dist/plots/map/geo/phases/hover.d.ts +2 -2
  199. package/dist/plots/map/geo/phases/hover.js +3 -3
  200. package/dist/plots/map/geo/phases/markers.d.ts +2 -2
  201. package/dist/plots/map/geo/phases/markers.js +3 -3
  202. package/dist/plots/map/geo/phases/scales.d.ts +2 -2
  203. package/dist/plots/map/geo/phases/scales.js +2 -2
  204. package/dist/plots/part-of-a-whole/treemap/Plot.svelte +2 -2
  205. package/dist/plots/part-of-a-whole/treemap/Plot.svelte.d.ts +0 -1
  206. package/dist/plots/part-of-a-whole/treemap/defaults.d.ts +2 -2
  207. package/dist/plots/part-of-a-whole/treemap/defaults.js +38 -22
  208. package/dist/plots/ranking/bar/Plot.svelte +2 -2
  209. package/dist/plots/ranking/bar/Plot.svelte.d.ts +0 -1
  210. package/dist/plots/ranking/bar/defaults.d.ts +2 -2
  211. package/dist/plots/ranking/bar/defaults.js +26 -10
  212. package/dist/plots/ranking/bar/markers.d.ts +3 -3
  213. package/dist/plots/ranking/bar/markers.js +17 -33
  214. package/dist/plots/ranking/bullet/Plot.svelte +2 -2
  215. package/dist/plots/ranking/bullet/Plot.svelte.d.ts +0 -1
  216. package/dist/plots/ranking/bullet/defaults.d.ts +2 -2
  217. package/dist/plots/ranking/bullet/defaults.js +24 -4
  218. package/dist/plots/ranking/bullet/markers.d.ts +3 -3
  219. package/dist/plots/ranking/bullet/markers.js +16 -10
  220. package/dist/plots/ranking/cleveland/ClevelandMarkers.d.ts +4 -11
  221. package/dist/plots/ranking/cleveland/ClevelandMarkers.js +73 -54
  222. package/dist/plots/ranking/cleveland/Plot.svelte +2 -2
  223. package/dist/plots/ranking/cleveland/Plot.svelte.d.ts +0 -1
  224. package/dist/plots/ranking/cleveland/defaults.d.ts +2 -2
  225. package/dist/plots/ranking/cleveland/defaults.js +39 -5
  226. package/dist/plots/ranking/dumbbell/Plot.svelte +2 -2
  227. package/dist/plots/ranking/dumbbell/Plot.svelte.d.ts +0 -1
  228. package/dist/plots/ranking/dumbbell/defaults.d.ts +2 -2
  229. package/dist/plots/ranking/forest/Plot.svelte +2 -2
  230. package/dist/plots/ranking/forest/Plot.svelte.d.ts +0 -1
  231. package/dist/plots/ranking/forest/defaults.d.ts +2 -2
  232. package/dist/plots/ranking/lollipop/Plot.svelte +2 -2
  233. package/dist/plots/ranking/lollipop/Plot.svelte.d.ts +0 -1
  234. package/dist/plots/ranking/lollipop/defaults.d.ts +2 -2
  235. package/dist/types/configuration/styling.d.ts +4 -0
  236. package/dist/types/layout/context.d.ts +23 -0
  237. package/dist/types/layout/context.js +1 -0
  238. package/dist/types/layout/hover.d.ts +3 -0
  239. package/dist/types/layout/styles/bullet.d.ts +4 -1
  240. package/dist/types/layout/styles/values.d.ts +59 -13
  241. package/dist/types/layout/tooltip.d.ts +5 -10
  242. package/dist/types/markers/axis/area.d.ts +5 -1
  243. package/dist/types/markers/axis/axisBasedMarkersConfig.d.ts +2 -1
  244. package/dist/types/markers/axis/band.d.ts +24 -0
  245. package/dist/types/markers/axis/band.js +1 -0
  246. package/dist/types/markers/axis/bar.d.ts +7 -4
  247. package/dist/types/markers/axis/bollinger.d.ts +2 -1
  248. package/dist/types/markers/axis/box.d.ts +2 -1
  249. package/dist/types/markers/axis/cell.d.ts +4 -1
  250. package/dist/types/markers/axis/hover.d.ts +60 -15
  251. package/dist/types/markers/axis/line.d.ts +4 -1
  252. package/dist/types/markers/axis/rect.d.ts +4 -1
  253. package/dist/types/markers/axis/regression.d.ts +2 -1
  254. package/dist/types/markers/axis/tick.d.ts +2 -1
  255. package/dist/types/markers/axis/trail.d.ts +4 -1
  256. package/dist/types/markers/axis/violin.d.ts +2 -1
  257. package/dist/types/markers/axis/waffle.d.ts +5 -1
  258. package/dist/types/markers/basic/dot.d.ts +4 -1
  259. package/dist/types/markers/basic/text.d.ts +25 -21
  260. package/dist/types/markers/channels/commonMarkerConfig.d.ts +6 -2
  261. package/dist/types/markers/channels/commonMarkerConfigWithLabel.d.ts +5 -9
  262. package/dist/types/markers/channels/commonMarkerConfigWithOrientation.d.ts +5 -0
  263. package/dist/types/markers/channels/commonMarkerConfigWithOrientation.js +1 -0
  264. package/dist/types/markers/common.d.ts +1 -0
  265. package/dist/types/markers/common.js +1 -0
  266. package/dist/types/markers/labels/box.d.ts +57 -0
  267. package/dist/types/markers/labels/box.js +1 -0
  268. package/dist/types/markers/labels/common.d.ts +15 -0
  269. package/dist/types/markers/labels/common.js +1 -0
  270. package/dist/types/markers/labels/path.d.ts +52 -0
  271. package/dist/types/markers/labels/path.js +1 -0
  272. package/dist/types/markers/labels/point.d.ts +40 -0
  273. package/dist/types/markers/labels/point.js +1 -0
  274. package/dist/types/markers/traits.d.ts +10 -0
  275. package/dist/types/phases/context/phase.d.ts +7 -0
  276. package/dist/types/phases/context/phase.js +1 -0
  277. package/dist/types/phases/data/phase.d.ts +2 -2
  278. package/dist/types/phases/hover/phase.d.ts +10 -7
  279. package/dist/types/phases/index.d.ts +2 -1
  280. package/dist/types/phases/kind.d.ts +11 -8
  281. package/dist/types/phases/mapping/phase.d.ts +2 -2
  282. package/dist/types/phases/markers/phase.d.ts +3 -10
  283. package/dist/types/phases/scales/phase.d.ts +4 -4
  284. package/dist/types/phases/stage.d.ts +3 -3
  285. package/dist/types/phases/state.d.ts +1 -1
  286. package/dist/types/phases/statistics/phase.d.ts +8 -3
  287. package/dist/types/phases/styles/phase.d.ts +18 -5
  288. package/dist/types/phases/transforms/phase.d.ts +4 -2
  289. package/dist/types/plots/constants.d.ts +3 -17
  290. package/dist/types/plots/correlation/heatmap/props.d.ts +3 -2
  291. package/dist/types/plots/correlation/heatmap/state.d.ts +2 -2
  292. package/dist/types/plots/correlation/scatter/props.d.ts +3 -2
  293. package/dist/types/plots/correlation/scatter/state.d.ts +2 -2
  294. package/dist/types/plots/distribution/box/props.d.ts +28 -2
  295. package/dist/types/plots/distribution/box/state.d.ts +6 -17
  296. package/dist/types/plots/distribution/density/props.d.ts +2 -1
  297. package/dist/types/plots/distribution/density/state.d.ts +2 -2
  298. package/dist/types/plots/distribution/histogram/props.d.ts +16 -2
  299. package/dist/types/plots/distribution/histogram/state.d.ts +2 -2
  300. package/dist/types/plots/distribution/pyramid/props.d.ts +3 -2
  301. package/dist/types/plots/distribution/pyramid/state.d.ts +2 -2
  302. package/dist/types/plots/distribution/violin/props.d.ts +6 -2
  303. package/dist/types/plots/distribution/violin/state.d.ts +2 -2
  304. package/dist/types/plots/evolution/area/props.d.ts +3 -2
  305. package/dist/types/plots/evolution/area/state.d.ts +2 -2
  306. package/dist/types/plots/evolution/line/props.d.ts +3 -2
  307. package/dist/types/plots/evolution/line/state.d.ts +2 -2
  308. package/dist/types/plots/evolution/slope/state.d.ts +2 -2
  309. package/dist/types/plots/evolution/sparkline/state.d.ts +2 -2
  310. package/dist/types/plots/generic/props.d.ts +16 -0
  311. package/dist/types/plots/generic/props.js +1 -0
  312. package/dist/types/plots/generic/state.d.ts +4 -0
  313. package/dist/types/plots/generic/state.js +1 -0
  314. package/dist/types/plots/map/geo/state.d.ts +1 -1
  315. package/dist/types/plots/part-of-a-whole/treemap/props.d.ts +18 -6
  316. package/dist/types/plots/part-of-a-whole/treemap/state.d.ts +2 -2
  317. package/dist/types/plots/props.d.ts +3 -0
  318. package/dist/types/plots/ranking/bar/props.d.ts +3 -2
  319. package/dist/types/plots/ranking/bar/state.d.ts +2 -2
  320. package/dist/types/plots/ranking/bullet/state.d.ts +2 -2
  321. package/dist/types/plots/ranking/cleveland/props.d.ts +3 -2
  322. package/dist/types/plots/ranking/cleveland/state.d.ts +2 -2
  323. package/dist/types/plots/ranking/dumbbell/props.d.ts +3 -2
  324. package/dist/types/plots/ranking/dumbbell/state.d.ts +2 -2
  325. package/dist/types/plots/ranking/forest/props.d.ts +5 -2
  326. package/dist/types/plots/ranking/forest/state.d.ts +2 -2
  327. package/dist/types/plots/ranking/lollipop/props.d.ts +3 -2
  328. package/dist/types/plots/ranking/lollipop/state.d.ts +2 -2
  329. package/docs/architecture.md +9 -9
  330. package/docs/markers.md +36 -6
  331. package/docs/plots/evolution/line.md +1 -1
  332. package/docs/plots/evolution/slope.md +1 -1
  333. package/docs/plots/part-of-a-whole/treemap.md +36 -2
  334. package/docs/plots/ranking/bar.md +1 -0
  335. package/docs/plots/ranking/cleveland.md +1 -1
  336. package/docs/state.md +33 -0
  337. package/docs/styles-and-segments.md +2 -15
  338. package/docs/theming.md +2 -1
  339. package/docs/tooltip-and-hover.md +81 -3
  340. package/docs/value-labels.md +159 -0
  341. package/examples/BarValues.svelte +1 -1
  342. package/examples/LineDates.svelte +1 -1
  343. package/examples/ResponsiveLine.svelte +3 -1
  344. package/examples/TreemapHover.svelte +25 -0
  345. package/examples/ValueLabels.svelte +1 -1
  346. package/llms-full.txt +9 -7
  347. package/llms.txt +3 -1
  348. package/package.json +3 -1
  349. package/dist/markers/utils/BoxLabel.d.ts +0 -58
  350. package/dist/markers/utils/BoxLabel.js +0 -175
  351. package/dist/markers/utils/MarkerLabel.svelte +0 -33
  352. package/dist/markers/utils/MarkerLabel.svelte.d.ts +0 -10
  353. /package/dist/layout/plot/{Plot.svelte → AbstractPlot.svelte} +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,65 @@
2
2
 
3
3
  All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/).
4
4
 
5
+ ## [1.19.0] - 2026-11-11
6
+
7
+ ### Added
8
+
9
+ - **Value labels, laid out three ways.** Every plot's `styles.values`, and every marker's `label`, takes a `layout`:
10
+ - `'point'` - beside a point: a line's last value, a scatter's dots, a corner of a bar. `side` (`'after'`, `'before'`, `'above'`, `'below'`, `'on'`) and `gap` place it.
11
+ - `'path'` - along an edge or a stroke: past a bar's tip (its sign followed per bar), along a line or an area's edge, around a dot's rim. `edge`, `side` and `offset` place it, `offset: 'max'` putting it at each curve's peak.
12
+ - `'box'` - inside each shape, fitted to it: a heatmap's cells, a stacked bar's segments.
13
+
14
+ Each plot kind keeps its own default and takes only the layouts its shapes can write, checked by its types: `<LinePlot styles={{ values: { layout: 'path' } }} />` writes each series' name along its line. See the new [Value labels](docs/value-labels.md) page and the _Layout/Values_ stories.
15
+
16
+ - **Labels that stay readable.** On a scatter, labels move clockwise around their dot to the first free spot, and are left out where there is none (`declutter: 'around'`, also on a marker's label or a `text` marker). A value written on its own dot is hidden where a later dot covers it.
17
+ - **Several values per row.** `styles.values.parts` picks which values a row writes, typed per plot: a box's or violin's `'min'`, `'p25'`, `'median'`, `'p75'`, `'max'` and `'outliers'`, a bullet's `'target'` and `'ranges'`, a forest's `'lower'` and `'upper'` - as a list, or a record with options for each (`parts: { median: true, max: { format } }`). A label's `format` gets the part in `context.part`.
18
+ - **Value labels on `BoxPlot`, `ViolinPlot` and `DensityPlot`.** A box writes its whisker ends and median, a violin its median, a density each curve's name at its peak.
19
+ - **More on value labels:** a marker's `label` can be a list; any option of `styles.values` turns the labels on, without `show: true`; `select` and `series` now also pick the labelled rows of bar, histogram, heatmap and scatter plots.
20
+ - **A generic `Plot`** that draws only its `markers`, with every option a plot takes, for annotations and custom compositions: `<Plot markers={[{ type: 'density', data, x: 'gdp', y: 'life' }]} />`.
21
+ - **Markers inherit from their plot** the position and channels they leave unset (`x`, `y`, `opacity`, `symbol`, `r`, `length`, with their scales), and run horizontally or vertically by their own channels when the plot has none.
22
+
23
+ ### Changed
24
+
25
+ - **Breaking:** `styles.values.anchor` is replaced by `layout` and its options. On a line plot, `'start'` is now `side: 'after'` (the default), `'end'` is `side: 'before'`, `'outside'` is `side: 'above'`, `'middle'` is `side: 'on'`. On a bar plot, `'outside'` is the default, `'tip'` and `'base'` are `{ layout: 'path', edge: 'tip' | 'base', side: 'inside' }`, and `'middle'` or a page edge is `{ layout: 'box', anchor }`.
26
+ - **Breaking:** `styles.values.fontStyle` only styles the text: `dx`, `dy`, `textAnchor` and `lineAnchor` are gone, the layout places it (`fontStyle: { dy: -12 }` is `gap: 12`).
27
+ - **Breaking:** a shape label's `outside` is gone: `{ anchor: 'top', outside: true }` is `{ layout: 'path', edge: 'top' }`.
28
+ - **Breaking:** the plot shell exported as `Plot` (to build your own plot kinds) is now `AbstractPlot`; `Plot` is the new generic plot.
29
+ - A scatter's value labels sit above their dots by default, and no longer overlap.
30
+
31
+ ### Fixed
32
+
33
+ - `styles.values.color` now colors the labels of bar, pyramid, histogram and scatter plots.
34
+ - A violin plot colored by its category draws each violin centered in its band, instead of side by side with empty slots.
35
+ - The x axis title no longer lands on the tick labels when value labels grow the plot's margins.
36
+ - A label along a line, near one of its ends, is no longer cut short.
37
+ - **Hovering no longer lays the whole plot out again at every move of the pointer.** svelteplot works a plot's scales out from every mark's rows, and the hover changed them at each move: its dots, rules and values came and went as marks of the plot, the `active` and `others` styles split a marker's rows anew, and a mark copied its rows whenever one of their styles changed. Each move rebuilt every scale from every row, scaled every mark again and measured the margins again, more so the more series, rows and synced panels a plot has. Now the hover's `back` and `front` markers are drawn on the plot's scales without taking part in them, a marker the hover restyles stays whole with each style read off the row as it is hovered, and the plot works its scales out again only when a mark's rows hold something new. A move of the pointer over a fifteen-line plot settles in about a quarter of the time, and over a treemap or a heatmap that restyles its shapes in a tenth to a quarter.
38
+ - The outline the `hover` marker's `active` gives the hovered shapes (its `stroke`, `strokeWidth`, `strokeOpacity` and `strokeDasharray`, the plot's own `hover.active` by default) is drawn whole, over every shape of the plot. It was drawn on the shape itself, in its marker's order, so the tiles of a treemap, the cells of a heatmap with no gap or the bars of a plot drawn after it covered part of it. The outline never takes the pointer from the shape under it.
39
+
40
+ ## [1.18.0] - 2026-11-09
41
+
42
+ ### Added
43
+
44
+ - A `band` marker: the band of a category on a band scale, across the whole of the other axis - `{ type: 'band', axis: 'x', value: 'Salta' }`. `value` is a category or a list of them, or with `data` a field key or a function of the row; rows that name the same category draw one band. `slice` fills part of it, as the fractions of its width left out at each end (a grouped bar's series), and a band several rows share fills what all of their slices do. `styles` take `AreaStyle`, each field a value or a function of the row, over the configuration's new `band` (`{ fill: '#94a3b8', fillOpacity: 0.25 }`). It takes the pointer only with a handler of its own, and draws nothing on an axis that is not a band scale.
45
+ - The `hover` marker's `active` and `others` restyle the shapes themselves: the ones the hover matches (by its `strategy`) take `active`, every other one `others`, while the hover is on - `fill`, `fillOpacity`, `stroke`, `strokeWidth`, `strokeOpacity` and `strokeDasharray`, each a value or a function of the row. `markers={[{ type: 'hover', active: { fillOpacity: 1 }, others: { fillOpacity: 0.3 } }]}` lightens the hovered tile of a `TreemapPlot` and fades the rest, and does the same on the cells of a `HeatmapPlot`, the bars of a `BarPlot`, a `BulletPlot` and a `PyramidPlot`, a `HistogramPlot`'s bins, a `ScatterPlot`'s dots and the dots of the Cleveland family, whose own shapes are linked to the hover. On a dot they are its `dotFill`, `dotStroke`... The shape is restyled, not covered: its label stays on top, and one with no `fill` of its own is written in the color that reads best on the new one. They go over `styles` and `segments`; a series the legend dims keeps its dimmed fill and opacities.
46
+ - The `hover` marker's `back` and `front`: the markers it draws behind the plot's shapes and in front of them - any marker but another `hover`, a `component` too, with its styles and events. They draw the hovered points, each a row with its `x`, `y`, `label` (written as the marker's number fields or `format` ask), `series`, `color`, `areaInset` and `row`, unless they have `data` of their own, and what they leave unset comes from the hover: `x` and `y`, a `rule`'s and a `band`'s `value` (and a band's `slice`), a `text`'s `text`, the configuration's `hover` look (`rule`, `dot`, `font`, `area`) and the series color of a `dot` and a `text`. `points: 'active'` draws only the point under the pointer, and a function of the point some of them. On a grouped bar plot each is drawn in its series' slice of the band.
47
+ - Each plot kind has a hover of its own that an author's `hover` marker is laid over: `active` and `others` field by field, `back` and `front` replaced when set (`back: []` draws nothing behind). `LinePlot`, `AreaPlot` and `DensityPlot` draw a crosshair along each axis their strategy matches along, and a dot and the value on each point, as the marker did; `ScatterPlot` a crosshair through the point and its value; `SlopePlot` and the Cleveland family (`ClevelandPlot`, `DumbbellPlot`, `ForestPlot`, `LollipopPlot`) a rule along the value axis, a dot and the value; `BarPlot`, `BulletPlot`, `BoxPlot`, `ViolinPlot` and `PyramidPlot` the hovered category's band behind their shapes; `HistogramPlot` the hovered bin's span; `SparklinePlot` a dot; `TreemapPlot` and `HeatmapPlot` only outline the hovered tile or cell, in the configuration's new `hover.active` (`{ stroke: '#111827', strokeWidth: 2 }`).
48
+ - The hover's point under the pointer is the one nearest it of those the hover reaches: a crosshair at it, and `points: 'active'`, follow the pointer up and down a category from one series' point to another's.
49
+ - A row context: what a plot knows of each row it draws, worked out once as it reads its data and kept on the row - its `series`, its `x` and `y` (its own values, not a stack's running total, else where the transforms put it), the `value` it shows, the `row` itself, and what the plot kind works out for it: a `TreemapPlot` tile's `name`, `path` and `share`; a `HistogramPlot` bin's `count`, `from` and `to`; a `BoxPlot` or `ViolinPlot` value's box (`category`, `min`, `p25`, `median`, `p75`, `max`, `count`, `outliers`); a `DensityPlot` point's estimate as its `value`; a `HeatmapPlot` cell's color value. `tooltip.format`, `styles.values.format`, the `hover` marker's points (`point.context`, in its `format` and its `back` and `front` markers) and `usePlot().contextOf(row)` all read it, and `RowContext.of(row)` reads it anywhere, from a row or a copy of it. A plot kind adds its own with a `context` function in its defaults. `PlotRowContext`, `KindRowContext`, `TreemapRowContext`, `HistogramRowContext` and `BoxRowContext` are exported.
50
+ - A `DensityPlot`'s hovered point and its tooltip read as its estimated density, with three decimals.
51
+ - What a plot's hover draws follows the strategy in force as it is shown: a composer's `hover.strategy` changed while the plot is on screen (a scrolly step) changes the crosshair it draws.
52
+ - A marker's `hover` takes `'trigger'` (a hit area of the plot's hover, what `true` was) and `'style'` (its shapes take the hover marker's `active` and `others`); `true` does both. `HoverMarkerConfig`, `HoverShapeStyle` and `HoverLayerMarker` are exported.
53
+ - `examples/TreemapHover.svelte`, a _Configuration / State_ story reading a histogram's row context, and a `Layout/Hover` section of stories: each plot kind's own hover, the strategies (one changed while a plot is shown), the number fields, the scope, `active` and `others`, `back` and `front`.
54
+
55
+ ### Changed
56
+
57
+ - **Breaking:** `styles.values.format` is `(value, number, context)`, as a tooltip's `format`: the series is `context.series`, the labelled row `context.row`. `format: (v, name) => `${name}: ${v}`` is `format: (v, _number, { series }) => `${series}: ${v}``.
58
+ - **Breaking:** a `HistogramPlot`'s tooltip rows are its bins as they are, without the `count`, `from`, `to` and `group` they had: those are in the `context`, a `tooltip.format`'s third argument (`group` is `series`).
59
+ - A tooltip's `context` holds the row's `x`, `y`, `value` and `row` along with its `series`, and a `TreemapPlot`'s the tile's `name`, `path` and `value` along with its `share`. `TreemapTooltipContext` is `TreemapRowContext`.
60
+ - **Breaking:** the `hover` marker's `ruleX`, `ruleY`, `areaX`, `areaY`, `showLabels`, `rule`, `area`, `dot` and `text` are gone: what it draws is its `back` and `front` markers. `ruleX: false` is `back: []`; `ruleY: true` a `{ type: 'rule', axis: 'y', points: 'active' }` in `back`; `areaX: true` a `{ type: 'band', axis: 'x' }` in `back`; `showLabels: false` is `front: [{ type: 'dot' }]`; `rule`, `area`, `dot` and `text` are the `styles` of those markers. `text.textAnchor: 'outside'` is two `text` markers, each kept to one side of zero by `points`. On every plot but `LinePlot`, `AreaPlot` and `DensityPlot`, `{ type: 'hover' }` draws something else than the crosshair, dot and label it drew: see the hover each plot kind has of its own, above.
61
+ - A marker with `hover: true` (or `'trigger'`) hovers the row of the shape under the pointer, not the first of its rows.
62
+ - A series the legend dims (`mode: 'dim'`) stays hoverable: it is matched and shows in the tooltip. Only one it hides, omits or rescales away is out of the hover.
63
+
5
64
  ## [1.17.0] - 2026-11-06
6
65
 
7
66
  ### Added
package/README.md CHANGED
@@ -136,7 +136,8 @@ Start with the concepts; the rest is organised by what you want a plot to do.
136
136
  | [Concepts](docs/concepts.md) | Plots and figures, rows and series, channels, the props every plot shares |
137
137
  | [Plots](docs/plots.md) | Every plot kind: what it draws and what it needs |
138
138
  | [Scales](docs/scales.md) | Axes (`x`, `y`) and channel scales (`color`, `grouping`, `opacity`, `symbol`, `r`, `length`) |
139
- | [Styles and segments](docs/styles-and-segments.md) | Value labels, frames, gap filling, and styling ranges of the data |
139
+ | [Styles and segments](docs/styles-and-segments.md) | Value labels in brief, frames, gap filling, and styling ranges of the data |
140
+ | [Value labels](docs/value-labels.md) | A plot's values on its shapes, and a marker's labels: layouts and their options |
140
141
  | [Markers](docs/markers.md) | Extra marks on a plot: annotations, regions, hover highlights, custom components |
141
142
  | [Transforms and statistics](docs/transforms-and-statistics.md) | Stacking, binning, smoothing, regression and the other data transforms |
142
143
  | [Tooltip and hover](docs/tooltip-and-hover.md) | Floating tooltips, in-plot highlights, syncing hover across plots |
@@ -158,10 +158,11 @@ export const DEFAULT_CONFIG = {
158
158
  border: 'none'
159
159
  },
160
160
  hover: {
161
- rule: { stroke: '#e6580d', strokeOpacity: 0.35, strokeWidth: 1.5, strokeDasharray: '4 4' },
161
+ rule: { stroke: '#64748b', strokeOpacity: 0.35, strokeWidth: 1.5, strokeDasharray: '4 4' },
162
162
  dot: { dotRadius: 5, dotFill: 'currentColor' },
163
163
  font: { fill: 'currentColor', fontSize: 12, dy: -18 },
164
- area: { fill: '#94a3b8', fillOpacity: 0.4 }
164
+ area: { fill: '#94a3b8', fillOpacity: 0.4 },
165
+ active: { stroke: '#111827', strokeWidth: 2 }
165
166
  },
166
167
  facet: {
167
168
  indicator: {
@@ -247,7 +248,7 @@ export const DEFAULT_CONFIG = {
247
248
  labelFontSize: 11,
248
249
  labelGap: 4
249
250
  },
250
- // Beside a vertical delta (taken on x), above a horizontal one (on y).
251
+ band: { fill: '#94a3b8', fillOpacity: 0.25 },
251
252
  delta: {
252
253
  text: {
253
254
  x: { dx: 12, dy: 0, lineAnchor: 'middle', textAnchor: 'start' },
package/dist/index.d.ts CHANGED
@@ -19,9 +19,15 @@ export { default as TreemapPlot } from './plots/part-of-a-whole/treemap/Plot.sve
19
19
  export { default as ViolinPlot } from './plots/distribution/violin/Plot.svelte';
20
20
  export { default as PlotComposer } from './layout/composer/PlotComposer.svelte';
21
21
  export { default as GridCell } from './layout/grid/GridCell.svelte';
22
- export { default as Plot } from './layout/plot/Plot.svelte';
22
+ export { default as Plot } from './plots/generic/Plot.svelte';
23
+ export { default as AbstractPlot } from './layout/plot/AbstractPlot.svelte';
23
24
  export { default as BasePlotLayout } from './layout/base/BasePlotLayout.svelte';
24
25
  export { usePlot, useFigure } from './layout/plot/usePlot';
26
+ export { RowContext } from './phases/context/RowContext';
27
+ export type { PlotRowContext, KindRowContext } from './types/layout/context';
28
+ export type { ContextStageOptions } from './types/phases/context/phase';
29
+ export type { BoxRowContext, BoxSummary } from './types/plots/distribution/box/props';
30
+ export type { HistogramRowContext } from './types/plots/distribution/histogram/props';
25
31
  export type { PublicPlotContext, PublicFigureContext, PublicHover, PublicPlotHover, PublicLegend, PublicTimeline } from './layout/plot/PublicPlotContext';
26
32
  export { argentinaBicontinental } from './layout/coordinates/projections/argentina';
27
33
  export { setConfiguration, getConfiguration, resetConfiguration, configToCssVars, cssVarsStyle, cssVarsRule, DEFAULT_CONFIG } from './configuration/config.svelte';
@@ -37,8 +43,9 @@ export { Statistics } from './phases/statistics/Statistics';
37
43
  export type { AxisValue, ChannelValue, ChannelName, AxisChannelName, IndependentChannelName, SizeChannelName, ChannelAccessors, GroupingAccessor } from './types/layout/mapping';
38
44
  export type { AxisScale, AxisBasedScalesConfig, ChannelScalesConfig } from './types/layout/scales';
39
45
  export type { NumberDisplay } from './types/layout/numbers';
40
- export type { TreemapPlotProps, TreemapTooltipContext } from './types/plots/part-of-a-whole/treemap/props';
46
+ export type { TreemapPlotProps, TreemapRowContext, TreemapTooltipContext } from './types/plots/part-of-a-whole/treemap/props';
41
47
  export type { TreemapTile } from './types/transforms/treemap';
48
+ export type { GenericPlotProps, GenericDataProps } from './types/plots/generic/props';
42
49
  export type { Accessor, Series, SeriesProps, NonAxisDataProps, SingleAxisDataProps, DualAxisDataProps } from './types/plots/data/common';
43
50
  export type { BasePlotProps, PlotCoreProps, PlotChromeProps, FigureBoxProps, SegmentsConfig, ScalesConfig, MarginConfig, TooltipConfig, HoverConfig } from './types/plots/props';
44
51
  export type { AxisBasedStylesConfig, ConnectorBasedStylesConfig, BulletStylesConfig, GapsAwarePlotStylesConfig, CurveAwarePlotStylesConfig, GeoStylesConfig, GeoTileLayerConfig } from './types/layout/styles';
@@ -47,7 +54,7 @@ export type { LineSegmentStyle, BarSegmentStyle, CellSegmentStyle, GeoSegmentSty
47
54
  export type { Range, Area, Segment } from './types/plots/segments/config';
48
55
  export type { SymbolType } from './types/plots/constants';
49
56
  export type { FontStyle, StrokeStyle, DotStyle, AreaStyle } from './types/plots/styling';
50
- export type { AxisBasedMarkersConfig, BrushSelection } from './types/markers/common';
57
+ export type { AxisBasedMarkersConfig, BrushSelection, HoverMarkerConfig, HoverShapeStyle, HoverLayerMarker } from './types/markers/common';
51
58
  export type { StatisticConfig } from './types/layout/statistics';
52
59
  export type * from './types/transforms';
53
60
  export type { GeoFeature, GeoJsonInput, GeoDataProps, Topology } from './types/plots/data/geo';
package/dist/index.js CHANGED
@@ -25,9 +25,12 @@ export { default as ViolinPlot } from './plots/distribution/violin/Plot.svelte';
25
25
  export { default as PlotComposer } from './layout/composer/PlotComposer.svelte';
26
26
  export { default as GridCell } from './layout/grid/GridCell.svelte';
27
27
  // The generic plot, to build your own plot kind: wrap it with your kind's core and defaults.
28
- export { default as Plot } from './layout/plot/Plot.svelte';
28
+ export { default as Plot } from './plots/generic/Plot.svelte';
29
+ export { default as AbstractPlot } from './layout/plot/AbstractPlot.svelte';
29
30
  export { default as BasePlotLayout } from './layout/base/BasePlotLayout.svelte';
30
31
  export { usePlot, useFigure } from './layout/plot/usePlot';
32
+ // What a plot knows of each row it draws, which every format reads.
33
+ export { RowContext } from './phases/context/RowContext';
31
34
  // Custom geo projections - usable as `scales.projection.type`.
32
35
  export { argentinaBicontinental } from './layout/coordinates/projections/argentina';
33
36
  export { setConfiguration, getConfiguration, resetConfiguration, configToCssVars, cssVarsStyle, cssVarsRule, DEFAULT_CONFIG } from './configuration/config.svelte';
@@ -2,6 +2,7 @@
2
2
  import type { ComponentProps, Snippet } from 'svelte';
3
3
  import { geoCentroid, type GeoPermissibleObjects } from 'd3-geo';
4
4
  import { Plot } from 'svelteplot';
5
+ import ScaleGateMarks from '../geometry/ScaleGateMarks.svelte';
5
6
  import { resolveProjection } from './resolveProjection';
6
7
  import { resolveCameraTarget } from './resolveCameraTarget';
7
8
  import { createGeoZoom, type GeoZoomTransform } from './zoom.svelte';
@@ -182,7 +183,8 @@
182
183
  </defs>
183
184
  <g clip-path="url(#{clipId})">
184
185
  <ProjectionZoom inner={geoZoom.transform} outer={cameraTransform}>
185
- {@render children()}
186
+ <!-- The plot's scales follow what its marks' rows hold, not every copy a mark makes of them. -->
187
+ <ScaleGateMarks>{@render children()}</ScaleGateMarks>
186
188
  </ProjectionZoom>
187
189
  </g>
188
190
  </Plot>
@@ -28,6 +28,7 @@
28
28
  import DotMarker from '../../markers/dot/DotMarker.svelte';
29
29
  import TextMarker from '../../markers/text/TextMarker.svelte';
30
30
  import RuleMarker from '../../markers/rule/RuleMarker.svelte';
31
+ import BandMarker from '../../markers/band/BandMarker.svelte';
31
32
  import HoverMarker from '../../markers/hover/HoverMarker.svelte';
32
33
  import GeoHoverMarker from '../../markers/geo/GeoHoverMarker.svelte';
33
34
  import DeltaMarker from '../../markers/delta/DeltaMarker.svelte';
@@ -39,9 +40,10 @@
39
40
  import ContourMarker from '../../markers/contour/ContourMarker.svelte';
40
41
  import ContourClipMarker from '../../markers/contour/ContourClipMarker.svelte';
41
42
  import InsetMarker from '../../markers/inset/InsetMarker.svelte';
42
- import MarkerLabel from '../../markers/utils/MarkerLabel.svelte';
43
+ import MarkerLabel from '../../markers/labels/MarkerLabel.svelte';
43
44
  import FrameClip from './FrameClip.svelte';
44
45
  import MarkerOffset from './MarkerOffset.svelte';
46
+ import ScaleFreeMarks from './ScaleFreeMarks.svelte';
45
47
  import { getConfiguration } from '../../configuration/config.svelte';
46
48
  import { usePlot } from '../plot/usePlot';
47
49
  import { PlotMargins } from '../margins/PlotMargins.svelte';
@@ -54,6 +56,14 @@
54
56
  import type { GeoFeature } from '../../types/plots/data/geo';
55
57
  import { MarkerGrouping } from '../../phases/statistics/MarkerGrouping';
56
58
  import { FrameClipping } from './FrameClipping';
59
+ import { HoverShapes, type HoverShapesReach } from '../hover/HoverShapes';
60
+ import { PlotInteraction } from '../interaction/PlotInteraction.svelte';
61
+ import { SERIES_KEY } from '../../phases/transforms/TransformsPhase';
62
+ import { HoverLayers, type HoverPointGroup } from '../hover/HoverLayers';
63
+ import { BandNudge } from '../../markers/utils/BandNudge';
64
+ import { PointPixel } from '../../markers/utils/PointPixel';
65
+ import { HoverDefaults } from '../hover/HoverDefaults';
66
+ import type { HoverMarkerConfig } from '../../types/markers/common';
57
67
 
58
68
  /**
59
69
  * Renders every marker in `markers`, in array order, each delegated to the
@@ -107,9 +117,137 @@
107
117
  } = $props();
108
118
 
109
119
  const cfg = $derived(getConfiguration());
120
+ const interaction = PlotInteraction.current(() => cfg);
121
+
122
+ /**
123
+ * The markers, each `hover` one laid over the plot kind's own hover under the strategy in force - read as they
124
+ * are drawn, so a strategy changed while the plot is shown changes what the hover draws.
125
+ */
126
+ const drawn = $derived.by(() => {
127
+ const look = ctrl.look;
128
+ return markers.map((marker) =>
129
+ marker.type === 'hover'
130
+ ? (HoverDefaults.merge(look, marker as HoverMarkerConfig) as MarkerConfig)
131
+ : marker
132
+ );
133
+ });
134
+
135
+ /** The look the hover markers give the shapes linked to the hover. */
136
+ const shapes = $derived(new HoverShapes(drawn));
137
+ const reach: HoverShapesReach = {
138
+ roleOf: (row, series) => ctrl.roleOf(row as TData, series),
139
+ dimmed: (row) => {
140
+ const series = row[SERIES_KEY];
141
+ return typeof series === 'string' && interaction.fillFor(series) !== undefined;
142
+ },
143
+ get cfg() {
144
+ return cfg;
145
+ }
146
+ };
110
147
 
111
148
  // Mounted inside svelteplot's `<Plot>`, the one place the margins it settles on can be read.
112
- PlotMargins.current()?.follow(usePlot().svelteplot);
149
+ const svelteplot = usePlot().svelteplot;
150
+ PlotMargins.current()?.follow(svelteplot);
151
+
152
+ /**
153
+ * The points a hover marker draws over: every matched one; with `series`, that series' only, in its color -
154
+ * or with `scope: 'segment'`, each segment's, in the segment's. The first is the active one of a series.
155
+ */
156
+ function hoverGroupsOf(marker: HoverMarkerConfig): HoverPointGroup[] {
157
+ const points = ctrl.points;
158
+ if (points.length === 0) return [];
159
+ const nearest = JSON.parse(nearestKey || '{}') as {
160
+ all?: number;
161
+ bySeries?: Record<string, number>;
162
+ };
163
+ const scope = marker.series;
164
+ if (!scope) {
165
+ const active = nearest.all !== undefined ? points[nearest.all] : undefined;
166
+ return [{ key: '', points, active: active ?? ctrl.activePoint }];
167
+ }
168
+ const under = nearest.bySeries?.[scope];
169
+ const activeOf = (list: typeof points) =>
170
+ (under !== undefined && list.find((p) => p.row === points[under].row)) || list[0] || null;
171
+ const group = groupByName.get(scope);
172
+ if (!group) return [];
173
+ const own = points.filter((p) => p.series === scope);
174
+ const colored = (list: typeof own, color: string | undefined) =>
175
+ color ? list.map((p) => ({ ...p, color })) : list;
176
+ if (marker.scope !== 'segment') {
177
+ const seriesPoints = colored(own, group.segments[0]?.color ?? group.color);
178
+ return [{ key: scope, points: seriesPoints, active: activeOf(seriesPoints) }];
179
+ }
180
+ return group.segments.map((seg, i) => {
181
+ // p.row (TData) is always a superset of TSeries in practice, not provable across two independent generics.
182
+ const segPoints = colored(
183
+ own.filter((p) => seg.match(p.row as unknown as TSeries)),
184
+ seg.color
185
+ );
186
+ return { key: `${scope}-${i}`, points: segPoints, active: activeOf(segPoints) };
187
+ });
188
+ }
189
+
190
+ /**
191
+ * The hovered point under the pointer: of all of them, and of each series - the nearest to the pointer, not the
192
+ * first the strategy matched, so a crosshair at it follows the pointer across the series of a category. Kept as
193
+ * text, so the hover's markers are built again only when it changes, not at every move of the pointer.
194
+ */
195
+ const nearestKey = $derived.by(() => {
196
+ const cursor = ctrl.cursor;
197
+ const points = ctrl.points;
198
+ if (!cursor || points.length === 0) return '';
199
+ const all = PointPixel.nearest(svelteplot.scales, points, cursor);
200
+ const bySeries: Record<string, number> = {};
201
+ for (const series of new Set(points.map((p) => p.series))) {
202
+ if (series == null) continue;
203
+ const indexes = points.flatMap((p, i) => (p.series === series ? [i] : []));
204
+ const nearest = PointPixel.nearest(
205
+ svelteplot.scales,
206
+ indexes.map((i) => points[i]),
207
+ cursor
208
+ );
209
+ if (nearest >= 0) bySeries[series] = indexes[nearest];
210
+ }
211
+ return JSON.stringify({ all: all >= 0 ? all : undefined, bySeries });
212
+ });
213
+
214
+ /** The markers `marker`'s `layer` draws, over each group of the points it draws over. */
215
+ function hoverPartsOf(marker: HoverMarkerConfig, layer: 'back' | 'front', index: number) {
216
+ return hoverGroupsOf(marker).flatMap((group) =>
217
+ HoverLayers.parts(
218
+ marker,
219
+ layer,
220
+ {
221
+ ...group,
222
+ points: HoverLayers.labelled(group.points, marker, cfg),
223
+ active: group.active && HoverLayers.labelled([group.active], marker, cfg)[0]
224
+ },
225
+ cfg
226
+ ).map((part) => ({ ...part, key: `${index}-${part.key}` }))
227
+ );
228
+ }
229
+
230
+ /**
231
+ * What each hover marker draws, behind and in front, built once per hover - not as it is drawn, where reading
232
+ * the scales would build its markers anew whenever svelteplot settles them, and settle them again.
233
+ */
234
+ const hoverLayers = $derived(
235
+ new Map(
236
+ drawn.flatMap((marker, index) =>
237
+ marker.type === 'hover'
238
+ ? [
239
+ [
240
+ index,
241
+ {
242
+ back: hoverPartsOf(marker as HoverMarkerConfig, 'back', index),
243
+ front: hoverPartsOf(marker as HoverMarkerConfig, 'front', index)
244
+ }
245
+ ] as const
246
+ ]
247
+ : []
248
+ )
249
+ )
250
+ );
113
251
 
114
252
  const scopedSeriesOf = (marker: MarkerConfig): string | undefined =>
115
253
  'series' in marker && typeof marker.series === 'string' && marker.series
@@ -131,19 +269,20 @@
131
269
  }
132
270
 
133
271
  /**
134
- * A marker with `hover: true`, with the plot's hover added to its own pointer handlers: entering or moving
135
- * over any of its shapes hovers its rows - as they are drawn now, should the plot have been laid out again
136
- * under a resting pointer - and leaving it ends the hover.
272
+ * A marker with `hover: true` or `'trigger'`, with the plot's hover added to its own pointer handlers: entering or
273
+ * moving over one of its shapes hovers that shape's row, and leaving it ends the hover.
137
274
  */
138
275
  function withHover(marker: MarkerConfig, rows: TData[] | TSeries[]): MarkerConfig {
139
- if (!('hover' in marker) || marker.hover !== true) return marker;
276
+ if (!('hover' in marker) || (marker.hover !== true && marker.hover !== 'trigger'))
277
+ return marker;
140
278
  const own = marker as CommonMarkerEvents & { data?: unknown[] };
141
- const hovered = (own.data ?? rows) as TData[];
279
+ // The row of the shape under the pointer - a copy svelteplot hands over, which the hover finds by its place.
280
+ const hovered = (row: unknown) => [(row ?? (own.data ?? rows)[0]) as TData];
142
281
  return {
143
282
  ...marker,
144
283
  onpointerenter: (event: Event, row: unknown, index: number) => {
145
284
  own.onpointerenter?.(event, row, index);
146
- ctrl.onPointer(hovered);
285
+ ctrl.onPointer(hovered(row));
147
286
  },
148
287
  onpointerleave: (event: Event, row: unknown, index: number) => {
149
288
  own.onpointerleave?.(event, row, index);
@@ -151,7 +290,7 @@
151
290
  },
152
291
  onpointermove: (event: Event, row: unknown, index: number) => {
153
292
  own.onpointermove?.(event, row, index);
154
- ctrl.onPointer(hovered);
293
+ ctrl.onPointer(hovered(row));
155
294
  }
156
295
  } as MarkerConfig;
157
296
  }
@@ -210,6 +349,8 @@
210
349
  <TextMarker marker={{ ...marker, data: marker.data ?? rows }} />
211
350
  {:else if marker.type === 'rule'}
212
351
  <RuleMarker {marker} />
352
+ {:else if marker.type === 'band'}
353
+ <BandMarker {marker} />
213
354
  {:else if marker.type === 'geo'}
214
355
  <GeoFeaturesMarker {marker} />
215
356
  {:else if marker.type === 'graticule'}
@@ -247,15 +388,6 @@
247
388
  <marker.component {...marker.props} data={marker.data ?? seriesData} />
248
389
  {:else if marker.type === 'geo-component'}
249
390
  <marker.component {...marker.props} data={marker.data ?? rows} />
250
- {:else if marker.type === 'hover'}
251
- <HoverMarker
252
- {marker}
253
- data={ctrl.points}
254
- activePoint={ctrl.activePoint}
255
- impliesCrosshairX={ctrl.impliesCrosshairX}
256
- impliesCrosshairY={ctrl.impliesCrosshairY}
257
- onActivePointPixel={ctrl.reportActivePointPixel}
258
- />
259
391
  {:else if marker.type === 'geo-hover'}
260
392
  <GeoHoverMarker {marker} data={ctrl.points} />
261
393
  {:else if marker.type === 'delta'}
@@ -264,41 +396,15 @@
264
396
  {/snippet}
265
397
 
266
398
  {#snippet renderMarker(marker: MarkerConfig, rows: TData[] | TSeries[])}
267
- <MarkerOffset {marker}>
268
- {@render drawMarker(withHover(marker, rows), rows)}
399
+ <!-- One marker over all its rows, each style the hover sets read off the row as it is hovered. -->
400
+ {@const styled = shapes.styled(withHover(marker, rows), rows, reach)}
401
+ <MarkerOffset marker={styled}>
402
+ {@render drawMarker(styled, rows)}
269
403
  </MarkerOffset>
270
404
  {/snippet}
271
405
 
272
406
  {#snippet renderScoped(marker: MarkerConfig, group: ScopedMarkerGroup<TSeries>)}
273
- {#if marker.type === 'hover'}
274
- {@const seriesPoints = ctrl.points.filter((p) => p.series === group.name)}
275
- {#if marker.scope === 'segment'}
276
- {#each group.segments as seg, segIdx (`${group.name}-hover-segment-${segIdx}`)}
277
- <!-- p.row (TData) is always a superset of TSeries in practice, not provable across two independent generics. -->
278
- {@const segPoints = seriesPoints.filter((p) => seg.match(p.row as unknown as TSeries))}
279
- {#if segPoints.length > 0}
280
- <HoverMarker
281
- marker={MarkerGrouping.withHoverSeriesColor(marker, seg.color)}
282
- data={segPoints}
283
- activePoint={segPoints[0] ?? null}
284
- impliesCrosshairX={ctrl.impliesCrosshairX}
285
- impliesCrosshairY={ctrl.impliesCrosshairY}
286
- />
287
- {/if}
288
- {/each}
289
- {:else}
290
- <HoverMarker
291
- marker={MarkerGrouping.withHoverSeriesColor(
292
- marker,
293
- group.segments[0]?.color ?? group.color
294
- )}
295
- data={seriesPoints}
296
- activePoint={seriesPoints[0] ?? null}
297
- impliesCrosshairX={ctrl.impliesCrosshairX}
298
- impliesCrosshairY={ctrl.impliesCrosshairY}
299
- />
300
- {/if}
301
- {:else if marker.type === 'component'}
407
+ {#if marker.type === 'component'}
302
408
  {#if marker.scope === 'segment'}
303
409
  {#each group.segments as seg, segIdx (`${group.name}-component-segment-${segIdx}`)}
304
410
  {@const segmentData = group.data.filter((row) => seg.match(row))}
@@ -316,10 +422,38 @@
316
422
  {/if}
317
423
  {/snippet}
318
424
 
319
- <!-- Every marker in array order, so a later one always draws on top. -->
425
+ {#snippet renderHoverLayer(index: number, layer: 'back' | 'front')}
426
+ <!-- Drawn on the plot's scales, never shaping them: a hover that moves never lays the plot out again. -->
427
+ <ScaleFreeMarks>
428
+ {#each hoverLayers.get(index)?.[layer] ?? [] as part (part.key)}
429
+ <!-- A point in a slice of its band (a grouped bar's series) is drawn in the middle of it. -->
430
+ {@const nudge = BandNudge.of(svelteplot.scales, part.slice)}
431
+ <g transform="translate({nudge.dx}, {nudge.dy})">
432
+ <FrameClip clip={FrameClipping.isClipped(part.marker)}>
433
+ {@render renderMarker(part.marker as MarkerConfig, data)}
434
+ </FrameClip>
435
+ </g>
436
+ {/each}
437
+ </ScaleFreeMarks>
438
+ {/snippet}
439
+
440
+ <!-- What the hover draws behind the plot's shapes, before any of them. -->
441
+ {#each [...hoverLayers.keys()] as index (index)}
442
+ {@render renderHoverLayer(index, 'back')}
443
+ {/each}
444
+
445
+ <!-- Every marker in array order, so a later one always draws on top; a hover marker draws its front markers. -->
320
446
  {#each markers as marker, i (markerKey(marker, i))}
321
447
  {@const scope = scopedSeriesOf(marker)}
322
- {#if scope === undefined}
448
+ {#if marker.type === 'hover'}
449
+ {#if scope === undefined}
450
+ <HoverMarker
451
+ activePoint={ctrl.activePoint}
452
+ onActivePointPixel={ctrl.reportActivePointPixel}
453
+ />
454
+ {/if}
455
+ {@render renderHoverLayer(i, 'front')}
456
+ {:else if scope === undefined}
323
457
  <FrameClip clip={FrameClipping.isClipped(marker)}>
324
458
  {@render renderMarker(marker, data)}
325
459
  </FrameClip>
@@ -328,6 +462,39 @@
328
462
  {/if}
329
463
  {/each}
330
464
 
465
+ {#snippet renderOutline(marker: MarkerConfig, rows: TData[] | TSeries[])}
466
+ {@const outline = shapes.outline(marker, rows, reach)}
467
+ {#if outline}
468
+ <FrameClip clip={FrameClipping.isClipped(outline)}>
469
+ <MarkerOffset marker={outline}>
470
+ {@render drawMarker(outline, rows)}
471
+ </MarkerOffset>
472
+ </FrameClip>
473
+ {/if}
474
+ {/snippet}
475
+
476
+ <!--
477
+ The hovered shapes' outline, over every shape: a shape is drawn in its marker's order, so a neighbour drawn after
478
+ it would cover part of its outline. Drawn on the plot's scales, never shaping them, and never taking the pointer.
479
+ -->
480
+ {#if shapes.outlines}
481
+ <g class="dct-hover-outline" pointer-events="none">
482
+ <ScaleFreeMarks>
483
+ {#each markers as marker, i (markerKey(marker, i))}
484
+ {@const scope = scopedSeriesOf(marker)}
485
+ {#if marker.type !== 'hover' && marker.type !== 'component'}
486
+ {#if scope === undefined}
487
+ {@render renderOutline(marker, data)}
488
+ {:else if groupByName.has(scope)}
489
+ {@const group = groupByName.get(scope)!}
490
+ {@render renderOutline(MarkerGrouping.withSeriesColor(marker, group.color), group.data)}
491
+ {/if}
492
+ {/if}
493
+ {/each}
494
+ </ScaleFreeMarks>
495
+ </g>
496
+ {/if}
497
+
331
498
  <!--
332
499
  The labels the shapes write in themselves, after every marker - the hover's hit areas too, which are the last of them -
333
500
  so a label that listens for the pointer is not covered, and one outside its shape is not clipped with it.
@@ -335,8 +502,10 @@
335
502
  {#each markers as marker, i (markerKey(marker, i))}
336
503
  {@const scope = scopedSeriesOf(marker)}
337
504
  {#if 'label' in marker && marker.label && (scope === undefined || groupByName.has(scope))}
338
- <MarkerOffset {marker}>
339
- <MarkerLabel marker={{ ...marker, data: marker.data ?? data }} />
505
+ <!-- Styled as the shapes are, so a label reads on its shape's color under the hover. -->
506
+ {@const styled = shapes.styled(marker, data, reach)}
507
+ <MarkerOffset marker={styled}>
508
+ <MarkerLabel marker={{ ...styled, data: styled.data ?? data }} />
340
509
  </MarkerOffset>
341
510
  {/if}
342
511
  {/each}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * svelteplot's plot context as the marks drawn under a `ScaleFreeMarks` see it: the plot's own state and scales,
3
+ * but marks that never join the plot's list of marks.
4
+ *
5
+ * svelteplot works out a plot's scales from every mark it holds - their data and options - so a mark whose data
6
+ * changes at every move of the pointer (a hover's dot, its rule, its value) lays the whole plot out again each time:
7
+ * every scale built anew from every row, every mark scaled again, the margins measured again. A mark that is only
8
+ * drawn on the plot's scales, never shaping them, can be left out of them.
9
+ *
10
+ * Left out, a mark is in none of the scales' `skip` lists either - the marks whose channel values are already
11
+ * output (a color, a symbol, an opacity) and go through no scale. What these marks draw has no scale of its own to
12
+ * go through, so every such channel of theirs is taken as it is: a hover's colors are its points' own, resolved.
13
+ */
14
+ /** The parts of svelteplot's plot context a mark reads. */
15
+ export type SvelteplotContext = {
16
+ addMark: (mark: {
17
+ id: symbol;
18
+ }) => void;
19
+ removeMark: (mark: {
20
+ id: symbol;
21
+ }) => void;
22
+ updateMark?: (mark: {
23
+ id: symbol;
24
+ }) => void;
25
+ getPlotState: () => object;
26
+ [key: string]: unknown;
27
+ };
28
+ export declare const ScaleFreeContext: {
29
+ /** `parent`, the plot's own context, for marks drawn on its scales that never take part in them. */
30
+ of(parent: SvelteplotContext): SvelteplotContext;
31
+ };