@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
@@ -0,0 +1,48 @@
1
+ import { resolveAccessor } from '../../utils/accessors';
2
+ /** The bands a `band` marker draws, one per category its rows (or its `value`) name, in the order they first come. */
3
+ export class Bands {
4
+ static #WHOLE = { start: 0, end: 0 };
5
+ /** The marker's bands. Rows that share a category share one band, which fills what all of their slices do. */
6
+ static of(marker) {
7
+ const { rows, categoryOf } = Bands.#rowsOf(marker);
8
+ const sliceOf = Bands.#sliceOf(marker.slice);
9
+ const bands = new Map();
10
+ rows.forEach((row, index) => {
11
+ const category = categoryOf(row);
12
+ if (category == null)
13
+ return;
14
+ const key = category instanceof Date ? +category : category;
15
+ const slice = sliceOf(row);
16
+ const band = bands.get(key);
17
+ if (!band) {
18
+ bands.set(key, { category, slice, row, index });
19
+ return;
20
+ }
21
+ // What either one fills: the least left out at each end.
22
+ band.slice = {
23
+ start: Math.min(band.slice.start, slice.start),
24
+ end: Math.min(band.slice.end, slice.end)
25
+ };
26
+ });
27
+ return [...bands.values()];
28
+ }
29
+ /** The rows a marker draws from, and the category of each: its `data` and `value`, or its `value`'s own. */
30
+ static #rowsOf(marker) {
31
+ const { value, data } = marker;
32
+ if (data) {
33
+ const read = resolveAccessor(value);
34
+ return { rows: data, categoryOf: read };
35
+ }
36
+ const values = (Array.isArray(value) ? value : [value]);
37
+ return { rows: values, categoryOf: (row) => row };
38
+ }
39
+ /** Each row's slice: the marker's own, or a function of the row's; the whole band when it gives none. */
40
+ static #sliceOf(slice) {
41
+ const whole = Bands.#WHOLE;
42
+ const read = typeof slice === 'function' ? slice : () => slice;
43
+ return (row) => {
44
+ const own = read(row);
45
+ return own ? { start: own.start ?? 0, end: own.end ?? 0 } : whole;
46
+ };
47
+ }
48
+ }
@@ -9,19 +9,19 @@
9
9
 
10
10
  /**
11
11
  * Renders one `'bar'` marker: `role: 'segment'` (visible bar via
12
- * `<BarX>`/`<BarY>`), `role: 'hitArea'` (invisible hover hit region for
13
- * one segment), or `role: 'highlight'` (visible area highlight).
12
+ * `<BarX>`/`<BarY>`) or `role: 'hitArea'` (invisible hover hit region for
13
+ * one segment).
14
14
  */
15
15
  let { marker }: { marker: BarMarkerConfig } = $props();
16
16
  const events = MarkerEvents.use(() => marker);
17
- /** The hover band stands for no row, so a style that is a function of one does not apply to it. */
18
- const flatStyles = $derived(RowStyle.flat(marker.styles));
19
17
 
20
18
  const cfg = $derived(getConfiguration());
21
19
  const data = $derived(marker.data ?? []);
22
20
  const channelFill = $derived(MarkerChannels.buildFill(data, marker.color, marker.scales, cfg));
23
21
 
24
- const plot = usePlot().svelteplot;
22
+ const context = usePlot();
23
+ const plot = context.svelteplot;
24
+ const isHorizontal = $derived(marker.isHorizontal ?? context.axes?.isHorizontal ?? false);
25
25
  function categoryScaleFor(isHorizontal: boolean) {
26
26
  return isHorizontal ? plot.scales.y : plot.scales.x;
27
27
  }
@@ -38,11 +38,11 @@
38
38
  </script>
39
39
 
