@fundar/data-chart-telling 1.16.0 → 1.18.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 (330) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/configuration/ConfigVars.svelte +14 -0
  3. package/dist/configuration/ConfigVars.svelte.d.ts +3 -0
  4. package/dist/configuration/config.svelte.d.ts +5 -0
  5. package/dist/configuration/config.svelte.js +20 -6
  6. package/dist/configuration/themes/dark.js +1 -1
  7. package/dist/configuration/themes/editorial.js +1 -1
  8. package/dist/index.d.ts +12 -4
  9. package/dist/index.js +4 -1
  10. package/dist/layout/base/BasePlotLayout.svelte +1 -1
  11. package/dist/layout/figure/Figure.svelte +5 -12
  12. package/dist/layout/figure/FigureChrome.svelte +2 -10
  13. package/dist/layout/geometry/GeometryLayout.svelte +219 -44
  14. package/dist/layout/hover/HoverDefaults.d.ts +52 -0
  15. package/dist/layout/hover/HoverDefaults.js +96 -0
  16. package/dist/layout/hover/HoverLayers.d.ts +35 -0
  17. package/dist/layout/hover/HoverLayers.js +122 -0
  18. package/dist/layout/hover/HoverSettings.js +4 -1
  19. package/dist/layout/hover/HoverShapes.d.ts +44 -0
  20. package/dist/layout/hover/HoverShapes.js +103 -0
  21. package/dist/layout/hover/PlotHover.svelte.d.ts +18 -0
  22. package/dist/layout/hover/PlotHover.svelte.js +54 -1
  23. package/dist/layout/legend/DisabledStyle.d.ts +1 -1
  24. package/dist/layout/legend/DisabledStyle.js +1 -1
  25. package/dist/layout/legend/DiscreteBadgeItem.svelte +1 -1
  26. package/dist/layout/legend/DiscreteSection.svelte +1 -1
  27. package/dist/layout/legend/LegendState.svelte.d.ts +14 -2
  28. package/dist/layout/legend/LegendState.svelte.js +23 -4
  29. package/dist/layout/legend/LegendText.d.ts +4 -1
  30. package/dist/layout/legend/LegendText.js +7 -1
  31. package/dist/layout/margins/PlotMargins.svelte.d.ts +2 -2
  32. package/dist/layout/margins/PlotMargins.svelte.js +2 -2
  33. package/dist/layout/plot/Core.svelte +2 -2
  34. package/dist/layout/plot/Plot.svelte +4 -2
  35. package/dist/layout/plot/Plot.svelte.d.ts +2 -1
  36. package/dist/layout/plot/PublicPlotContext.d.ts +6 -0
  37. package/dist/layout/plot/PublicPlotContext.js +8 -0
  38. package/dist/layout/scales/ScalesLayout.svelte +1 -1
  39. package/dist/layout/styles/ValueLabels.d.ts +43 -4
  40. package/dist/layout/styles/ValueLabels.js +87 -19
  41. package/dist/layout/timeline/Timeline.svelte +5 -1
  42. package/dist/layout/tooltip/TooltipState.svelte.d.ts +8 -9
  43. package/dist/layout/tooltip/TooltipState.svelte.js +28 -29
  44. package/dist/markers/MarkerKinds.d.ts +5 -0
  45. package/dist/markers/MarkerKinds.js +1 -0
  46. package/dist/markers/area/AreaMarker.svelte +3 -0
  47. package/dist/markers/arrow/ArrowMarker.svelte +9 -5
  48. package/dist/markers/band/BandMarker.svelte +74 -0
  49. package/dist/markers/band/BandMarker.svelte.d.ts +7 -0
  50. package/dist/markers/band/Bands.d.ts +16 -0
  51. package/dist/markers/band/Bands.js +48 -0
  52. package/dist/markers/bar/BarMarker.svelte +50 -96
  53. package/dist/markers/bollinger/BollingerMarker.svelte +3 -0
  54. package/dist/markers/box/BoxMarker.svelte +3 -1
  55. package/dist/markers/cell/CellMarker.svelte +11 -7
  56. package/dist/markers/contour/ContourMarker.svelte +3 -0
  57. package/dist/markers/delaunay/DelaunayLinkMarker.svelte +9 -5
  58. package/dist/markers/delaunay/DelaunayMeshMarker.svelte +3 -0
  59. package/dist/markers/density/DensityMarker.svelte +3 -0
  60. package/dist/markers/difference/DifferenceMarker.svelte +3 -0
  61. package/dist/markers/dot/DotMarker.svelte +11 -6
  62. package/dist/markers/geo/GraticuleMarker.svelte +3 -0
  63. package/dist/markers/geo/SphereMarker.svelte +3 -0
  64. package/dist/markers/hover/HoverMarker.svelte +7 -249
  65. package/dist/markers/hover/HoverMarker.svelte.d.ts +4 -27
  66. package/dist/markers/hull/HullMarker.svelte +3 -0
  67. package/dist/markers/image/ImageMarker.svelte +3 -0
  68. package/dist/markers/line/LineMarker.svelte +3 -0
  69. package/dist/markers/link/LinkMarker.svelte +3 -0
  70. package/dist/markers/raster/RasterMarker.svelte +3 -0
  71. package/dist/markers/rect/RectMarker.svelte +25 -17
  72. package/dist/markers/regression/RegressionMarker.svelte +3 -0
  73. package/dist/markers/rule/RuleMarker.svelte +15 -5
  74. package/dist/markers/text/TextFit.d.ts +44 -0
  75. package/dist/markers/text/TextFit.js +86 -0
  76. package/dist/markers/text/TextMarker.svelte +186 -90
  77. package/dist/markers/text/TextMarker.svelte.d.ts +2 -0
  78. package/dist/markers/tick/TickMarker.svelte +9 -3
  79. package/dist/markers/trail/TrailMarker.svelte +3 -0
  80. package/dist/markers/utils/BoxLabel.d.ts +58 -0
  81. package/dist/markers/utils/BoxLabel.js +175 -0
  82. package/dist/markers/utils/MarkerEvents.d.ts +23 -0
  83. package/dist/markers/utils/MarkerEvents.js +44 -0
  84. package/dist/markers/utils/MarkerLabel.svelte +33 -0
  85. package/dist/markers/utils/MarkerLabel.svelte.d.ts +10 -0
  86. package/dist/markers/utils/PointPixel.d.ts +37 -0
  87. package/dist/markers/utils/PointPixel.js +44 -0
  88. package/dist/markers/utils/RowStroke.d.ts +9 -21
  89. package/dist/markers/utils/RowStroke.js +10 -21
  90. package/dist/markers/utils/RowStyle.d.ts +26 -0
  91. package/dist/markers/utils/RowStyle.js +55 -0
  92. package/dist/markers/vector/VectorMarker.svelte +3 -0
  93. package/dist/markers/voronoi/VoronoiMarker.svelte +9 -5
  94. package/dist/markers/voronoi/VoronoiMeshMarker.svelte +3 -0
  95. package/dist/markers/waffle/WaffleMarker.svelte +9 -5
  96. package/dist/phases/Pipeline.d.ts +10 -8
  97. package/dist/phases/Pipeline.js +13 -9
  98. package/dist/phases/context/ContextPhase.d.ts +22 -0
  99. package/dist/phases/context/ContextPhase.js +23 -0
  100. package/dist/phases/context/RowContext.d.ts +35 -0
  101. package/dist/phases/context/RowContext.js +95 -0
  102. package/dist/phases/data/DataPhase.d.ts +4 -4
  103. package/dist/phases/data/DataPhase.js +53 -12
  104. package/dist/phases/hover/HoverPhase.d.ts +6 -7
  105. package/dist/phases/hover/HoverPhase.js +28 -15
  106. package/dist/phases/mapping/MappingPhase.d.ts +4 -4
  107. package/dist/phases/mapping/MappingPhase.js +4 -3
  108. package/dist/phases/markers/MarkerStyles.d.ts +26 -0
  109. package/dist/phases/markers/MarkerStyles.js +126 -0
  110. package/dist/phases/markers/MarkersPhase.d.ts +5 -5
  111. package/dist/phases/markers/MarkersPhase.js +8 -6
  112. package/dist/phases/scales/ScalesPhase.d.ts +4 -4
  113. package/dist/phases/scales/ScalesPhase.js +4 -4
  114. package/dist/phases/sharedScales/SharedScalesPhase.d.ts +2 -2
  115. package/dist/phases/sharedScales/SharedScalesPhase.js +2 -2
  116. package/dist/phases/statistics/MarkerGrouping.d.ts +0 -9
  117. package/dist/phases/statistics/MarkerGrouping.js +0 -16
  118. package/dist/phases/statistics/StatisticsPhase.js +1 -1
  119. package/dist/phases/styles/StylesPhase.d.ts +3 -3
  120. package/dist/phases/styles/StylesPhase.js +2 -2
  121. package/dist/phases/tooltip/TooltipPhase.d.ts +4 -4
  122. package/dist/phases/tooltip/TooltipPhase.js +10 -7
  123. package/dist/phases/transforms/Transforms.js +3 -1
  124. package/dist/phases/transforms/TransformsPhase.d.ts +3 -3
  125. package/dist/phases/transforms/TransformsPhase.js +60 -6
  126. package/dist/phases/transforms/methods/TreemapTransform.d.ts +28 -0
  127. package/dist/phases/transforms/methods/TreemapTransform.js +119 -0
  128. package/dist/plots/correlation/heatmap/defaults.d.ts +2 -2
  129. package/dist/plots/correlation/heatmap/defaults.js +23 -8
  130. package/dist/plots/correlation/heatmap/markers.d.ts +2 -10
  131. package/dist/plots/correlation/heatmap/markers.js +11 -37
  132. package/dist/plots/correlation/scatter/defaults.d.ts +2 -2
  133. package/dist/plots/correlation/scatter/defaults.js +9 -3
  134. package/dist/plots/correlation/scatter/markers.d.ts +3 -3
  135. package/dist/plots/correlation/scatter/markers.js +6 -5
  136. package/dist/plots/distribution/box/BoxSummaries.d.ts +17 -8
  137. package/dist/plots/distribution/box/BoxSummaries.js +90 -40
  138. package/dist/plots/distribution/box/defaults.d.ts +2 -2
  139. package/dist/plots/distribution/box/defaults.js +9 -6
  140. package/dist/plots/distribution/box/markers.d.ts +2 -2
  141. package/dist/plots/distribution/box/markers.js +3 -3
  142. package/dist/plots/distribution/density/defaults.d.ts +2 -2
  143. package/dist/plots/distribution/density/defaults.js +17 -1
  144. package/dist/plots/distribution/density/markers.d.ts +2 -2
  145. package/dist/plots/distribution/density/markers.js +4 -4
  146. package/dist/plots/distribution/histogram/defaults.d.ts +2 -2
  147. package/dist/plots/distribution/histogram/defaults.js +22 -27
  148. package/dist/plots/distribution/histogram/markers.d.ts +3 -12
  149. package/dist/plots/distribution/histogram/markers.js +21 -62
  150. package/dist/plots/distribution/pyramid/defaults.d.ts +2 -2
  151. package/dist/plots/distribution/pyramid/defaults.js +7 -4
  152. package/dist/plots/distribution/pyramid/markers.d.ts +2 -12
  153. package/dist/plots/distribution/pyramid/markers.js +16 -66
  154. package/dist/plots/distribution/violin/defaults.d.ts +2 -2
  155. package/dist/plots/distribution/violin/defaults.js +9 -7
  156. package/dist/plots/distribution/violin/markers.d.ts +2 -2
  157. package/dist/plots/distribution/violin/markers.js +4 -4
  158. package/dist/plots/evolution/area/defaults.d.ts +2 -2
  159. package/dist/plots/evolution/area/defaults.js +1 -1
  160. package/dist/plots/evolution/area/markers.d.ts +2 -2
  161. package/dist/plots/evolution/area/markers.js +4 -4
  162. package/dist/plots/evolution/line/defaults.d.ts +2 -2
  163. package/dist/plots/evolution/line/defaults.js +1 -1
  164. package/dist/plots/evolution/line/markers.d.ts +2 -2
  165. package/dist/plots/evolution/line/markers.js +3 -3
  166. package/dist/plots/evolution/slope/defaults.d.ts +2 -2
  167. package/dist/plots/evolution/slope/defaults.js +8 -4
  168. package/dist/plots/evolution/slope/markers.d.ts +2 -2
  169. package/dist/plots/evolution/slope/markers.js +3 -3
  170. package/dist/plots/evolution/sparkline/defaults.d.ts +2 -2
  171. package/dist/plots/evolution/sparkline/defaults.js +5 -2
  172. package/dist/plots/evolution/sparkline/markers.d.ts +2 -2
  173. package/dist/plots/evolution/sparkline/markers.js +3 -3
  174. package/dist/plots/map/geo/Core.svelte +3 -3
  175. package/dist/plots/map/geo/defaults.d.ts +2 -2
  176. package/dist/plots/map/geo/phases/data.d.ts +1 -1
  177. package/dist/plots/map/geo/phases/data.js +1 -1
  178. package/dist/plots/map/geo/phases/hover.d.ts +2 -2
  179. package/dist/plots/map/geo/phases/hover.js +3 -3
  180. package/dist/plots/map/geo/phases/markers.d.ts +2 -2
  181. package/dist/plots/map/geo/phases/markers.js +5 -4
  182. package/dist/plots/map/geo/phases/scales.d.ts +2 -2
  183. package/dist/plots/map/geo/phases/scales.js +2 -2
  184. package/dist/plots/part-of-a-whole/treemap/Plot.svelte +47 -0
  185. package/dist/plots/part-of-a-whole/treemap/Plot.svelte.d.ts +26 -0
  186. package/dist/plots/part-of-a-whole/treemap/defaults.d.ts +10 -0
  187. package/dist/plots/part-of-a-whole/treemap/defaults.js +183 -0
  188. package/dist/plots/ranking/bar/defaults.d.ts +2 -2
  189. package/dist/plots/ranking/bar/defaults.js +15 -9
  190. package/dist/plots/ranking/bar/markers.d.ts +4 -14
  191. package/dist/plots/ranking/bar/markers.js +45 -86
  192. package/dist/plots/ranking/bullet/defaults.d.ts +2 -2
  193. package/dist/plots/ranking/bullet/defaults.js +4 -4
  194. package/dist/plots/ranking/bullet/markers.d.ts +3 -3
  195. package/dist/plots/ranking/bullet/markers.js +11 -12
  196. package/dist/plots/ranking/cleveland/ClevelandMarkers.d.ts +3 -3
  197. package/dist/plots/ranking/cleveland/ClevelandMarkers.js +28 -23
  198. package/dist/plots/ranking/cleveland/defaults.d.ts +2 -2
  199. package/dist/plots/ranking/cleveland/defaults.js +7 -4
  200. package/dist/plots/ranking/dumbbell/defaults.d.ts +2 -2
  201. package/dist/plots/ranking/forest/defaults.d.ts +2 -2
  202. package/dist/plots/ranking/lollipop/defaults.d.ts +2 -2
  203. package/dist/types/configuration/styling.d.ts +31 -2
  204. package/dist/types/layout/context.d.ts +21 -0
  205. package/dist/types/layout/context.js +1 -0
  206. package/dist/types/layout/hover.d.ts +3 -0
  207. package/dist/types/layout/legend.d.ts +8 -1
  208. package/dist/types/layout/mapping.d.ts +12 -3
  209. package/dist/types/layout/scales.d.ts +6 -0
  210. package/dist/types/layout/styles/values.d.ts +8 -2
  211. package/dist/types/layout/tooltip.d.ts +11 -4
  212. package/dist/types/markers/axis/arrow.d.ts +2 -8
  213. package/dist/types/markers/axis/axisBasedMarkersConfig.d.ts +2 -1
  214. package/dist/types/markers/axis/band.d.ts +24 -0
  215. package/dist/types/markers/axis/band.js +1 -0
  216. package/dist/types/markers/axis/bar.d.ts +6 -10
  217. package/dist/types/markers/axis/cell.d.ts +5 -5
  218. package/dist/types/markers/axis/delaunayLink.d.ts +2 -2
  219. package/dist/types/markers/axis/hover.d.ts +60 -15
  220. package/dist/types/markers/axis/rect.d.ts +4 -8
  221. package/dist/types/markers/axis/rule.d.ts +2 -16
  222. package/dist/types/markers/axis/tick.d.ts +2 -2
  223. package/dist/types/markers/axis/voronoi.d.ts +2 -2
  224. package/dist/types/markers/axis/waffle.d.ts +4 -3
  225. package/dist/types/markers/basic/dot.d.ts +2 -2
  226. package/dist/types/markers/basic/text.d.ts +56 -14
  227. package/dist/types/markers/channels/commonMarkerConfig.d.ts +8 -1
  228. package/dist/types/markers/channels/commonMarkerConfigWithArea.d.ts +1 -2
  229. package/dist/types/markers/channels/commonMarkerConfigWithLabel.d.ts +10 -0
  230. package/dist/types/markers/channels/commonMarkerConfigWithLabel.js +1 -0
  231. package/dist/types/markers/channels/commonMarkerEvents.d.ts +17 -0
  232. package/dist/types/markers/channels/commonMarkerEvents.js +13 -0
  233. package/dist/types/markers/common.d.ts +1 -0
  234. package/dist/types/markers/common.js +1 -0
  235. package/dist/types/markers/geo/contour.d.ts +2 -1
  236. package/dist/types/markers/geo/graticule.d.ts +2 -1
  237. package/dist/types/markers/geo/link.d.ts +2 -1
  238. package/dist/types/markers/geo/sphere.d.ts +2 -1
  239. package/dist/types/markers/geo/vector.d.ts +2 -1
  240. package/dist/types/phases/context/phase.d.ts +7 -0
  241. package/dist/types/phases/context/phase.js +1 -0
  242. package/dist/types/phases/data/phase.d.ts +7 -2
  243. package/dist/types/phases/hover/phase.d.ts +10 -5
  244. package/dist/types/phases/index.d.ts +2 -1
  245. package/dist/types/phases/kind.d.ts +11 -8
  246. package/dist/types/phases/mapping/phase.d.ts +2 -2
  247. package/dist/types/phases/markers/phase.d.ts +3 -3
  248. package/dist/types/phases/scales/phase.d.ts +4 -4
  249. package/dist/types/phases/stage.d.ts +3 -3
  250. package/dist/types/phases/state.d.ts +8 -1
  251. package/dist/types/phases/statistics/phase.d.ts +2 -1
  252. package/dist/types/phases/styles/phase.d.ts +3 -2
  253. package/dist/types/phases/transforms/phase.d.ts +13 -2
  254. package/dist/types/plots/constants.d.ts +17 -19
  255. package/dist/types/plots/correlation/heatmap/props.d.ts +3 -3
  256. package/dist/types/plots/correlation/heatmap/state.d.ts +2 -2
  257. package/dist/types/plots/correlation/scatter/props.d.ts +3 -3
  258. package/dist/types/plots/correlation/scatter/state.d.ts +2 -2
  259. package/dist/types/plots/data/common.d.ts +19 -6
  260. package/dist/types/plots/data/geo.d.ts +1 -1
  261. package/dist/types/plots/distribution/box/props.d.ts +25 -3
  262. package/dist/types/plots/distribution/box/state.d.ts +6 -17
  263. package/dist/types/plots/distribution/density/props.d.ts +3 -11
  264. package/dist/types/plots/distribution/density/state.d.ts +2 -2
  265. package/dist/types/plots/distribution/histogram/props.d.ts +16 -11
  266. package/dist/types/plots/distribution/histogram/state.d.ts +2 -2
  267. package/dist/types/plots/distribution/pyramid/props.d.ts +3 -3
  268. package/dist/types/plots/distribution/pyramid/state.d.ts +2 -2
  269. package/dist/types/plots/distribution/violin/props.d.ts +4 -3
  270. package/dist/types/plots/distribution/violin/state.d.ts +2 -2
  271. package/dist/types/plots/evolution/area/props.d.ts +3 -3
  272. package/dist/types/plots/evolution/area/state.d.ts +2 -2
  273. package/dist/types/plots/evolution/line/props.d.ts +3 -3
  274. package/dist/types/plots/evolution/line/state.d.ts +2 -2
  275. package/dist/types/plots/evolution/slope/state.d.ts +2 -2
  276. package/dist/types/plots/evolution/sparkline/state.d.ts +2 -2
  277. package/dist/types/plots/map/geo/state.d.ts +1 -1
  278. package/dist/types/plots/part-of-a-whole/treemap/props.d.ts +29 -0
  279. package/dist/types/plots/part-of-a-whole/treemap/props.js +1 -0
  280. package/dist/types/plots/part-of-a-whole/treemap/state.d.ts +6 -0
  281. package/dist/types/plots/part-of-a-whole/treemap/state.js +1 -0
  282. package/dist/types/plots/props.d.ts +10 -4
  283. package/dist/types/plots/ranking/bar/props.d.ts +3 -3
  284. package/dist/types/plots/ranking/bar/state.d.ts +2 -2
  285. package/dist/types/plots/ranking/bullet/state.d.ts +2 -2
  286. package/dist/types/plots/ranking/cleveland/props.d.ts +3 -3
  287. package/dist/types/plots/ranking/cleveland/state.d.ts +2 -2
  288. package/dist/types/plots/ranking/dumbbell/props.d.ts +3 -3
  289. package/dist/types/plots/ranking/dumbbell/state.d.ts +2 -2
  290. package/dist/types/plots/ranking/forest/props.d.ts +3 -3
  291. package/dist/types/plots/ranking/forest/state.d.ts +2 -2
  292. package/dist/types/plots/ranking/lollipop/props.d.ts +3 -3
  293. package/dist/types/plots/ranking/lollipop/state.d.ts +2 -2
  294. package/dist/types/plots/styling.d.ts +24 -0
  295. package/dist/types/transforms/index.d.ts +3 -1
  296. package/dist/types/transforms/treemap.d.ts +32 -0
  297. package/dist/types/transforms/treemap.js +5 -0
  298. package/dist/utils/color/ColorTones.d.ts +19 -0
  299. package/dist/utils/color/ColorTones.js +64 -0
  300. package/dist/utils/color/CssColor.d.ts +14 -5
  301. package/dist/utils/color/CssColor.js +69 -27
  302. package/dist/utils/color/index.d.ts +4 -0
  303. package/dist/utils/color/index.js +4 -0
  304. package/dist/utils/grouping.d.ts +18 -1
  305. package/dist/utils/grouping.js +31 -0
  306. package/docs/concepts.md +3 -2
  307. package/docs/legend.md +8 -5
  308. package/docs/markers.md +110 -28
  309. package/docs/plots/evolution/line.md +1 -1
  310. package/docs/plots/evolution/slope.md +1 -1
  311. package/docs/plots/part-of-a-whole/treemap.md +103 -0
  312. package/docs/plots/ranking/bar.md +2 -1
  313. package/docs/plots/ranking/cleveland.md +1 -1
  314. package/docs/plots.md +21 -20
  315. package/docs/scales.md +3 -0
  316. package/docs/state.md +34 -1
  317. package/docs/styles-and-segments.md +20 -19
  318. package/docs/theming.md +6 -12
  319. package/docs/tooltip-and-hover.md +81 -3
  320. package/docs/transforms-and-statistics.md +17 -16
  321. package/examples/LineDates.svelte +1 -1
  322. package/examples/ResponsiveLine.svelte +3 -1
  323. package/examples/Treemap.svelte +13 -0
  324. package/examples/TreemapHover.svelte +25 -0
  325. package/examples/ValueLabels.svelte +1 -1
  326. package/examples/datasets/economic-activity.ts +40 -0
  327. package/examples/datasets/index.ts +1 -0
  328. package/llms-full.txt +11 -9
  329. package/llms.txt +4 -1
  330. package/package.json +3 -1