40
40
  {#if marker.role === 'segment'}
41
- {@const categoryScale = categoryScaleFor(marker.isHorizontal)}
41
+ {@const categoryScale = categoryScaleFor(isHorizontal)}
42
42
  {@const bandwidth = categoryScale?.type === 'band' ? categoryScale.fn.bandwidth() : 0}
43
43
  {@const centered =
44
44
  marker.thickness != null ? Math.max(0, (bandwidth - marker.thickness) / 2) : undefined}
45
- {#if marker.isHorizontal}
45
+ {#if isHorizontal}
46
46
  <BarX
47
47
  {...events.props}
48
48
  {data}
@@ -82,7 +82,7 @@
82
82
  />
83
83
  {/if}
84
84
  {:else}
85
- {@const categoryScale = categoryScaleFor(marker.isHorizontal)}
85
+ {@const categoryScale = categoryScaleFor(isHorizontal)}
86
86
  {#if categoryScale?.type === 'band'}
87
87
  {@const bandwidth = categoryScale.fn.bandwidth()}
88
88
  {@const bandStart = Number(categoryScale.fn(marker.category as never) ?? 0)}
@@ -90,69 +90,28 @@
90
90
  {@const insetRight = (marker.styles?.insetRight ?? 0) * bandwidth}
91
91
  {@const insetTop = (marker.styles?.insetTop ?? 0) * bandwidth}
92
92
  {@const insetBottom = (marker.styles?.insetBottom ?? 0) * bandwidth}
93
- {#if marker.role === 'hitArea'}
94
- <!-- The band runs the plot's whole value axis, so the pointer needn't be over the bar. -->
95
- {@const [rangeMin, rangeMax] = valueExtentFor(marker.isHorizontal)}
96
- {#if marker.isHorizontal}
97
- <rect
98
- class="dct-hit-area"
99
- x={rangeMin + insetLeft}
100
- y={bandStart + insetBottom}
101
- width={Math.max(0, rangeMax - rangeMin - insetLeft - insetRight)}
102
- height={Math.max(0, bandwidth - insetTop - insetBottom)}
103
- fill="transparent"
104
- {...events.forRow(data[0], 0)}
105
- />
106
- {:else}
107
- <rect
108
- class="dct-hit-area"
109
- x={bandStart + insetLeft}
110
- y={rangeMin + insetBottom}
111
- width={Math.max(0, bandwidth - insetLeft - insetRight)}
112
- height={Math.max(0, rangeMax - rangeMin - insetTop - insetBottom)}
113
- fill="transparent"
114
- {...events.forRow(data[0], 0)}
115
- />
116
- {/if}
93
+ <!-- The band runs the plot's whole value axis, so the pointer needn't be over the bar. -->
94
+ {@const [rangeMin, rangeMax] = valueExtentFor(isHorizontal)}
95
+ {#if isHorizontal}
96
+ <rect
97
+ class="dct-hit-area"
98
+ x={rangeMin + insetLeft}
99
+ y={bandStart + insetBottom}
100
+ width={Math.max(0, rangeMax - rangeMin - insetLeft - insetRight)}
101
+ height={Math.max(0, bandwidth - insetTop - insetBottom)}
102
+ fill="transparent"
103
+ {...events.forRow(data[0], 0)}
104
+ />
117
105
  {:else}
118
- {@const [valueMin, valueMax] = valueExtentFor(marker.isHorizontal)}
119
- {#if marker.isHorizontal}
120
- {@const thickness = Math.max(0, bandwidth - insetTop - insetBottom) + 2}
121
- {@const center = bandStart + insetBottom + (bandwidth - insetTop - insetBottom) / 2}
122
- <rect
123
- class="hover-area"
124
- x={valueMin}
125
- y={center - thickness / 2}
126
- width={Math.max(0, valueMax - valueMin)}
127
- height={thickness}
128
- fill={flatStyles.fill}
129
- fill-opacity={flatStyles.fillOpacity}
130
- stroke={flatStyles.stroke}
131
- stroke-width={flatStyles.strokeWidth}
132
- stroke-opacity={flatStyles.strokeOpacity}
133
- stroke-dasharray={flatStyles.strokeDasharray}
134
- rx={flatStyles.borderRadius}
135
- pointer-events="none"
136
- />
137
- {:else}
138
- {@const thickness = Math.max(0, bandwidth - insetLeft - insetRight) + 2}
139
- {@const center = bandStart + insetLeft + (bandwidth - insetLeft - insetRight) / 2}
140
- <rect
141
- class="hover-area"
142
- x={center - thickness / 2}
143
- y={valueMin}
144
- width={thickness}
145
- height={Math.max(0, valueMax - valueMin)}
146
- fill={flatStyles.fill}
147
- fill-opacity={flatStyles.fillOpacity}
148
- stroke={flatStyles.stroke}
149
- stroke-width={flatStyles.strokeWidth}
150
- stroke-opacity={flatStyles.strokeOpacity}
151
- stroke-dasharray={flatStyles.strokeDasharray}
152
- ry={flatStyles.borderRadius}
153
- pointer-events="none"
154
- />
155
- {/if}
106
+ <rect
107
+ class="dct-hit-area"
108
+ x={bandStart + insetLeft}
109
+ y={rangeMin + insetBottom}
110
+ width={Math.max(0, bandwidth - insetLeft - insetRight)}
111
+ height={Math.max(0, rangeMax - rangeMin - insetTop - insetBottom)}
112
+ fill="transparent"
113
+ {...events.forRow(data[0], 0)}
114
+ />
156
115
  {/if}
157
116
  {/if}
158
117
  {/if}
@@ -22,7 +22,7 @@
22
22
  const events = MarkerEvents.use(() => marker);
23
23
 
24
24
  const plot = usePlot();
25
- const isHorizontal = $derived(plot.axes?.isHorizontal ?? false);
25
+ const isHorizontal = $derived(marker.isHorizontal ?? plot.axes?.isHorizontal ?? false);
26
26
  const BollingerMark = $derived(isHorizontal ? BollingerX : BollingerY);
27
27
 
28
28
  const cfg = $derived(getConfiguration());
@@ -19,7 +19,7 @@
19
19
  const events = MarkerEvents.use(() => marker);
20
20
 
21
21
  const plot = usePlot();
22
- const isHorizontal = $derived(plot.axes?.isHorizontal ?? false);
22
+ const isHorizontal = $derived(marker.isHorizontal ?? plot.axes?.isHorizontal ?? false);
23
23
  const BoxMark = $derived(isHorizontal ? BoxX : BoxY);
24
24
 
25
25
  /**
@@ -0,0 +1,11 @@
1
+ import type { BoxScales } from '../../types/markers/labels/box';
2
+ type Dotted = {
3
+ r?: unknown;
4
+ styles?: object;
5
+ };
6
+ /** A dot's radius in pixels, as its marker draws it. */
7
+ export declare class DotRadius {
8
+ /** Its `r`: a number as it is, a channel through the plot's `r` scale; else its `dotRadius`, else `fallback`. */
9
+ static of(marker: Dotted, row: unknown, scales: BoxScales, fallback?: number): number;
10
+ }
11
+ export {};
@@ -0,0 +1,21 @@
1
+ const read = (channel, row) => typeof channel === 'function'
2
+ ? channel(row)
3
+ : typeof channel === 'string' || typeof channel === 'symbol'
4
+ ? row?.[channel]
5
+ : channel;
6
+ /** A dot's radius in pixels, as its marker draws it. */
7
+ export class DotRadius {
8
+ /** Its `r`: a number as it is, a channel through the plot's `r` scale; else its `dotRadius`, else `fallback`. */
9
+ static of(marker, row, scales, fallback = 5) {
10
+ const { r } = marker;
11
+ if (typeof r === 'number')
12
+ return r;
13
+ if (r !== undefined && scales.r) {
14
+ const value = Number(scales.r.fn(read(r, row)));
15
+ if (Number.isFinite(value))
16
+ return value;
17
+ }
18
+ const own = marker.styles?.dotRadius;
19
+ return typeof own === 'number' ? own : fallback;
20
+ }
21
+ }
@@ -1,283 +1,25 @@
1
1
  <script lang="ts">
2
2
  import { usePlot } from '../../layout/plot/usePlot';
3
- import DotMarker from '../dot/DotMarker.svelte';
4
- import TextMarker from '../text/TextMarker.svelte';
5
- import RuleMarker from '../rule/RuleMarker.svelte';
6
- import BarMarker from '../bar/BarMarker.svelte';
7
- import { getConfiguration } from '../../configuration/config.svelte';
8
- import { NumberFormat } from '../../utils/NumberFormat';
9
- import { BandNudge } from '../utils/BandNudge';
10
- import type { BandSlice } from '../../types/layout/hover';
11
- import type { HoverMarkerConfig } from '../../types/markers/common';
3
+ import { PointPixel } from '../utils/PointPixel';
12
4
  import type { HoverDisplayPoint } from '../../types/layout/hover';
13
5
 
14
6
  /**
15
- * In-SVG hover highlight, rendered *inside* a `<Plot>`. Because it positions
16
- * itself through the host plot's scales, it places the same coordinate
17
- * correctly in every facet - that is what makes cross-facet sync work without
18
- * any pixel math. Draws optional x/y crosshair rules plus a dot + value label
19
- * for each matched point.
20
- *
21
- * Takes the raw `marker` config plus the couple of things it can't know on
22
- * its own - `activePoint` (the specific matched point actually under the
23
- * cursor, for the crosshair position; see `controller.svelte.ts`'s own doc
24
- * comment) and whether the active hover strategy implies a crosshair on
25
- * each axis by default - the same "component owns its own rendering"
26
- * pattern `BarMarker`/`RuleMarker` follow. `activePoint`/
27
- * `impliesCrosshairX`/`impliesCrosshairY` are all optional and default to
28
- * "no crosshair".
29
- *
30
- * `areaX`/`areaY` are a separate, always-explicit opt-in (no implied
31
- * default) for a thickened area highlight in place of the thin crosshair -
32
- * see `HoverMarkerConfig`'s own doc comment. Rendered via `BarMarker`'s
33
- * `role: 'highlight'`, so it renders nothing on an axis without a band
34
- * scale (e.g. a line/scatter plot's continuous axis).
7
+ * Where the hover is, rendered *inside* a `<Plot>`: it reports the pixel position of the point under the pointer,
8
+ * through the host plot's scales, so a synced plot's tooltip can sit on it. It draws nothing itself - the
9
+ * `hover` marker's `back` and `front` markers are drawn by `GeometryLayout`, as every other marker.
35
10
  */
36
11
  interface Props {
37
- data?: HoverDisplayPoint[];
38
- /** Narrowed to just the fields this component reads - `HoverMarkerConfig` also carries routing/scoping fields (`series`/`scope`/`strategy`/`sync`) it has no use for. */
39
- marker: Pick<
40
- HoverMarkerConfig,
41
- | 'ruleX'
42
- | 'ruleY'
43
- | 'areaX'
44
- | 'areaY'
45
- | 'showLabels'
46
- | 'format'
47
- | 'rule'
48
- | 'area'
49
- | 'dot'
50
- | 'text'
51
- | 'decimals'
52
- | 'prefix'
53
- | 'suffix'
54
- | 'signDisplay'
55
- >;
56
12
  activePoint?: HoverDisplayPoint | null;
57
- impliesCrosshairX?: boolean;
58
- impliesCrosshairY?: boolean;
59
- /** Reports `activePoint`'s real pixel position within this facet's own box, or `null` when nothing's matched. */
13
+ /** Reports `activePoint`'s pixel position within this facet's own box, or `null` when nothing's matched. */
60
14
  onActivePointPixel?: (pos: { x: number; y: number } | null) => void;
61
15
  }
62
16
 
63
- let {
64
- data = [],
65
- marker,
66
- activePoint = null,
67
- impliesCrosshairX = false,
68
- impliesCrosshairY = false,
69
- onActivePointPixel
70
- }: Props = $props();
71
-
72
- const cfg = $derived(getConfiguration());
17
+ let { activePoint = null, onActivePointPixel }: Props = $props();
73
18
  const plot = usePlot().svelteplot;
74
19
 
75
- /** Scaled pixel position of `value`, centered within its band for a band scale. */
76
- function scaledPixel(
77
- scale: { type?: string; fn?: (v: never) => unknown } | undefined,
78
- value: unknown
79
- ): number | null {
80
- if (!scale?.fn || value == null) return null;
81
- const raw = Number(scale.fn(value as never));
82
- if (!Number.isFinite(raw)) return null;
83
- if (scale.type === 'band') {
84
- const bandwidth = (scale.fn as { bandwidth?: () => number }).bandwidth?.() ?? 0;
85
- return raw + bandwidth / 2;
86
- }
87
- return raw;
88
- }
89
-
90
- const nudgeOf = (point: { areaInset?: BandSlice } | null | undefined) =>
91
- BandNudge.of(plot.scales, point?.areaInset);
92
-
93
- const activePixel = $derived.by((): { x: number; y: number } | null => {
94
- if (!activePoint) return null;
95
- const x = scaledPixel(plot.scales.x, activePoint.x);
96
- const y = scaledPixel(plot.scales.y, activePoint.y);
97
- if (x == null || y == null) return null;
98
- const nudge = nudgeOf(activePoint);
99
- return { x: x + nudge.dx, y: y + nudge.dy };
100
- });
20
+ const activePixel = $derived(activePoint ? PointPixel.of(plot.scales, activePoint) : null);
101
21
 
102
22
  $effect(() => {
103
23
  onActivePointPixel?.(activePixel);
104
24
  });
105
-
106
- const showCrosshairX = $derived(
107
- marker.ruleX !== false && (impliesCrosshairX || marker.ruleX === true)
108
- );
109
- const showCrosshairY = $derived(
110
- marker.ruleY !== false && (impliesCrosshairY || marker.ruleY === true)
111
- );
112
- const ruleX = $derived(showCrosshairX ? (activePoint?.x ?? null) : null);
113
- const ruleY = $derived(showCrosshairY ? (activePoint?.y ?? null) : null);
114
- // areaX/areaY have no implied default - always off unless explicitly set.
115
- const areaX = $derived(marker.areaX === true ? (activePoint?.x ?? null) : null);
116
- const areaY = $derived(marker.areaY === true ? (activePoint?.y ?? null) : null);
117
- /**
118
- * The part of the band an area covers: the active point's own slice (a grouped bar's series), or the whole
119
- * band while the hover matches more than one point in that category, as its dots do.
120
- */
121
- const areaInsetOf = (axis: 'x' | 'y'): BandSlice | undefined => {
122
- const at = activePoint?.[axis];
123
- const key = (value: unknown) => (value instanceof Date ? +value : value);
124
- const shared = data.filter((point) => key(point[axis]) === key(at)).length > 1;
125
- return shared ? undefined : activePoint?.areaInset;
126
- };
127
- const areaInsetX = $derived(areaX != null ? areaInsetOf('x') : undefined);
128
- const areaInsetY = $derived(areaY != null ? areaInsetOf('y') : undefined);
129
- const showLabels = $derived(marker.showLabels ?? true);
130
- const format = $derived(marker.format);
131
- /** The hovered value as the marker's display fields ask; `undefined` while nothing does, so the plot's own label stays. */
132
- const numberOf = $derived(NumberFormat.maybe(NumberFormat.displayOf(marker), cfg));
133
- const number = $derived(numberOf ?? NumberFormat.of(undefined, cfg));
134
- const labelOf = (d: HoverDisplayPoint): string => {
135
- if (format) return format(d, number);
136
- const value = Number(d.label);
137
- return numberOf && d.label !== undefined && d.label !== '' && Number.isFinite(value)
138
- ? numberOf(value)
139
- : (d.label ?? '');
140
- };
141
- const ruleStyle = $derived(marker.rule);
142
- const areaStyle = $derived({ ...cfg.hover.area, ...marker.area });
143
- const dotStyle = $derived(marker.dot);
144
- const fontStyle = $derived(marker.text);
145
-
146
- /** Explicit style wins; otherwise fall back to the point's own resolved color. */
147
- const resolveColor = (explicit: string | undefined, point: HoverDisplayPoint) =>
148
- explicit ?? point.color;
149
-
150
- // Horizontal gap between the dot's edge and an 'outside'-anchored label -
151
- // scales with the dot's own resolved radius so the label clears it.
152
- const dotRadius = $derived(dotStyle?.dotRadius ?? cfg.hover.dot.dotRadius ?? 5);
153
-
154
- /**
155
- * Resolves `text.textAnchor: 'outside'` into a per-point anchor +
156
- * offset, mirroring the value-label `'outside'` anchor's own left/right
157
- * split (see pyramid/bar's own `ValueAnchor` handling): a positive `x`
158
- * anchors `'start'` and nudges right, a negative `x` anchors `'end'` and
159
- * nudges left - so a diverging mark's label sits on the side of the dot
160
- * away from zero, on whichever side that dot itself landed. Only
161
- * meaningful when the point's `x` is numeric (e.g. pyramid's magnitude
162
- * axis); anything else falls through to the plain `text` style unchanged.
163
- *
164
- * Also overrides `cfg.hover.font`'s default `dy: -18` (meant for a label
165
- * floating *above* the dot) back to vertically centered, and clears the
166
- * dot's own radius horizontally instead of the flat default nudge, so the
167
- * label doesn't collide with the dot it's labeling.
168
- */
169
- function resolveFontStyle(point: HoverDisplayPoint) {
170
- if (fontStyle?.textAnchor !== 'outside' || typeof point.x !== 'number') {
171
- return { ...cfg.hover.font, ...fontStyle, fill: resolveColor(fontStyle?.fill, point) };
172
- }
173
- const outward = point.x >= 0;
174
- const gap = dotRadius + 5;
175
- return {
176
- ...cfg.hover.font,
177
- ...fontStyle,
178
- fill: resolveColor(fontStyle?.fill, point),
179
- textAnchor: outward ? ('start' as const) : ('end' as const),
180
- lineAnchor: fontStyle?.lineAnchor ?? ('middle' as const),
181
- dx: fontStyle?.dx ?? (outward ? gap : -gap),
182
- dy: fontStyle?.dy ?? 0
183
- };
184
- }
185
25
  </script>
186
-
187
- {#if areaX != null}
188
- <BarMarker
189
- marker={{
190
- type: 'bar',
191
- role: 'highlight',
192
- isHorizontal: false,
193
- data: [],
194
- category: areaX,
195
- styles: {
196
- ...areaStyle,
197
- insetLeft: areaInsetX?.start,
198
- insetRight: areaInsetX?.end
199
- }
200
- }}
201
- />
202
- {/if}
203
-
204
- {#if areaY != null}
205
- <BarMarker
206
- marker={{
207
- type: 'bar',
208
- role: 'highlight',
209
- isHorizontal: true,
210
- data: [],
211
- category: areaY,
212
- styles: {
213
- ...areaStyle,
214
- insetTop: areaInsetY?.start,
215
- insetBottom: areaInsetY?.end
216
- }
217
- }}
218
- />
219
- {/if}
220
-
221
- {#if ruleX != null}
222
- <g transform="translate({nudgeOf(activePoint).dx}, {nudgeOf(activePoint).dy})">
223
- <RuleMarker
224
- marker={{
225
- type: 'rule',
226
- axis: 'x',
227
- value: ruleX,
228
- styles: { ...cfg.hover.rule, ...ruleStyle }
229
- }}
230
- />
231
- </g>
232
- {/if}
233
-
234
- {#if ruleY != null}
235
- <g transform="translate({nudgeOf(activePoint).dx}, {nudgeOf(activePoint).dy})">
236
- <RuleMarker
237
- marker={{
238
- type: 'rule',
239
- axis: 'y',
240
- value: ruleY,
241
- styles: { ...cfg.hover.rule, ...ruleStyle }
242
- }}
243
- />
244
- </g>
245
- {/if}
246
-
247
- {#if data.length > 0}
248
- {#each data as point (`${point.series ?? ''}_${point.x}_${point.y}`)}
249
- <!-- A grouped bar's point sits in its series' slice of the band (`areaInset`), not at the band's middle. -->
250
- <g transform="translate({nudgeOf(point).dx}, {nudgeOf(point).dy})">
251
- <DotMarker
252
- marker={{
253
- type: 'dot',
254
- data: [point],
255
- x: (d) => d.x,
256
- y: (d) => d.y,
257
- styles: {
258
- ...cfg.hover.dot,
259
- ...dotStyle,
260
- dotFill: resolveColor(dotStyle?.dotFill, point),
261
- dotStroke: resolveColor(dotStyle?.dotStroke, point)
262
- }
263
- }}
264
- />
265
- </g>
266
- {/each}
267
- {#if showLabels}
268
- {#each data as point (`${point.series ?? ''}_${point.x}_${point.y}`)}
269
- <g transform="translate({nudgeOf(point).dx}, {nudgeOf(point).dy})">
270
- <TextMarker
271
- marker={{
272
- type: 'text',
273
- data: [point],
274
- x: (d: HoverDisplayPoint) => d.x,
275
- y: (d: HoverDisplayPoint) => d.y,
276
- text: labelOf,
277
- styles: resolveFontStyle(point)
278
- }}
279
- />
280
- </g>
281
- {/each}
282
- {/if}
283
- {/if}
@@ -1,35 +1,12 @@
1
- import type { HoverMarkerConfig } from '../../types/markers/common';
2
1
  import type { HoverDisplayPoint } from '../../types/layout/hover';
3
2
  /**
4
- * In-SVG hover highlight, rendered *inside* a `<Plot>`. Because it positions
5
- * itself through the host plot's scales, it places the same coordinate
6
- * correctly in every facet - that is what makes cross-facet sync work without
7
- * any pixel math. Draws optional x/y crosshair rules plus a dot + value label
8
- * for each matched point.
9
- *
10
- * Takes the raw `marker` config plus the couple of things it can't know on
11
- * its own - `activePoint` (the specific matched point actually under the
12
- * cursor, for the crosshair position; see `controller.svelte.ts`'s own doc
13
- * comment) and whether the active hover strategy implies a crosshair on
14
- * each axis by default - the same "component owns its own rendering"
15
- * pattern `BarMarker`/`RuleMarker` follow. `activePoint`/
16
- * `impliesCrosshairX`/`impliesCrosshairY` are all optional and default to
17
- * "no crosshair".
18
- *
19
- * `areaX`/`areaY` are a separate, always-explicit opt-in (no implied
20
- * default) for a thickened area highlight in place of the thin crosshair -
21
- * see `HoverMarkerConfig`'s own doc comment. Rendered via `BarMarker`'s
22
- * `role: 'highlight'`, so it renders nothing on an axis without a band
23
- * scale (e.g. a line/scatter plot's continuous axis).
3
+ * Where the hover is, rendered *inside* a `<Plot>`: it reports the pixel position of the point under the pointer,
4
+ * through the host plot's scales, so a synced plot's tooltip can sit on it. It draws nothing itself - the
5
+ * `hover` marker's `back` and `front` markers are drawn by `GeometryLayout`, as every other marker.
24
6
  */
25
7
  interface Props {
26
- data?: HoverDisplayPoint[];
27
- /** Narrowed to just the fields this component reads - `HoverMarkerConfig` also carries routing/scoping fields (`series`/`scope`/`strategy`/`sync`) it has no use for. */
28
- marker: Pick<HoverMarkerConfig, 'ruleX' | 'ruleY' | 'areaX' | 'areaY' | 'showLabels' | 'format' | 'rule' | 'area' | 'dot' | 'text' | 'decimals' | 'prefix' | 'suffix' | 'signDisplay'>;
29
8
  activePoint?: HoverDisplayPoint | null;
30
- impliesCrosshairX?: boolean;
31
- impliesCrosshairY?: boolean;
32
- /** Reports `activePoint`'s real pixel position within this facet's own box, or `null` when nothing's matched. */
9
+ /** Reports `activePoint`'s pixel position within this facet's own box, or `null` when nothing's matched. */
33
10
  onActivePointPixel?: (pos: {
34
11
  x: number;
35
12
  y: number;
@@ -0,0 +1,56 @@
1
+ <script lang="ts">
2
+ import { usePlot } from '../../layout/plot/usePlot';
3
+ import { getConfiguration } from '../../configuration/config.svelte';
4
+ import { CurveGeometry } from './geometry/CurveGeometry';
5
+ import { Box } from '../../layout/margins/Box';
6
+ import type { PathLabelConfig, PathShape } from '../../types/markers/labels/path';
7
+ import type { BoxScales } from '../../types/markers/labels/box';
8
+
9
+ /** Writes one `'path'` label along the curves of a marker: its lines, an area's edge or each dot's rim. */
10
+ const {
11
+ marker,
12
+ label,
13
+ shape
14
+ }: {
15
+ marker: Record<string, unknown>;
16
+ label: PathLabelConfig<string, string>;
17
+ shape: Exclude<PathShape, 'box'>;
18
+ } = $props();
19
+ const plot = usePlot();
20
+ const cfg = $derived(getConfiguration());
21
+ const id = $props.id();
22
+
23
+ const styles = $derived(label.styles ?? {});
24
+ const curves = $derived(
25
+ CurveGeometry.build(shape, marker, label, {
26
+ scales: plot.svelteplot.scales as unknown as BoxScales,
27
+ gap: cfg.text.label.gap,
28
+ measure: (text) => Box.ofText(text, Number(styles.fontSize ?? 11), cfg).width
29
+ })
30
+ );
31
+ // Centred on its curve, a label is drawn over a halo of the background so the curve does not cross it.
32
+ const halo = $derived((label.side ?? '') === 'on' && styles.stroke === undefined);
33
+ /** A style's value for a curve's row: a function of the row, or the value itself. */
34
+ const of = (value: unknown, row: unknown) =>
35
+ (typeof value === 'function' ? value(row) : value) as string | number | undefined;
36
+ </script>
37
+
38
+ {#each curves as curve, i (i)}
39
+ <path id="{id}-{i}" d={curve.d} fill="none" stroke="none" />
40
+ <text
41
+ dy={curve.dy}
42
+ dominant-baseline={curve.baseline}
43
+ text-anchor={curve.textAnchor}
44
+ fill={String(of(styles.fill, curve.row) ?? curve.fill ?? 'currentColor')}
45
+ fill-opacity={of(styles.fillOpacity, curve.row)}
46
+ font-size={styles.fontSize ?? 11}
47
+ font-weight={of(styles.fontWeight, curve.row)}
48
+ font-style={of(styles.fontStyle, curve.row)}
49
+ stroke={halo ? cfg.background : (of(styles.stroke, curve.row) as string | undefined)}
50
+ stroke-width={halo ? 3 : of(styles.strokeWidth, curve.row)}
51
+ paint-order={halo ? 'stroke' : styles.paintOrder}
52
+ pointer-events="none"
53
+ >
54
+ <textPath href="#{id}-{i}" startOffset={curve.startOffset}>{curve.text}</textPath>
55
+ </text>
56
+ {/each}
@@ -0,0 +1,9 @@
1
+ import type { PathLabelConfig, PathShape } from '../../types/markers/labels/path';
2
+ type $$ComponentProps = {
3
+ marker: Record<string, unknown>;
4
+ label: PathLabelConfig<string, string>;
5
+ shape: Exclude<PathShape, 'box'>;
6
+ };
7
+ declare const CurveLabel: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type CurveLabel = ReturnType<typeof CurveLabel>;
9
+ export default CurveLabel;
@@ -0,0 +1,11 @@
1
+ import type { TextMarkerConfig } from '../../types/markers/basic/text';
2
+ /** The label a merged row was written by. */
3
+ export declare const LABEL_SOURCE: unique symbol;
4
+ /**
5
+ * Labels drawn as one `text` marker: those whose other options are alike merge, each row tagged with the label
6
+ * it comes from, so labels from several markers declutter together and draw as one.
7
+ */
8
+ export declare class LabelMerge {
9
+ #private;
10
+ static merge(markers: TextMarkerConfig[]): TextMarkerConfig[];
11
+ }