@@ -0,0 +1,175 @@
1
+ const read = (edge) => (row) => typeof edge === 'function'
2
+ ? edge(row)
3
+ : typeof edge === 'string' || typeof edge === 'symbol'
4
+ ? row?.[edge]
5
+ : edge;
6
+ /** The middle of two positions along an axis, whether numbers or dates. */
7
+ const middle = (from, to) => from instanceof Date || to instanceof Date
8
+ ? new Date((Number(from) + Number(to)) / 2)
9
+ : (Number(from) + Number(to)) / 2;
10
+ const bandwidth = (scale) => scale?.type === 'band' ? Number(scale.fn.bandwidth()) : undefined;
11
+ const distance = (scale, from, to) => scale ? Math.abs(Number(scale.fn(to)) - Number(scale.fn(from))) : undefined;
12
+ /**
13
+ * How a marker that draws a box per row writes a label in each: the `text` marker for them, centred on the box,
14
+ * and where the box is for it to fit to. A `rect` says it with its edges, a `cell` is a band of each axis, and a bar
15
+ * or a waffle is a band of its category axis and the stretch of its value.
16
+ */
17
+ export class BoxLabel {
18
+ /** `undefined` when the marker has no label, or does not say where its boxes are. */
19
+ static of(marker, plot = {}) {
20
+ if (!marker.label)
21
+ return undefined;
22
+ const own = BoxLabel.#shape(marker, plot.isHorizontal ?? marker.isHorizontal ?? false);
23
+ if (!own)
24
+ return undefined;
25
+ const { anchor, outside, gap, ...label } = marker.label;
26
+ const size = typeof own.box === 'function' ? own.box : own.size;
27
+ const placed = BoxLabel.#anchored({
28
+ anchor,
29
+ outside,
30
+ gap: gap ?? plot.gap
31
+ }, label, size, plot.scales);
32
+ return {
33
+ box: own.box,
34
+ marker: {
35
+ // A label outside its shape has nothing to fit to.
36
+ fit: !outside,
37
+ ...label,
38
+ ...placed,
39
+ type: 'text',
40
+ data: marker.data,
41
+ x: own.x,
42
+ y: own.y
43
+ }
44
+ };
45
+ }
46
+ /**
47
+ * What puts a label at `anchor` of its shape: the pixels it is moved from the middle - a function of the row, for
48
+ * the size of its shape is the row's own - and the sides of its point it is written on. `{}` for the middle.
49
+ */
50
+ static #anchored(where, label, size, scales) {
51
+ const { anchor = 'middle', outside = false } = where;
52
+ if (anchor === 'middle' || !size)
53
+ return {};
54
+ const gap = where.gap ?? 4;
55
+ const horizontal = anchor.endsWith('left') ? -1 : anchor.endsWith('right') ? 1 : 0;
56
+ const vertical = anchor.startsWith('top') ? -1 : anchor.startsWith('bottom') ? 1 : 0;
57
+ // Beyond an edge only means something for an edge: a corner is inside its shape.
58
+ const beyond = outside && horizontal * vertical === 0;
59
+ const away = beyond ? 1 : -1;
60
+ const move = (axis, side, row) => {
61
+ // Read when a label is drawn, not when its marker is made: the scales move as the labels register.
62
+ const current = scales?.();
63
+ const box = current ? size(row, current) : undefined;
64
+ return box ? side * (box[axis] / 2 + away * gap) : 0;
65
+ };
66
+ // A number of the label's own (or its styles') is added to the move: it is the push from the anchor.
67
+ const own = (value, fallback) => Number(typeof value === 'number' ? value : (fallback ?? 0));
68
+ const baseX = own(label.dx, label.styles?.dx);
69
+ const baseY = own(label.dy, label.styles?.dy);
70
+ return {
71
+ dx: horizontal === 0 ? label.dx : (row) => baseX + move('width', horizontal, row),
72
+ dy: vertical === 0 ? label.dy : (row) => baseY + move('height', vertical, row),
73
+ styles: {
74
+ ...label.styles,
75
+ textAnchor: label.styles?.textAnchor ??
76
+ (horizontal === 0 ? 'middle' : (horizontal === 1) === beyond ? 'start' : 'end'),
77
+ lineAnchor: label.styles?.lineAnchor ??
78
+ (vertical === 0 ? 'middle' : (vertical === 1) === beyond ? 'top' : 'bottom')
79
+ }
80
+ };
81
+ }
82
+ /** A style of the marker, when it is a number: a function of the row says nothing of a box in general. */
83
+ static #style(marker, name) {
84
+ const value = marker.styles?.[name];
85
+ return typeof value === 'number' ? value : undefined;
86
+ }
87
+ static #shape(marker, isHorizontal) {
88
+ if (marker.type === 'cell')
89
+ return BoxLabel.#cell(marker);
90
+ if (marker.type === 'bar') {
91
+ return marker.role === 'segment'
92
+ ? BoxLabel.#bar(marker, marker.isHorizontal ?? false)
93
+ : undefined;
94
+ }
95
+ if (marker.type === 'waffle')
96
+ return BoxLabel.#bar(marker, isHorizontal);
97
+ return BoxLabel.#edges(marker);
98
+ }
99
+ /** A rectangle: the box is between its edges. */
100
+ static #edges({ x, y, x1, x2, y1, y2 }) {
101
+ // A side with a value and no start, next to one with both its edges, runs from zero to it, as a bar does.
102
+ if (y1 === undefined &&
103
+ y2 === undefined &&
104
+ y !== undefined &&
105
+ x1 !== undefined &&
106
+ x2 !== undefined) {
107
+ [y1, y2] = [0, y];
108
+ }
109
+ if (x1 === undefined &&
110
+ x2 === undefined &&
111
+ x !== undefined &&
112
+ y1 !== undefined &&
113
+ y2 !== undefined) {
114
+ [x1, x2] = [0, x];
115
+ }
116
+ if ([x1, x2, y1, y2].some((edge) => edge === undefined))
117
+ return undefined;
118
+ const [left, right, top, bottom] = [x1, x2, y1, y2].map(read);
119
+ const size = (row, scales) => {
120
+ const [width, height] = [
121
+ distance(scales.x, left(row), right(row)),
122
+ distance(scales.y, top(row), bottom(row))
123
+ ];
124
+ return width === undefined || height === undefined ? undefined : { width, height };
125
+ };
126
+ return {
127
+ box: { x1, x2, y1, y2 },
128
+ size,
129
+ x: (row) => middle(left(row), right(row)),
130
+ y: (row) => middle(top(row), bottom(row))
131
+ };
132
+ }
133
+ /** A cell: a band of each axis, less its inset. */
134
+ static #cell(marker) {
135
+ if (marker.x === undefined || marker.y === undefined)
136
+ return undefined;
137
+ const inset = Number(BoxLabel.#style(marker, 'inset') ?? 0.5);
138
+ const box = (_, scales) => {
139
+ const [width, height] = [bandwidth(scales.x), bandwidth(scales.y)];
140
+ return width === undefined || height === undefined
141
+ ? undefined
142
+ : { width: width - 2 * inset, height: height - 2 * inset };
143
+ };
144
+ return { box: box, x: marker.x, y: marker.y };
145
+ }
146
+ /** A bar or a waffle: a band of the category axis, as wide as its insets leave it, and as long as its value. */
147
+ static #bar(marker, isHorizontal) {
148
+ const [category, from, to] = isHorizontal
149
+ ? [marker.y, marker.x1, marker.x2]
150
+ : [marker.x, marker.y1, marker.y2];
151
+ const value = isHorizontal ? marker.x : marker.y;
152
+ // Without both ends, the bar runs from zero to its value.
153
+ const [start, end] = from !== undefined && to !== undefined ? [from, to] : [0, value];
154
+ if (category === undefined || end === undefined)
155
+ return undefined;
156
+ const [first, last] = [start, end].map(read);
157
+ const [before, after] = isHorizontal
158
+ ? [BoxLabel.#style(marker, 'insetTop'), BoxLabel.#style(marker, 'insetBottom')]
159
+ : [BoxLabel.#style(marker, 'insetLeft'), BoxLabel.#style(marker, 'insetRight')];
160
+ const middleOf = (row) => middle(first(row), last(row));
161
+ const box = (row, scales) => {
162
+ const band = bandwidth(isHorizontal ? scales.y : scales.x);
163
+ const length = distance(isHorizontal ? scales.x : scales.y, first(row), last(row));
164
+ if (band === undefined || length === undefined)
165
+ return undefined;
166
+ const thickness = marker.thickness ?? band * (1 - Number(before ?? 0) - Number(after ?? 0));
167
+ return isHorizontal
168
+ ? { width: length, height: thickness }
169
+ : { width: thickness, height: length };
170
+ };
171
+ return isHorizontal
172
+ ? { box: box, x: middleOf, y: category }
173
+ : { box: box, x: category, y: middleOf };
174
+ }
175
+ }
@@ -0,0 +1,23 @@
1
+ import type { CommonMarkerEvents, MarkEventHandler, MarkEventName } from '../../types/markers/channels/commonMarkerEvents';
2
+ /** What svelteplot's marks are given for a marker's events. */
3
+ export type MarkerEventProps = Partial<Record<MarkEventName, MarkEventHandler>>;
4
+ /**
5
+ * The events of a marker, as the props of the svelteplot mark that draws it: the handlers it is given
6
+ * (`onclick`, `onpointerenter`...). Every marker takes them from `CommonMarkerConfig`, so each one only has to
7
+ * spread {@link MarkerEvents.props} on its mark.
8
+ */
9
+ export declare class MarkerEvents {
10
+ #private;
11
+ private constructor();
12
+ /** The events of the marker `marker` reads. */
13
+ static use(marker: () => CommonMarkerEvents): MarkerEvents;
14
+ /** Whether the marker has a handler for any event. */
15
+ get any(): boolean;
16
+ /**
17
+ * The handlers as DOM listeners of the shape drawn for `row` (the `index`-th), for a marker that draws
18
+ * its shapes itself rather than through a svelteplot mark that wires them up.
19
+ */
20
+ forRow(row: unknown, index: number): Partial<Record<MarkEventName, (event: Event) => void>>;
21
+ /** The props to spread on the marker's svelteplot mark. Read in the template, so it follows the marker. */
22
+ get props(): MarkerEventProps;
23
+ }
@@ -0,0 +1,44 @@
1
+ import { MARK_EVENTS } from '../../types/markers/channels/commonMarkerEvents';
2
+ /**
3
+ * The events of a marker, as the props of the svelteplot mark that draws it: the handlers it is given
4
+ * (`onclick`, `onpointerenter`...). Every marker takes them from `CommonMarkerConfig`, so each one only has to
5
+ * spread {@link MarkerEvents.props} on its mark.
6
+ */
7
+ export class MarkerEvents {
8
+ #marker;
9
+ constructor(marker) {
10
+ this.#marker = marker;
11
+ }
12
+ /** The events of the marker `marker` reads. */
13
+ static use(marker) {
14
+ return new MarkerEvents(marker);
15
+ }
16
+ /** Whether the marker has a handler for any event. */
17
+ get any() {
18
+ const marker = this.#marker();
19
+ return MARK_EVENTS.some((name) => !!marker[name]);
20
+ }
21
+ /**
22
+ * The handlers as DOM listeners of the shape drawn for `row` (the `index`-th), for a marker that draws
23
+ * its shapes itself rather than through a svelteplot mark that wires them up.
24
+ */
25
+ forRow(row, index) {
26
+ const marker = this.#marker();
27
+ const own = {};
28
+ for (const name of MARK_EVENTS) {
29
+ const handler = marker[name];
30
+ if (handler)
31
+ own[name] = (event) => handler(event, row, index);
32
+ }
33
+ return own;
34
+ }
35
+ /** The props to spread on the marker's svelteplot mark. Read in the template, so it follows the marker. */
36
+ get props() {
37
+ const marker = this.#marker();
38
+ const own = {};
39
+ for (const name of MARK_EVENTS)
40
+ if (marker[name])
41
+ own[name] = marker[name];
42
+ return own;
43
+ }
44
+ }
@@ -0,0 +1,33 @@
1
+ <script lang="ts">
2
+ import TextMarker from '../text/TextMarker.svelte';
3
+ import { getConfiguration } from '../../configuration/config.svelte';
4
+ import { usePlot } from '../../layout/plot/usePlot';
5
+ import { BoxLabel, type Labelled } from './BoxLabel';
6
+ import { MARK_EVENTS } from '../../types/markers/channels/commonMarkerEvents';
7
+ import type { TextLabelConfig } from '../../types/markers/basic/text';
8
+
9
+ /**
10
+ * The `label` of a marker that draws a box per row: a `text` marker anchored in each box and fitted to it. A marker
11
+ * with a label only has to render `<MarkerLabel {marker} />` after its own shapes. Nothing is drawn without a
12
+ * `label`, or when the marker does not say where its boxes are.
13
+ */
14
+ const { marker }: { marker: Labelled & { label?: TextLabelConfig } } = $props();
15
+ const plot = usePlot();
16
+ const cfg = $derived(getConfiguration());
17
+
18
+ const labelled = $derived(
19
+ BoxLabel.of(marker, {
20
+ isHorizontal: plot.axes?.isHorizontal,
21
+ gap: cfg.text.label.gap,
22
+ scales: () => plot.svelteplot.scales as never
23
+ })
24
+ );
25
+ /** A label with a handler of its own listens for the pointer; one without leaves it to the shape under it. */
26
+ const listens = $derived(MARK_EVENTS.some((name) => !!marker.label?.[name]));
27
+ </script>
28
+
29
+ {#if labelled}
30
+ <g pointer-events={listens ? undefined : 'none'}>
31
+ <TextMarker marker={labelled.marker} box={labelled.box} />
32
+ </g>
33
+ {/if}
@@ -0,0 +1,10 @@
1
+ import { type Labelled } from './BoxLabel';
2
+ import type { TextLabelConfig } from '../../types/markers/basic/text';
3
+ type $$ComponentProps = {
4
+ marker: Labelled & {
5
+ label?: TextLabelConfig;
6
+ };
7
+ };
8
+ declare const MarkerLabel: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type MarkerLabel = ReturnType<typeof MarkerLabel>;
10
+ export default MarkerLabel;
@@ -0,0 +1,37 @@
1
+ import type { BandSlice } from '../../types/layout/hover';
2
+ type Scale = {
3
+ type?: string;
4
+ fn?: (value: never) => unknown;
5
+ } | undefined;
6
+ /** Where a point is drawn, in pixels of its plot: its `x` and `y` through the plot's scales. */
7
+ export declare class PointPixel {
8
+ #private;
9
+ /**
10
+ * `point`'s pixel position - the middle of its band on a band scale, of its slice when it has one (a grouped
11
+ * bar's series) - or `null` when a scale cannot place it.
12
+ */
13
+ static of(scales: {
14
+ x?: Scale;
15
+ y?: Scale;
16
+ }, point: {
17
+ x: unknown;
18
+ y: unknown;
19
+ areaInset?: BandSlice;
20
+ }): {
21
+ x: number;
22
+ y: number;
23
+ } | null;
24
+ /** The index of the one of `points` nearest `cursor`, or `-1` when none can be placed. */
25
+ static nearest(scales: {
26
+ x?: Scale;
27
+ y?: Scale;
28
+ }, points: readonly {
29
+ x: unknown;
30
+ y: unknown;
31
+ areaInset?: BandSlice;
32
+ }[], cursor: {
33
+ x: number;
34
+ y: number;
35
+ }): number;
36
+ }
37
+ export {};
@@ -0,0 +1,44 @@
1
+ import { BandNudge } from './BandNudge';
2
+ /** Where a point is drawn, in pixels of its plot: its `x` and `y` through the plot's scales. */
3
+ export class PointPixel {
4
+ /**
5
+ * `point`'s pixel position - the middle of its band on a band scale, of its slice when it has one (a grouped
6
+ * bar's series) - or `null` when a scale cannot place it.
7
+ */
8
+ static of(scales, point) {
9
+ const x = PointPixel.#along(scales.x, point.x);
10
+ const y = PointPixel.#along(scales.y, point.y);
11
+ if (x == null || y == null)
12
+ return null;
13
+ const nudge = BandNudge.of(scales, point.areaInset);
14
+ return { x: x + nudge.dx, y: y + nudge.dy };
15
+ }
16
+ /** The index of the one of `points` nearest `cursor`, or `-1` when none can be placed. */
17
+ static nearest(scales, points, cursor) {
18
+ let best = -1;
19
+ let bestDistance = Infinity;
20
+ points.forEach((point, index) => {
21
+ const pixel = PointPixel.of(scales, point);
22
+ if (!pixel)
23
+ return;
24
+ const distance = Math.hypot(pixel.x - cursor.x, pixel.y - cursor.y);
25
+ if (distance < bestDistance) {
26
+ best = index;
27
+ bestDistance = distance;
28
+ }
29
+ });
30
+ return best;
31
+ }
32
+ /** `value`'s pixel along one scale, in the middle of its band on a band scale. */
33
+ static #along(scale, value) {
34
+ if (!scale?.fn || value == null)
35
+ return null;
36
+ const raw = Number(scale.fn(value));
37
+ if (!Number.isFinite(raw))
38
+ return null;
39
+ if (scale.type !== 'band')
40
+ return raw;
41
+ const bandwidth = scale.fn.bandwidth?.() ?? 0;
42
+ return raw + bandwidth / 2;
43
+ }
44
+ }
@@ -1,31 +1,19 @@
1
- import type { StrokeStyle } from '../../types/plots/styling';
2
- /** A stroke channel per row: a field key of the row, or a function of it. */
3
- type RowChannel<T> = string | ((d: never) => T) | undefined;
1
+ import type { PerRow, StrokeStyle } from '../../types/plots/styling';
4
2
  /**
5
- * The stroke of a line-like marker that takes it row by row (a `rule`, an
6
- * `arrow`): each of `stroke`, `strokeWidth` and `strokeOpacity` is a field of
7
- * the row or a function of it, else the marker's own `styles`, else a default.
8
- * A color and an opacity per row are drawn as they are - svelteplot would map
9
- * them through its own color and opacity scales.
3
+ * The stroke of a line-like marker that takes it row by row (a `rule`, an `arrow`): each of
4
+ * `stroke`, `strokeWidth` and `strokeOpacity` in the marker's `styles` is a value or a function of
5
+ * the row, else a default. A color and an opacity per row are drawn as they are - svelteplot would
6
+ * map them through its own color and opacity scales.
10
7
  */
11
8
  export declare class RowStroke {
12
- #private;
13
- /** The props a mark takes for `channels`, over `styles` and the given `fallback`s. */
14
- static of(channels: {
15
- stroke?: RowChannel<string | undefined>;
16
- strokeWidth?: RowChannel<number>;
17
- strokeOpacity?: RowChannel<number>;
18
- }, styles: StrokeStyle | undefined, fallback: {
9
+ /** The props a mark takes for `styles`, over the given `fallback`s; `rows` are what a string in `styles` can name a field of. */
10
+ static of(styles: PerRow<StrokeStyle> | undefined, rows: readonly unknown[], fallback: {
19
11
  stroke: string;
20
12
  strokeWidth?: number;
21
13
  strokeOpacity?: number;
22
14
  }): {
23
- stroke: string | {
24
- value: (d: Record<string, unknown>) => string | undefined;
25
- scale: null;
26
- };
27
- strokeWidth: number | ((d: Record<string, unknown>) => number) | undefined;
15
+ stroke: string;
16
+ strokeWidth: number | undefined;
28
17
  strokeOpacity: never;
29
18
  };
30
19
  }
31
- export {};
@@ -1,28 +1,17 @@
1
+ import { RowStyle } from './RowStyle';
1
2
  /**
2
- * The stroke of a line-like marker that takes it row by row (a `rule`, an
3
- * `arrow`): each of `stroke`, `strokeWidth` and `strokeOpacity` is a field of
4
- * the row or a function of it, else the marker's own `styles`, else a default.
5
- * A color and an opacity per row are drawn as they are - svelteplot would map
6
- * them through its own color and opacity scales.
3
+ * The stroke of a line-like marker that takes it row by row (a `rule`, an `arrow`): each of
4
+ * `stroke`, `strokeWidth` and `strokeOpacity` in the marker's `styles` is a value or a function of
5
+ * the row, else a default. A color and an opacity per row are drawn as they are - svelteplot would
6
+ * map them through its own color and opacity scales.
7
7
  */
8
8
  export class RowStroke {
9
- /** A per-row channel as the function svelteplot reads. */
10
- static #accessor(channel) {
11
- return typeof channel === 'string'
12
- ? (d) => d[channel]
13
- : channel;
14
- }
15
- /** The props a mark takes for `channels`, over `styles` and the given `fallback`s. */
16
- static of(channels, styles, fallback) {
17
- const color = RowStroke.#accessor(channels.stroke);
18
- const width = RowStroke.#accessor(channels.strokeWidth);
19
- const opacity = RowStroke.#accessor(channels.strokeOpacity);
9
+ /** The props a mark takes for `styles`, over the given `fallback`s; `rows` are what a string in `styles` can name a field of. */
10
+ static of(styles, rows, fallback) {
20
11
  return {
21
- stroke: color ? { value: color, scale: null } : (styles?.stroke ?? fallback.stroke),
22
- strokeWidth: width ?? styles?.strokeWidth ?? fallback.strokeWidth,
23
- strokeOpacity: (opacity
24
- ? { value: opacity, scale: null }
25
- : (styles?.strokeOpacity ?? fallback.strokeOpacity))
12
+ stroke: RowStyle.of(styles?.stroke, rows) ?? fallback.stroke,
13
+ strokeWidth: RowStyle.field(styles?.strokeWidth) ?? fallback.strokeWidth,
14
+ strokeOpacity: (RowStyle.opacity(styles?.strokeOpacity) ?? fallback.strokeOpacity)
26
15
  };
27
16
  }
28
17
  }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * A marker's style as svelteplot reads it. A style that depends on the row is handed over as the
3
+ * value of a channel with no scale: svelteplot would otherwise map what it gives through its own
4
+ * color or opacity scale, and a row's opacity of 0.55 would no longer be 0.55.
5
+ */
6
+ export declare class RowStyle {
7
+ #private;
8
+ /**
9
+ * A color, as a prop of a mark: a function of the row is a channel with no scale; a string is the
10
+ * field of the rows it names (when they have one of that name), else the color itself.
11
+ */
12
+ static of<T>(style: T | ((row: never) => T) | undefined, rows?: readonly unknown[]): T | undefined;
13
+ /**
14
+ * The color each row is drawn with, as {@link of} reads `style`: a function of the row, the field of the rows a
15
+ * string names, else the color itself. `undefined` when there is no color to read.
16
+ */
17
+ static colorOf(style: unknown, rows?: readonly unknown[]): ((row: unknown) => string | undefined) | undefined;
18
+ /** An opacity: a number as it is, a string the field of the rows it names, a function of the row; the last two with no scale. */
19
+ static opacity(style: number | string | ((row: never) => number) | undefined): number | undefined;
20
+ /** Any other number (a width, a radius, an inset): a string is the field of the rows it names, a function is called with the row. */
21
+ static field<T>(style: T | string | ((row: never) => T) | undefined): T | undefined;
22
+ /** \`styles\` without its functions - for a shape that stands for no row (a hover band), where there is nothing to call them with. */
23
+ static flat<TStyle extends object>(styles: TStyle | undefined): {
24
+ [K in keyof TStyle]?: Exclude<TStyle[K], (...args: never[]) => unknown>;
25
+ };
26
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * A marker's style as svelteplot reads it. A style that depends on the row is handed over as the
3
+ * value of a channel with no scale: svelteplot would otherwise map what it gives through its own
4
+ * color or opacity scale, and a row's opacity of 0.55 would no longer be 0.55.
5
+ */
6
+ export class RowStyle {
7
+ /** The accessor that reads `key` off a row. */
8
+ static #read = (key) => (row) => row?.[key];
9
+ /**
10
+ * A color, as a prop of a mark: a function of the row is a channel with no scale; a string is the
11
+ * field of the rows it names (when they have one of that name), else the color itself.
12
+ */
13
+ static of(style, rows) {
14
+ if (typeof style === 'function')
15
+ return { value: style, scale: null };
16
+ if (typeof style === 'string' && RowStyle.#isField(style, rows))
17
+ return { value: RowStyle.#read(style), scale: null };
18
+ return style;
19
+ }
20
+ /**
21
+ * The color each row is drawn with, as {@link of} reads `style`: a function of the row, the field of the rows a
22
+ * string names, else the color itself. `undefined` when there is no color to read.
23
+ */
24
+ static colorOf(style, rows) {
25
+ if (typeof style === 'function')
26
+ return (row) => style(row);
27
+ if (typeof style !== 'string')
28
+ return undefined;
29
+ if (RowStyle.#isField(style, rows)) {
30
+ const read = RowStyle.#read(style);
31
+ return (row) => read(row);
32
+ }
33
+ return () => style;
34
+ }
35
+ /** An opacity: a number as it is, a string the field of the rows it names, a function of the row; the last two with no scale. */
36
+ static opacity(style) {
37
+ if (typeof style === 'function')
38
+ return { value: style, scale: null };
39
+ if (typeof style === 'string')
40
+ return { value: RowStyle.#read(style), scale: null };
41
+ return style;
42
+ }
43
+ /** Any other number (a width, a radius, an inset): a string is the field of the rows it names, a function is called with the row. */
44
+ static field(style) {
45
+ return (typeof style === 'string' ? RowStyle.#read(style) : style);
46
+ }
47
+ /** Whether a string names a field of the rows - at least one has it - rather than being a color. */
48
+ static #isField(name, rows) {
49
+ return !!rows?.some((row) => typeof row === 'object' && row !== null && name in row);
50
+ }
51
+ /** \`styles\` without its functions - for a shape that stands for no row (a hover band), where there is nothing to call them with. */
52
+ static flat(styles) {
53
+ return Object.fromEntries(Object.entries(styles ?? {}).filter(([, value]) => typeof value !== 'function'));
54
+ }
55
+ }
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import { MarkerEvents } from '../utils/MarkerEvents';
2
3
  import { Vector } from 'svelteplot';
3
4
  import type { GeoVectorMarkerConfig } from '../../types/markers/geo';
4
5
 
@@ -10,12 +11,14 @@
10
11
  * shape actually draws with, matching svelteplot's own convention.
11
12
  */
12
13
  let { marker }: { marker: GeoVectorMarkerConfig } = $props();
14
+ const events = MarkerEvents.use(() => marker);
13
15
 
14
16
  const shape = $derived(marker.shape ?? 'arrow-filled');
15
17
  const isFilledShape = $derived(shape === 'arrow-filled');
16
18
  </script>
17
19
 
18
20
  <Vector
21
+ {...events.props}
19
22
  data={marker.data}
20
23
  x={marker.x}
21
24
  y={marker.y}
@@ -1,4 +1,6 @@
1
1
  <script lang="ts">
2
+ import { RowStyle } from '../utils/RowStyle';
3
+ import { MarkerEvents } from '../utils/MarkerEvents';
2
4
  import { Voronoi } from 'svelteplot';
3
5
  import { MarkerChannels } from '../utils/MarkerChannels';
4
6
  import { getConfiguration } from '../../configuration/config.svelte';
@@ -6,6 +8,7 @@
6
8
 
7
9
  /** Renders one `'voronoi'` marker as `<Voronoi>` - one Voronoi cell per point. */
8
10
  let { marker }: { marker: VoronoiMarkerConfig } = $props();
11
+ const events = MarkerEvents.use(() => marker);
9
12
 
10
13
  const cfg = $derived(getConfiguration());
11
14
  const data = $derived(marker.data ?? []);
@@ -13,14 +16,15 @@
13
16
  </script>
14
17
 
15
18
  <Voronoi
19
+ {...events.props}
16
20
  {data}
17
21
  x={marker.x}
18
22
  y={marker.y}
19
23
  z={marker.grouping}
20
- fill={marker.styles?.fill}
21
- fillOpacity={marker.styles?.fillOpacity}
22
- stroke={marker.styles?.stroke ?? channelColor}
23
- strokeWidth={marker.styles?.strokeWidth}
24
- strokeOpacity={marker.styles?.strokeOpacity}
24
+ fill={RowStyle.of(marker.styles?.fill, data)}
25
+ fillOpacity={RowStyle.opacity(marker.styles?.fillOpacity)}
26
+ stroke={RowStyle.of(marker.styles?.stroke, data) ?? channelColor}
27
+ strokeWidth={RowStyle.field(marker.styles?.strokeWidth)}
28
+ strokeOpacity={RowStyle.opacity(marker.styles?.strokeOpacity)}
25
29
  strokeDasharray={marker.styles?.strokeDasharray}
26
30
  />
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import { MarkerEvents } from '../utils/MarkerEvents';
2
3
  import { VoronoiMesh } from 'svelteplot';
3
4
  import { MarkerChannels } from '../utils/MarkerChannels';
4
5
  import { getConfiguration } from '../../configuration/config.svelte';
@@ -6,6 +7,7 @@
6
7
 
7
8
  /** Renders one `'voronoiMesh'` marker as `<VoronoiMesh>` - the Voronoi diagram as a single mesh. */
8
9
  let { marker }: { marker: VoronoiMeshMarkerConfig } = $props();
10
+ const events = MarkerEvents.use(() => marker);
9
11
 
10
12
  const cfg = $derived(getConfiguration());
11
13
  const data = $derived(marker.data ?? []);
@@ -13,6 +15,7 @@
13
15
  </script>
14
16
 
15
17
  <VoronoiMesh
18
+ {...events.props}
16
19
  {data}
17
20
  x={marker.x}
18
21
  y={marker.y}
@@ -1,4 +1,6 @@
1
1
  <script lang="ts">
2
+ import { RowStyle } from '../utils/RowStyle';
3
+ import { MarkerEvents } from '../utils/MarkerEvents';
2
4
  import { WaffleX, WaffleY } from 'svelteplot';
3
5
  import { usePlot } from '../../layout/plot/usePlot';
4
6
  import { MarkerChannels } from '../utils/MarkerChannels';
@@ -7,6 +9,7 @@
7
9
 
8
10
  /** Renders one `'waffle'` marker as `<WaffleX>` or `<WaffleY>`, picked from the way the plot runs (`usePlot().axes`). */
9
11
  let { marker }: { marker: WaffleMarkerConfig } = $props();
12
+ const events = MarkerEvents.use(() => marker);
10
13
 
11
14
  const plot = usePlot();
12
15
  const isHorizontal = $derived(plot.axes?.isHorizontal ?? false);
@@ -19,6 +22,7 @@
19
22
  </script>
20
23
 
21
24
  <WaffleMark
25
+ {...events.props}
22
26
  {data}
23
27
  x={marker.x}
24
28
  y={marker.y}
@@ -27,10 +31,10 @@
27
31
  multiple={marker.multiple}
28
32
  gap={marker.gap}
29
33
  round={marker.round}
30
- borderRadius={marker.styles?.borderRadius}
34
+ borderRadius={RowStyle.field(marker.styles?.borderRadius)}
31
35
  {fill}
32
- fillOpacity={marker.styles?.fillOpacity}
33
- stroke={marker.styles?.stroke}
34
- strokeWidth={marker.styles?.strokeWidth}
35
- strokeOpacity={marker.styles?.strokeOpacity}
36
+ fillOpacity={RowStyle.opacity(marker.styles?.fillOpacity)}
37
+ stroke={RowStyle.of(marker.styles?.stroke, data)}
38
+ strokeWidth={RowStyle.field(marker.styles?.strokeWidth)}
39
+ strokeOpacity={RowStyle.opacity(marker.styles?.strokeOpacity)}
36
40
  />